Claude Code for Docker and DevOps: Containers, Compose, and CI/CD — Claude Skills 360 Blog
Blog / Development / Claude Code for Docker and DevOps: Containers, Compose, and CI/CD
Development

Claude Code for Docker and DevOps: Containers, Compose, and CI/CD

Published: May 3, 2026
Read time: 9 min read
By: Claude Skills 360

Dockerfile debugging is tedious. Layer caching, multi-stage builds, Alpine vs Debian, security scanning, Compose networking — each has its own footguns. Claude Code handles Docker and DevOps tasks well, especially the debugging and optimization work that requires deep knowledge of how the daemon processes layers.

This guide covers using Claude Code for container work: writing production Dockerfiles, debugging build failures, multi-service Compose stacks, and integrating containers into CI/CD.

Dockerfiles: Writing Production-Grade Ones

The difference between a working Dockerfile and a good Dockerfile is significant — image size, build time, security, and layer cache efficiency. Claude Code produces good ones when you give it the right constraints.

Write a production Dockerfile for a Node.js 22 app.
Requirements:
- Multi-stage build (build stage + runtime stage)
- Final image as small as possible
- Non-root user
- Proper layer caching (dependencies install before code copy)
- Health check
- The app runs with: npm start (listens on PORT env var, default 3000)

Claude generates:

# Build stage
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# Runtime stage
FROM node:22-alpine AS runtime
WORKDIR /app

# Non-root user
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodeuser -u 1001 -G nodejs

# Copy built assets with correct ownership
COPY --from=builder --chown=nodeuser:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodeuser:nodejs /app/dist ./dist
COPY --from=builder --chown=nodeuser:nodejs /app/package.json ./

USER nodeuser

ENV PORT=3000
EXPOSE $PORT

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget -qO- http://localhost:$PORT/health || exit 1

CMD ["npm", "start"]

Key things Claude includes without being asked: --only=production to skip devDependencies in the final image, non-root user creation with proper GID/UID, --chown flag on COPY for secure file ownership, and health check with appropriate timing.

Debugging Docker Build Failures

Docker build errors can be cryptic. Show Claude the full error:

My Docker build is failing with:
"npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /home/node/.npm"
Here's my Dockerfile: [paste]

Claude identifies that the error is a permissions issue — the npm cache directory isn’t writable by the non-root user. It adds the fix: ENV NPM_CONFIG_CACHE=/tmp/npm-cache before the npm commands, or creates the cache directory with proper permissions.

Layer Cache Invalidation

My Docker builds take 8 minutes every time even though I only changed one 
source file. Here's my Dockerfile: [paste]

Claude spots the cache-busting pattern — usually COPY . . before RUN npm install, which means any file change invalidates the npm install cache. It reorders to: COPY package.json, install dependencies, then COPY source code.

Alpine vs Debian Issues

My build works with node:22 but fails with node:22-alpine.
Error: gyp ERR! find Python Python is not set

Claude explains that Alpine uses musl libc, which breaks native modules that depend on Python for compilation or expect glibc. It offers solutions in order of preference: use a pre-compiled version of the package, use a Debian-slim base image (node:22-slim), or install build tools in Alpine (apk add python3 make g++).

Docker Compose for Development

Claude Code writes complete Compose stacks that actually work:

Create a docker-compose.yml for local development.
Services: Next.js app, PostgreSQL 16, Redis 7, and Mailhog for email testing.
The app should hot-reload on code changes.
Postgres and Redis data should persist between restarts.
The app needs these env vars: DATABASE_URL, REDIS_URL, SMTP_HOST.
# Generated by Claude — connects all services correctly
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - .:/app
      - /app/node_modules  # Anonymous volume prevents host node_modules override
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://postgres:postgres@db:5432/myapp_dev
      REDIS_URL: redis://redis:6379
      SMTP_HOST: mailhog
      SMTP_PORT: 1025
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: myapp_dev
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
    ports:
      - "5432:5432"

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
    ports:
      - "6379:6379"

  mailhog:
    image: mailhog/mailhog
    ports:
      - "1025:1025"   # SMTP
      - "8025:8025"   # Web UI

volumes:
  postgres_data:
  redis_data:

Claude includes the depends_on condition check (so the app waits for Postgres to actually be ready, not just started) and the anonymous volume trick for node_modules (prevents the host’s node_modules from overriding the container’s).

