Dockerfiles
Chapter 05: Dockerfiles
Section titled “Chapter 05: Dockerfiles”Dockerfiles are text files containing instructions to build Docker images. This chapter covers writing effective Dockerfiles.
Dockerfile Basics
Section titled “Dockerfile Basics”A Dockerfile is a script with instructions to build an image:
# CommentFROM ubuntu:20.04LABEL maintainer="you@example.com"RUN apt-get update && apt-get install -y nginxCOPY index.html /var/www/html/EXPOSE 80CMD ["nginx", "-g", "daemon off;"]Dockerfile Instructions
Section titled “Dockerfile Instructions”Sets the base image:
# Use official base imageFROM node:18-alpineFROM python:3.11-slim
# Use specific versionFROM nginx:1.25
# Multi-stage build - first stageFROM node:18 AS builderAdd metadata to the image:
LABEL version="1.0"LABEL description="My web application"LABEL maintainer="you@example.com"LABEL "org.opencontainers.image.authors"="you@example.com"Execute commands during build:
# Shell formRUN apt-get update && apt-get install -y nginx
# Exec form (preferred)RUN ["apt-get", "update"]RUN ["apt-get", "install", "-y", "nginx"]Copy files from build context to image:
# Copy single fileCOPY index.html /var/www/html/
# Copy directoryCOPY src/ /var/www/html/src/
# Copy with ownershipCOPY --chown=www-data:www-data . /var/www/html/Similar to COPY but with additional features:
# Copy and extract tar filesADD website.tar.gz /var/www/html/
# Copy from URLADD https://example.com/file.tar.gz /tmp/Best Practice: Use COPY unless you need ADD’s features.
WORKDIR
Section titled “WORKDIR”Set the working directory:
WORKDIR /appWORKDIR /var/logWORKDIR /workspaceSet environment variables:
ENV NODE_ENV=productionENV PORT=8080ENV DATABASE_URL=postgres://user:pass@db:5432/mydbEXPOSE
Section titled “EXPOSE”Document which ports the container listens on:
EXPOSE 80EXPOSE 443EXPOSE 8080 8081 8082Set the user for subsequent commands:
# Create userRUN addgroup -g 1000 appgroup && adduser -u 1000 -G appgroup -s /bin/sh -D appuser
# Switch to userUSER appuserDefine build-time variables:
ARG VERSION=latestARG BUILD_DATE
# Use ARGRUN echo "Building version $VERSION"ENTRYPOINT
Section titled “ENTRYPOINT”Configure the command that always executes:
# Exec formENTRYPOINT ["python", "app.py"]
# Shell formENTRYPOINT python app.pyDefine the default command:
# Exec form (preferred)CMD ["nginx", "-g", "daemon off;"]
# Shell formCMD nginx -g "daemon off;"
# Default arguments for ENTRYPOINTCMD ["--port", "8080"]Dockerfile Best Practices
Section titled “Dockerfile Best Practices”1. Use Specific Base Images
Section titled “1. Use Specific Base Images”# BadFROM ubuntu
# GoodFROM ubuntu:20.04
# Better - Alpine basedFROM node:18-alpine2. Use .dockerignore
Section titled “2. Use .dockerignore”.gitnode_modulesnpm-debug.log.env*.md__pycache__*.pyc.vscode.idea3. Order Instructions for Caching
Section titled “3. Order Instructions for Caching”# Bad - invalidates cache for every code changeCOPY . .RUN npm installFROM node:18
# Good - cache npm install unless package.json changesFROM node:18WORKDIR /appCOPY package*.json ./RUN npm installCOPY . .4. Use Multi-stage Builds
Section titled “4. Use Multi-stage Builds”# Build stageFROM node:18 AS builderWORKDIR /appCOPY package*.json ./RUN npm installCOPY . .RUN npm run build
# Production stageFROM node:18-alpineWORKDIR /appCOPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesCMD ["node", "dist/index.js"]5. Minimize Layers
Section titled “5. Minimize Layers”# Bad - multiple RUN layersRUN apt-get updateRUN apt-get install -y nginxRUN apt-get cleanRUN rm -rf /var/lib/apt/lists/*
# Good - single RUN layerRUN apt-get update && \ apt-get install -y nginx && \ apt-get clean && \ rm -rf /var/lib/apt/lists/*6. Don’t Run as Root
Section titled “6. Don’t Run as Root”# Create non-root userRUN addgroup -g 1000 appgroup && \ adduser -u 1000 -G appgroup -s /bin/sh -D appuser
# Set ownershipRUN chown -R appuser:appgroup /app
USER appuser7. Use Health Checks
Section titled “7. Use Health Checks”HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000/health || exit 18. Use Labels for Metadata
Section titled “8. Use Labels for Metadata”LABEL maintainer="you@example.com"LABEL version="1.0.0"LABEL description="My application"Dockerfile Examples
Section titled “Dockerfile Examples”Node.js Application
Section titled “Node.js Application”# Build stageFROM node:18-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ci --only=productionCOPY . .RUN npm run build
# Production stageFROM node:18-alpineWORKDIR /appRUN addgroup -g 1000 -S nodejs && \ adduser -u 1000 -S nodejs -G nodejsCOPY --from=builder --chown=nodejs:nodejs /app/dist ./distCOPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modulesUSER nodejsEXPOSE 3000CMD ["node", "dist/index.js"]Python Application
Section titled “Python Application”FROM python:3.11-slim
WORKDIR /app
# Install dependenciesCOPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txt
# Copy applicationCOPY . .
# Create non-root userRUN useradd -m -u 1000 appuser && \ chown -R appuser:appuser /appUSER appuser
EXPOSE 8000CMD ["python", "main.py"]Go Application
Section titled “Go Application”# Build stageFROM golang:1.21-alpine AS builderWORKDIR /appCOPY go.mod go.sum ./RUN go mod downloadCOPY . .RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
# Production stageFROM alpine:latestRUN apk --no-cache add ca-certificatesWORKDIR /appCOPY --from=builder /app/main .EXPOSE 8080CMD ["./main"]Building Images
Section titled “Building Images”# Build with default tagdocker build .
# Build with custom tagdocker build -t myapp:latest .
# Build with build argsdocker build --build-arg VERSION=1.0 -t myapp:1.0 .
# Build with no cachedocker build --no-cache -t myapp:latest .
# Build with target stage (multi-stage)docker build --target builder -t myapp:builder .
# Build and pass secrets (for RUN --mount=type=cache)docker build --secret id=npm,src=.npmrc -t myapp .Dockerfile Validation
Section titled “Dockerfile Validation”# Lint Dockerfiledocker build --check .
# Hadolint (external tool)hadolint DockerfileDockerfile Syntax Highlighting
Section titled “Dockerfile Syntax Highlighting”Most editors support Dockerfile syntax highlighting:
- VS Code: Docker extension
- IntelliJ: Docker plugin
- Sublime: Dockerfile syntax
Summary
Section titled “Summary”In this chapter, you learned:
- Dockerfile instructions (FROM, RUN, COPY, etc.)
- Best practices for writing efficient Dockerfiles
- Multi-stage builds
- Security best practices
- Building images from Dockerfiles