Docker — Basics
Docker — Basics
Section titled “Docker — Basics”Concepts
Section titled “Concepts”- Image — read-only template (layers) with filesystem + metadata.
- Container — running instance of an image (writable layer on top).
- Dockerfile — recipe to build an image.
- Registry — store images (Docker Hub, ECR, GCR, GHCR, GitLab, Harbor).
- Layer — each instruction creates one. Layers cached + shared.
- Volume — persistent data outside container layers.
- Network — virtual network for container comms (bridge, host, overlay).
- Compose — multi-container local dev (
docker-compose.yml).
Dockerfile essentials
Section titled “Dockerfile essentials”FROM node:20-alpine # base imageWORKDIR /app
# Cache layer: deps before codeCOPY package*.json ./RUN npm ci --omit=dev
# Then code (changes more often)COPY . .
ENV NODE_ENV=productionEXPOSE 3000USER node # non-rootHEALTHCHECK --interval=30s --timeout=3s CMD curl -fsS http://localhost:3000/healthz || exit 1CMD ["node", "dist/server.js"]Key directives:
FROM— base.RUN— execute at build time → new layer.COPY/ADD— files in.WORKDIR— set CWD.ENV/ARG— env vars (ARG only at build).EXPOSE— documentation, not enforcement.ENTRYPOINTvsCMD— entrypoint = the executable; cmd = default args.HEALTHCHECK— container health probe.USER— non-root.
Multi-stage builds
Section titled “Multi-stage builds”FROM node:20 AS buildWORKDIR /srcCOPY . .RUN npm ci && npm run build
FROM node:20-alpineWORKDIR /appCOPY --from=build /src/dist ./distCOPY --from=build /src/node_modules ./node_modulesUSER nodeCMD ["node", "dist/server.js"]Smaller final image, no compilers, no source code.
Image layers & caching
Section titled “Image layers & caching”- Layers cache on each instruction.
- Order matters: stable layers first (deps), volatile layers last (code). Otherwise every code change invalidates dep cache.
.dockerignorekeeps junk out of build context.
Common base images
Section titled “Common base images”- scratch — empty (Go static binaries).
- distroless — Google minimal (no shell, no package mgr).
- alpine — tiny musl libc; some glibc tools fail.
- debian-slim / ubuntu — full libc, larger.
For Node/Python: alpine or slim. For static Go binaries: scratch or distroless.
Networking
Section titled “Networking”- bridge (default) — internal subnet, NAT to host.
- host — share host’s network. No isolation. Linux only.
- none — no network.
- overlay — multi-host (Swarm/K8s).
- macvlan — give container its own MAC on LAN.
docker run -p 8080:80 — host:container port mapping.
Volumes
Section titled “Volumes”- Named volume —
docker volume create x→ managed by Docker. - Bind mount —
-v /host/path:/in/container. - tmpfs — RAM only.
Container fs is ephemeral. Persistent data → volume.
Common commands
Section titled “Common commands”docker build -t myimg:latest .docker imagesdocker run --rm -it myimg:latest shdocker ps; docker ps -adocker logs -f <id>docker exec -it <id> shdocker stop / start / rm <id>docker rmi <image>
docker system prune -af --volumes # cleanup
docker tag myimg:latest registry/proj/myimg:1.2.3docker push registry/proj/myimg:1.2.3Compose (local dev)
Section titled “Compose (local dev)”services: app: build: . ports: ["3000:3000"] environment: - DATABASE_URL=postgres://x:x@db:5432/app depends_on: { db: { condition: service_healthy } } db: image: postgres:16-alpine environment: { POSTGRES_PASSWORD: x } volumes: [ pgdata:/var/lib/postgresql/data ] healthcheck: test: ["CMD", "pg_isready", "-U", "postgres"] interval: 5svolumes: pgdata:docker compose up -d, down, logs, exec.
Build optimization
Section titled “Build optimization”- Use BuildKit (default in Docker 23+): parallel, cache mounts.
RUN --mount=type=cache,target=/root/.npm npm ci— persistent cache.--platform=linux/amd64,linux/arm64for multi-arch.- Use
buildxfor multi-platform.
Container vs VM
Section titled “Container vs VM”- Container: shares host kernel, isolated user-space (cgroups + namespaces). Lightweight, fast start.
- VM: own kernel, hardware-virtualized. Heavier.
Containers aren’t a strong security boundary — gVisor / Kata / Firecracker add VM-like isolation.
Common pitfalls
Section titled “Common pitfalls”- Running as root by default (uses host UID 0!).
- Using
:latesttag in production — non-reproducible. - Bloated final images with build tools.
- Logging to file inside container (logs lost). Use stdout/stderr.
- Storing state inside container without volume.
- Not using
.dockerignore. - Hard-coding secrets in image layers (visible via
docker history).