Compose Networking

My frontend (port 3000) can't connect to my API (port 8000) in Docker Compose.
Both services are running but the frontend gets "connection refused."
Here's my Compose file: [paste]

Claude diagnoses Compose networking: services on the same Compose network communicate via service name, not localhost. The fix: change http://localhost:8000 to http://api:8000 (using the service name). It explains the Docker DNS resolution so you understand the pattern, not just the fix.

Multi-Stage Builds for Different Environments

I need three stages: dev (with hot reload), test (runs test suite), 
and prod (optimized, no dev tools).
All three should share the same base and dependency install.

Claude generates a properly layered multi-stage Dockerfile:

FROM node:22-alpine AS base
WORKDIR /app
COPY package*.json ./

FROM base AS deps
RUN npm ci

FROM deps AS development
COPY . .
CMD ["npm", "run", "dev"]

FROM deps AS test
COPY . .
RUN npm test

FROM deps AS builder
COPY . .
RUN npm run build

FROM node:22-alpine AS production
WORKDIR /app
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
USER appuser
CMD ["node", "dist/main.js"]

The FROM deps AS ... pattern lets each stage inherit the installed dependencies without reinstalling them.

Integrating with CI/CD

For Docker and GitHub Actions together, see the CI/CD guide. The key pattern Claude generates:

Add a GitHub Actions workflow that:
1. Builds the Docker image on every push to main
2. Runs the test stage
3. If tests pass, pushes to GitHub Container Registry
4. Tags with: latest, and the git SHA

Claude generates the full workflow with proper Docker layer caching (using cache-from/cache-to with GitHub Actions cache), GHCR authentication, and correct tagging strategy.

Security: Scanning and Hardening

Audit this Dockerfile for security issues.
[paste Dockerfile]

Claude reviews for common issues:

  • Running as root (add non-root user)
  • COPY . . including sensitive files (add .dockerignore)
  • Outdated base image (specific tag, not latest)
  • Exposed unnecessary ports
  • Secrets baked into image (should be runtime env vars, never build args for secrets)
  • Missing --no-cache on package manager installs

For actively maintained production images, Claude also suggests adding Trivy or Grype scanning to the CI pipeline.

Docker + Claude Code: Common Patterns

.dockerignore Generation

Generate a .dockerignore for a Node.js project.
Include: development files, test artifacts, secrets, large binaries.

Claude generates a comprehensive .dockerignorenode_modules, .env*, *.test.*, .git, coverage/, dist/ (from build stage perspective), IDE config files.

Kubernetes Manifests

Convert this Docker Compose service to a Kubernetes Deployment + Service.
The app needs: 3 replicas, resource limits, readiness and liveness probes,
and the database URL from a Secret.

Claude writes the Deployment with proper resources.requests/resources.limits, readiness and liveness probes matching the health check from the Dockerfile, and envFrom.secretRef for the database URL. It generates the Service as ClusterIP unless you specify LoadBalancer or NodePort.

Working with Claude Code and Docker Day-to-Day

The most effective pattern: have your CLAUDE.md include your containerization standards.

## Containerization
- Base images: node:22-alpine, python:3.12-slim, golang:1.23-alpine
- Always multi-stage builds — final image should be minimal
- Non-root user required in all production images
- Health checks required on all services
- Secrets via environment variables only — never baked into images
- Local dev: Docker Compose in docker-compose.dev.yml

With this in CLAUDE.md, every Dockerfile Claude generates follows your standards without being asked. This is covered in the CLAUDE.md guide.

For automating container operations — like triggering a rebuild when files change — Claude Code hooks can watch for file changes and run docker compose up --build automatically.

The Automation Stack

Claude Code handles Docker tasks at a qualitatively higher level than inline autocomplete because it can:

  • Read the existing Dockerfile and understand the build context
  • Run docker build and see the actual error output
  • Read the source code to understand what the container needs
  • Fix and rebuild in sequence

This is especially powerful for debugging complex multi-service stacks where the issue often spans multiple config files. If you’re doing serious DevOps work, combining Claude Code with DevOps-specific skills from Claude Skills 360 gives you a ready-made library of deployment, monitoring, and infrastructure patterns.

Start with the free tier to see how Claude Code handles your specific Docker and deployment workflows before committing.

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free