docker-helper
Build, debug, and optimize Docker configurations. Use when a user asks to create a Dockerfile, fix Docker build errors, optimize image size, write docker-compose files, debug container issues, set up multi-stage builds, or troubleshoot networking between containers. Covers Dockerfile best practices and compose orchestration.
Usage
Getting Started
- Install the skill using the command above
- Open your AI coding agent (Claude Code, Codex, Gemini CLI, or Cursor)
- Reference the skill in your prompt
- The AI will use the skill's capabilities automatically
Example Prompts
- "Deploy the latest build to the staging environment and run smoke tests"
- "Check the CI pipeline status and summarize any recent failures"
Documentation
Overview
Create, debug, and optimize Docker configurations including Dockerfiles, docker-compose setups, and container troubleshooting. Follows Docker best practices for security, image size, and build speed.
Instructions
When a user asks for help with Docker, determine which task they need:
Task A: Create a Dockerfile
- Identify the application language and framework
- Choose the right base image (prefer
-slimor-alpinevariants) - Use multi-stage builds for compiled languages
- Follow this ordering for optimal layer caching:
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Stage 2: Runtime
FROM node:20-alpine
WORKDIR /app
RUN addgroup -g 1001 appgroup && adduser -u 1001 -G appgroup -D appuser
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
USER appuser
EXPOSE 3000
CMD ["node", "dist/index.js"]
Key rules:
- Copy dependency files first, then source (caching)
- Run as non-root user
- Use
.dockerignoreto excludenode_modules,.git,.env - Pin base image versions (e.g.,
node:20.11-alpine, notnode:latest) - Combine RUN commands to reduce layers
Task B: Write docker-compose.yml
version: "3.8"
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/myapp
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: myapp
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
interval: 5s
timeout: 5s
retries: 5
volumes:
pgdata:
Key rules:
- Use
depends_onwith health checks, not just service names - Use named volumes for persistent data
- Never hardcode secrets in compose files for production (use env files or secrets)
- Set restart policies
Task C: Debug container issues
Follow this diagnostic sequence:
# 1. Check container status
docker ps -a
# 2. Read container logs
docker logs <container> --tail 50
# 3. Inspect container details
docker inspect <container> | jq '.[0].State'
# 4. Check resource usage
docker stats --no-stream
# 5. Get a shell inside the container
docker exec -it <container> /bin/sh
# 6. Check networking
docker network ls
docker network inspect <network>
Common issues and fixes:
- Container exits immediately: Check logs; usually a missing env var or config file
- Port already in use:
lsof -i :PORTto find the conflict - Cannot connect between containers: Ensure they are on the same Docker network and use service names as hostnames
- Out of disk space:
docker system prune -ato clean up unused images and containers - Build fails at COPY: Check
.dockerignoreand verify paths are relative to build context
Task D: Optimize image size
# Check current image size
docker images | grep myapp
# Analyze layers
docker history myapp:latest
Optimization checklist:
- Switch to alpine base images
- Use multi-stage builds (build deps stay in builder stage)
- Combine RUN commands with
&& - Remove package manager caches:
rm -rf /var/cache/apk/* - Use
.dockerignoreto exclude test files, docs, .git - Do not install dev dependencies in the final image
Examples
Example 1: Create a Dockerfile for a Python FastAPI app
User request: "Create a Dockerfile for my FastAPI project"
Output Dockerfile:
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
RUN useradd -r -s /bin/false appuser
COPY --from=builder /install /usr/local
COPY . .
USER appuser
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Output .dockerignore:
__pycache__
*.pyc
.git
.env
.venv
tests/
*.md
Result: Image size ~180MB instead of ~1.2GB with the full Python image.
Example 2: Debug a container that keeps restarting
User request: "My web container keeps restarting, can you help?"
Diagnostic steps:
$ docker ps -a
CONTAINER ID IMAGE STATUS NAMES
a1b2c3d4e5f6 web:1.0 Restarting (1) 5 sec ago web
$ docker logs web --tail 20
Error: ECONNREFUSED 127.0.0.1:5432
at TCPConnectWrap.afterConnect
Root cause: The app is trying to connect to PostgreSQL at 127.0.0.1,
but in Docker the database is a separate container.
Fix: Change DATABASE_URL from localhost to the service name:
DATABASE_URL=postgres://user:pass@db:5432/myapp
^^ service name, not localhost
Guidelines
- Always create a
.dockerignorealongside any Dockerfile. - Pin base image versions to specific tags, not
latest. - Never store secrets in Docker images or Dockerfiles. Use environment variables or Docker secrets.
- For production, always run as a non-root user.
- When optimizing, measure before and after with
docker images. - If a build is slow, check layer ordering. Dependencies (package.json, requirements.txt) should be copied and installed before source code.
- For local development, use bind mounts for live reloading. For production, use COPY.
- Health checks should test actual application readiness, not just process existence.
Information
- Version
- 1.0.0
- Author
- terminal-skills
- Category
- DevOps
- License
- Apache-2.0