Docker 27: What Developers Need to Know
Docker 27 is the latest stable release with significant improvements: BuildKit is the default builder (faster, more efficient layer caching), Compose v2 is integrated into the Docker CLI (docker compose instead of docker-compose), and containerd is the default runtime.
As a developer, Docker solves the "it works on my machine" problem by packaging your application with ALL its dependencies into a standardized container. The container runs identically on your laptop, CI server, staging, and production.
The key concepts: a Dockerfile defines how to build an image. An image is a read-only template. A container is a running instance of an image. A volume persists data outside the container lifecycle. A network connects containers.
Key Takeaways
Writing Efficient Dockerfiles
A Dockerfile defines the steps to build your image. The order of instructions matters enormously for build speed: Docker caches each layer, and changing one layer invalidates all subsequent layers. Put things that change rarely (OS packages, dependencies) first, and things that change often (your code) last.
The biggest mistake: copying all source code before installing dependencies. This means every code change re-installs all packages. Instead, copy only package.json first, install dependencies, then copy source code.
For production images: use slim/alpine base images (90% smaller), run as non-root user, and set explicit WORKDIR.
# ❌ BAD: Code change invalidates dependency cache FROM node:22 WORKDIR /app COPY . . # Code change → re-installs ALL deps! RUN npm install CMD ["node", "dist/server.js"] # ✅ GOOD: Dependencies cached separately from source FROM node:22-slim AS builder WORKDIR /app # 1. Copy dependency files FIRST (rarely change) COPY package.json pnpm-lock.yaml ./ RUN corepack enable && pnpm install --frozen-lockfile # 2. Copy source code AFTER dependencies (frequently change) COPY . . RUN pnpm build # 3. Production stage — minimal image FROM node:22-slim WORKDIR /app # Security: run as non-root user RUN groupadd -r appuser && useradd -r -g appuser appuser # Copy only production artifacts COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./ # Set non-root user USER appuser # Health check HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ CMD node -e "fetch('http://localhost:3000/health').then(r => r.ok ? process.exit(0) : process.exit(1))" EXPOSE 3000 CMD ["node", "dist/server.js"]
Key Takeaways
Docker Compose v2: Multi-Service Development
Docker Compose v2 defines and runs multi-container applications. A single compose.yaml file describes your entire development stack: app server, database, cache, message broker — all started with one command.
Compose v2 is integrated into the Docker CLI (docker compose instead of docker-compose). It supports profiles (enable/disable services), watch mode (hot reload on file changes), and GPU access.
# compose.yaml — Full development stack services: app: build: context: . target: builder # Use the builder stage for dev (includes dev deps) ports: - "3000:3000" volumes: - .:/app # Hot reload: mount source code - /app/node_modules # Don't override container's node_modules environment: - DATABASE_URL=postgresql://postgres:secret@db:5432/inkdb - REDIS_URL=redis://cache:6379 depends_on: db: condition: service_healthy cache: condition: service_started develop: watch: - action: sync path: ./src target: /app/src - action: rebuild path: ./package.json db: image: postgres:17 environment: POSTGRES_DB: inkdb POSTGRES_PASSWORD: secret volumes: - pgdata:/var/lib/postgresql/data ports: - "5432:5432" healthcheck: test: pg_isready -U postgres interval: 5s timeout: 3s retries: 5 cache: image: redis:8-alpine ports: - "6379:6379" volumes: - redisdata:/data volumes: pgdata: redisdata:
Key Takeaways
Security Scanning & Hardening
Container security is a critical production concern. Docker Scout (built into Docker 27) scans your images for known CVEs (Common Vulnerabilities and Exposures) in base images and dependencies. Run it in CI to block deployments with critical vulnerabilities.
Beyond scanning: use distroless or Alpine base images (fewer attack vectors), never run as root, use read-only file systems where possible, and set resource limits to prevent container escape via resource exhaustion.
# Scan for vulnerabilities docker scout cves myapp:latest docker scout recommendations myapp:latest # .dockerignore — Never copy these into the image .git .env node_modules *.log .DS_Store tests/ docs/ # Production hardening in compose.yaml services: app: image: myapp:latest read_only: true # Read-only filesystem tmpfs: - /tmp # Writable temp directory security_opt: - no-new-privileges # Prevent privilege escalation deploy: resources: limits: cpus: '1.0' memory: 512M reservations: cpus: '0.25' memory: 128M
Key Takeaways
Key Takeaways
Docker is the foundation of modern deployment. Master Dockerfiles (layer caching, multi-stage builds), Compose (multi-service development), and security (scanning, non-root, read-only) to build production-ready containers.
For interviews: explain how layer caching works, demonstrate a multi-stage build, discuss the difference between COPY and ADD, explain why containers should run as non-root, and describe how Compose dependencies with health checks prevent race conditions.