docker-helper
Docker Helper
Dockerfile Best Practices
Layer Caching and .dockerignore
Order instructions from least to most frequently changing. Copy dependency manifests before source code.
FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "server.js"]
Always include a .dockerignore to reduce build context and prevent secret leaks:
node_modules
.git
.env
*.log
dist
__pycache__
.venv
Health Checks
HEALTHCHECK \
CMD wget -qO- http://localhost:3000/health || exit 1
Image Management
docker build -t myapp:latest .
docker build -t myapp:v1.2 -f Dockerfile.prod --build-arg NODE_ENV=production .
docker build --no-cache -t myapp:latest .
docker tag myapp:latest registry.example.com/myapp:v1.2
docker push registry.example.com/myapp:v1.2
docker pull registry.example.com/myapp:v1.2
docker images
docker images --filter "dangling=true"
docker image ls --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
docker history myapp:latest
docker rmi myapp:latest
docker image prune -a
Container Lifecycle
# Run (create + start)
docker run -d --name myapp -p 8080:80 nginx
docker run -it --rm ubuntu bash
docker run -d --restart unless-stopped myapp
# Start / stop / restart
docker start myapp
docker stop myapp
docker restart myapp
# Remove
docker rm myapp
docker rm -f myapp
# List
docker ps # Running
docker ps -a # All
# Logs
docker logs myapp
docker logs -f --tail 200 myapp
docker logs --since 10m myapp
# Execute inside a running container
docker exec -it myapp bash
docker exec -it myapp sh # Alpine
docker exec myapp cat /etc/os-release
Networking
docker network ls
docker network create mynet
# Containers on the same custom network resolve each other by name
docker run -d --name api --network mynet myapi:latest
docker run -d --name db --network mynet postgres:16
# From api, reach db at hostname "db": postgresql://user:pass@db:5432/mydb
docker network connect mynet myapp
docker network disconnect mynet myapp
docker network inspect mynet
# Port mapping
docker run -d -p 8080:80 nginx # Host 8080 -> container 80
docker run -d -p 127.0.0.1:8080:80 nginx # Bind to localhost only
docker run -d -P nginx # All exposed -> random host ports
# Host networking (Linux only, container shares host network stack)
docker run -d --network host nginx
Volumes and Bind Mounts
# Named volume
docker volume create mydata
docker run -d -v mydata:/var/lib/data myapp
# Bind mount
docker run -d -v $(pwd)/src:/app/src myapp
docker run -d -v $(pwd)/config.yaml:/app/config.yaml:ro myapp
# tmpfs (in-memory, never written to disk)
docker run -d --tmpfs /tmp:rw,size=64m myapp
docker volume ls
docker volume inspect mydata
docker volume rm mydata
# Copy files
docker cp myapp:/app/data.json ./
docker cp ./config.yaml myapp:/app/
Environment Variables and Secrets
docker run -e DATABASE_URL=postgres://user:pass@db:5432/app myapp
docker run --env-file .env myapp
BuildKit secrets (never stored in image layers):
docker build --secret id=npmrc,src=$HOME/.npmrc -t myapp .
# syntax=docker/dockerfile:1
RUN npm ci
Multi-Stage Build Patterns
Go (scratch)
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app .
FROM scratch
COPY /app /app
ENTRYPOINT ["/app"]
Python
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN python -m venv /opt/venv && /opt/venv/bin/pip install --no-cache-dir -r requirements.txt
FROM python:3.12-slim
COPY /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
WORKDIR /app
COPY . .
USER nobody
CMD ["python", "main.py"]
Node.js
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --omit=dev
FROM node:20-alpine
WORKDIR /app
COPY /app/node_modules ./node_modules
COPY /app/dist ./dist
COPY package.json ./
RUN addgroup -g 1001 appgroup && adduser -S -u 1001 -G appgroup appuser
USER appuser
EXPOSE 3000
CMD ["node", "dist/server.js"]
Java
FROM eclipse-temurin:21-jdk AS builder
WORKDIR /app
COPY build.gradle settings.gradle gradlew ./
COPY gradle ./gradle
RUN ./gradlew dependencies --no-daemon
COPY src ./src
RUN ./gradlew bootJar --no-daemon
FROM eclipse-temurin:21-jre
COPY /app/build/libs/*.jar app.jar
USER 1000
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
Debugging Containers
docker inspect myapp
docker inspect --format '{{.State.Status}}' myapp
docker inspect --format '{{.State.ExitCode}}' myapp
docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' myapp
docker stats # Live resource usage
docker stats myapp --no-stream # Single snapshot
docker top myapp # Processes inside container
docker diff myapp # Filesystem changes since start
docker events --filter container=myapp
# Debug sidecar with network tools
docker run -it --rm --pid=container:myapp --network=container:myapp nicolaka/netshoot
Docker Buildx (Multi-Platform)
docker buildx create --name multibuilder --use
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest --push .
docker buildx build --platform linux/amd64 -t myapp:latest --load .
docker buildx ls
docker buildx rm multibuilder
Image Optimization
| Base Image | Size | Shell | Use Case |
|---|---|---|---|
| ubuntu:22.04 | ~77 MB | Yes | General purpose |
| debian:bookworm-slim | ~52 MB | Yes | Smaller general purpose |
| alpine:3.19 | ~7 MB | Yes | Small images with shell |
| gcr.io/distroless/base | ~20 MB | No | Minimal attack surface |
| scratch | 0 MB | No | Static binaries (Go, Rust) |
- Combine RUN statements:
RUN apt-get update && apt-get install -y pkg && rm -rf /var/lib/apt/lists/* - Remove caches in the same layer they are created.
- Use
docker historyanddiveto find large layers.
Security
# Non-root user
RUN addgroup -g 1001 appgroup && adduser -S -u 1001 -G appgroup appuser
USER appuser
# Read-only filesystem
docker run --read-only --tmpfs /tmp myapp
# Drop capabilities
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp
# Prevent privilege escalation
docker run --security-opt no-new-privileges myapp
# Limit resources
docker run --memory 512m --cpus 1.0 myapp
Never use COPY or ENV for secrets. Use BuildKit secret mounts or runtime env vars.
Scanning with Trivy
trivy image myapp:latest
trivy image --severity HIGH,CRITICAL --exit-code 1 myapp:latest
trivy config Dockerfile
Cleanup Commands
docker container prune # Remove stopped containers
docker image prune -a # Remove all unused images
docker volume prune # Remove unused volumes (data loss risk)
docker network prune # Remove unused networks
docker system prune -a --volumes # Remove everything unused
docker system df # Check disk usage
Troubleshooting
Container Exits Immediately
docker logs myapp
docker inspect --format '{{.State.ExitCode}}' myapp
# Exit 0: process completed (not a daemon, or CMD missing)
# Exit 1: application error
# Exit 137: OOM killed or SIGKILL
# Exit 126: command not executable
# Exit 127: command not found (check CMD/ENTRYPOINT path)
Port Conflicts
lsof -i :8080 # Find what uses the port
docker run -d -p 9090:80 nginx # Use a different host port
Permission Issues
COPY . /app
docker run -u $(id -u):$(id -g) -v $(pwd):/app myapp
Container Cannot Resolve Other Containers
Default bridge does not support DNS. Use a user-defined network:
docker network create mynet
docker run -d --name api --network mynet myapi
docker run -d --name db --network mynet postgres:16
Build Context Too Large
Add paths to .dockerignore, or specify a smaller context directory:
docker build -t myapp -f Dockerfile ./src
More from 1mangesh1/dev-skills-collection
curl-http
HTTP request construction and API testing with curl and HTTPie. Use when user asks to "test API", "make HTTP request", "curl POST", "send request", "test endpoint", "debug API", "upload file", "check response time", "set auth header", "basic auth with curl", "send JSON", "test webhook", "check status code", "follow redirects", "rate limit testing", "measure API latency", "stress test endpoint", "mock API response", or any HTTP calls from the command line.
28database-indexing
Database indexing internals, index type selection, query plan analysis, and write-overhead tradeoffs across PostgreSQL, MySQL, and MongoDB. Use when user asks to "optimize queries", "create indexes", "fix slow queries", "read EXPLAIN output", "reduce query time", "index strategy", "database performance", "composite index", "covering index", "partial index", "index bloat", "unused indexes", or needs help diagnosing and resolving database performance problems.
13testing-strategies
Testing strategies, patterns, and methodologies across the full testing spectrum. Use when asked about unit tests, integration tests, e2e tests, test pyramid, mocking, test doubles, TDD, property-based testing, snapshot testing, test coverage, mutation testing, contract testing, performance testing, test data management, CI/CD testing, flaky tests, test anti-patterns, test organization, test isolation, test fixtures, test parameterization, or any testing strategy, approach, or methodology.
10secret-scanner
This skill should be used when the user asks to "scan for secrets", "find API keys", "detect credentials", "check for hardcoded passwords", "find leaked tokens", "scan for sensitive keys", "check git history for secrets", "audit repository for credentials", or mentions secret detection, credential scanning, API key exposure, token leakage, password detection, or security key auditing.
10terraform
Terraform infrastructure as code for provisioning, modules, state management, and workspaces. Use when user asks to "create infrastructure", "write Terraform", "manage state", "create module", "import resource", "plan changes", or any IaC tasks.
10kubernetes
Kubernetes and kubectl mastery for deployments, services, pods, debugging, and cluster management. Use when user asks to "deploy to k8s", "create deployment", "debug pod", "kubectl commands", "scale service", "check pod logs", "create ingress", or any Kubernetes tasks.
10