flowardΒ·vibes
Home / 03 β€” Dockerfile 2 min read

03 β€” Dockerfile

What it is: a recipe that tells Docker how to package your application into a container image. Location: dockerfiles/Dockerfile

Rules

  • Use a small, official Linux base image:

    • Node.js β†’ node:20-alpine
    • Python β†’ python:3.12-slim
    • Java β†’ eclipse-temurin:21-jre-alpine
  • Target platform is linux/amd64. On Apple Silicon (M-series) Macs, test with docker build --platform linux/amd64 … β€” an image that builds as arm64 locally can still fail on the amd64 cluster.

  • Use a multi-stage build: install/build dependencies in a builder stage, copy only what's needed into a lean final stage.

  • The app must not run as root inside the container, and the final USER must be a numeric UID (e.g. USER 10001:10001). Kubernetes' runAsNonRoot check can only verify numeric users β€” a named user (USER appuser) makes the pod fail to start with "container has runAsNonRoot and image has non-numeric user".

  • No passwords, API keys, or .env files baked into the image. Also add .env to dockerfiles/.dockerignore so it can never leak in via COPY.

  • Must build successfully from the repo root with:

    docker build -f dockerfiles/Dockerfile -t myapp:latest .
    

Example β€” Node.js

Note: COPY paths start with source/ because the build context is the repo root (the dependency manifest lives in source/, per guide 02).

# syntax=docker/dockerfile:1

# Stage 1: install production dependencies
FROM node:20-alpine AS builder
WORKDIR /app
COPY source/package*.json ./
RUN npm ci --omit=dev

# Stage 2: lean final image
FROM node:20-alpine
# Numeric UID/GID so Kubernetes' runAsNonRoot can verify the user
RUN addgroup -S -g 10001 appgroup && adduser -S -u 10001 -G appgroup appuser
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY source/ ./
USER 10001:10001
EXPOSE 3000
CMD ["node", "server.js"]

(npm ci --only=production is deprecated in npm 8+; use --omit=dev. npm ci requires source/package-lock.json to be committed.)

Example β€” Python

# syntax=docker/dockerfile:1

FROM python:3.12-slim AS builder
WORKDIR /app
COPY source/requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

FROM python:3.12-slim
# Numeric UID so Kubernetes' runAsNonRoot can verify the user
RUN useradd -m -u 10001 appuser
WORKDIR /app
COPY --from=builder /install /usr/local
COPY source/ ./
USER 10001
EXPOSE 8000
CMD ["python", "app.py"]

.dockerignore

Create dockerfiles/.dockerignore (used automatically when building with -f dockerfiles/Dockerfile on Docker β‰₯ 19.03 as dockerfiles/Dockerfile.dockerignore, otherwise place it at repo root β€” safest is repo root and keeping secrets out entirely):

node_modules
.git
.env
*.env
__pycache__
dist
target

Prompt tip

"Write a production-ready multi-stage Dockerfile in dockerfiles/Dockerfile. The build context is the repository root and the app code is in source/. Use a non-root user. Do not copy any .env files or secrets into the image. Target linux/amd64."