diff --git a/ingest-go/Dockerfile b/ingest-go/Dockerfile new file mode 100644 index 00000000..17e91cd4 --- /dev/null +++ b/ingest-go/Dockerfile @@ -0,0 +1,40 @@ +# ============================================================================= +# Stage 1: Build - Compile Go binary +# ============================================================================= +FROM golang:1.22-alpine AS builder + +WORKDIR /app + +# Copy modules manifests +COPY go.mod ./ + +# Download dependencies +RUN go mod download + +# Copy source code +COPY main.go ./ + +# Compile Go binary statically with optimizations +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o ingest-go main.go + +# ============================================================================= +# Stage 2: Production Runtime - Minimal final image +# ============================================================================= +FROM alpine:3.19 AS production + +# Create non-root user for security +RUN addgroup -g 1001 -S appgroup && \ + adduser -S appuser -u 1001 -G appgroup + +WORKDIR /app + +# Copy compiled binary from builder +COPY --from=builder --chown=appuser:appgroup /app/ingest-go ./ingest-go + +# Switch to non-root user +USER appuser + +EXPOSE 3002 + +# Run Go application +CMD ["./ingest-go"] diff --git a/ingest-node/.dockerignore b/ingest-node/.dockerignore new file mode 100644 index 00000000..b763d823 --- /dev/null +++ b/ingest-node/.dockerignore @@ -0,0 +1,3 @@ +node_modules +dist +Dockerfile diff --git a/ingest-node/Dockerfile b/ingest-node/Dockerfile new file mode 100644 index 00000000..0bc47352 --- /dev/null +++ b/ingest-node/Dockerfile @@ -0,0 +1,51 @@ +# ============================================================================= +# Stage 1: Build - Compile TypeScript +# ============================================================================= +FROM node:20-alpine AS builder +WORKDIR /app +COPY package*.json tsconfig.json ./ +RUN npm ci +COPY src/ ./src/ +RUN npm run build + +# ============================================================================= +# Stage 2: Dependencies - Install ONLY production modules +# ============================================================================= +FROM node:20-alpine AS deps +WORKDIR /app +COPY package*.json ./ +RUN npm ci --omit=dev --ignore-scripts && \ + npm cache clean --force + +# ============================================================================= +# Stage 3: Production Runtime - Minimal final image +# ============================================================================= +FROM node:20-alpine AS production +ENV NODE_ENV=production + +# Create non-root user for security +RUN addgroup -g 1001 -S nodejs && \ + adduser -S nodejs -u 1001 + +WORKDIR /app + +# Copy ONLY what is strictly necessary from the previous stages +COPY --from=deps --chown=nodejs:nodejs /app/node_modules ./node_modules +COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist +COPY --from=builder --chown=nodejs:nodejs /app/package.json ./ + +# Manually remove npm and yarn binaries +RUN rm -rf /usr/local/lib/node_modules/npm \ + && rm -rf /usr/local/bin/npm \ + && rm -rf /usr/local/bin/npx \ + && rm -rf /opt/yarn-* \ + && rm -rf /usr/local/bin/yarn \ + && rm -rf /usr/local/bin/yarnpkg + +# Switch to non-root user +USER nodejs + +EXPOSE 3001 + +# Direct node execution (no npm start wrapper) +CMD ["node", "dist/index.js"]