Docker
Package applications and dependencies into portable containers - ensuring consistent environments from development through production.
skill: Docker category: Backend tags: [Docker, Containers, Dockerfile, Docker Compose, DevOps] readingTime: 6
Docker is the standard containerization tool - if your app runs in Docker, it runs the same everywhere. Use Docker for local development parity, CI builds, and production deployment. For orchestration at scale, pair with Kubernetes.
Workflow
- Write a DockerfileA Dockerfile is a reproducible recipe for building your app image - base image, dependencies, code, and runtime command.
- Optimize image sizeSmaller images pull faster, start faster, and have a smaller attack surface. Alpine base images are 5MB vs 900MB for the full Debian-based node.
- Compose services locally with docker-composeDocker Compose runs multiple containers (app + DB + Redis) locally with a single command - eliminating 'install Postgres on your machine' setup docs.
- Run securely with a non-root userBy default, containers run as root - if the container is compromised, the attacker has root access to the container. Always run as a non-root user.
- Tag, push, and pull from a registryDocker registries (Docker Hub, GHCR, ECR) store and distribute images for deployment to any server or Kubernetes cluster.
Output Format
Production Docker image: Alpine base, multi-stage build, non-root user, optimized layers.
project/
├── Dockerfile # Multi-stage production build
├── .dockerignore # Exclude node_modules, .git, etc.
├── docker-compose.yml # Local dev: app + db + redis
└── docker-compose.prod.yml # Production overridesExamples
Input
Output
Edge Cases & Gotchas
- Secrets in Dockerfile or images - Never ARG or ENV a secret in the Dockerfile - it's stored in image layers. Use Docker secrets, runtime environment variables, or a secrets manager at startup.
- Volume mounts override COPY - A bind mount from docker-compose (-v ./src:/app/src) overlays the container's filesystem. If the local dir is empty, it hides the container's files.
- PID 1 and signal handling - Node.js as PID 1 doesn't handle SIGTERM correctly by default. Use ENTRYPOINT ["/usr/bin/tini", "--"] with Tini as init, or node --enable-source-maps as a proper PID 1.
- File permissions between host and container - Files created by a non-root container user may not be writable by the host user and vice versa. Match UIDs: --user $(id -u):$(id -g) in docker run.
When to Break These Rules
- Use Podman instead of Docker for rootless containers and daemonless operation in security-sensitive or RHEL/Fedora environments.
- Use nix or devcontainers for development environments when reproducibility of the entire toolchain (not just runtime) is required.
Reference Files
https://docs.docker.com/https://docs.docker.com/compose/