L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Déploiement et opérations · SKILL.md

docker-fundamentals

docker-fundamentals

Use when working with Docker containers — core concepts, CLI commands, image management, container lifecycle, Dockerfile patterns, BuildKit features, multi-stage builds, layer caching optimization, health checks, restart policies, resource limits, npm/Node.js Docker patterns, Python Docker patterns, .dockerignore, debugging and troubleshooting containers. P…

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: docker-fundamentals description: Use when working with Docker containers — core concepts, CLI commands, image management, container lifecycle, Dockerfile patterns, BuildKit features, multi-stage builds, layer caching optimization, health checks, restart policies, resource limits, npm/Node.js Docker patterns, Python Docker patterns, .dockerignore, debugging and troubleshooting containers. Parent skill for the docker-* skill family. OS-agnostic — for OS-specific setup see ubuntu-docker-host or rhel-docker-host. family: docker disambiguation: Core local usage — CLI, image and container lifecycle, Dockerfile patterns, BuildKit. Running builds inside CI pipelines is docker-cicd.

Docker Fundamentals

OS-agnostic Docker core concepts and patterns. For OS-specific installation and setup, see ubuntu-docker-host or rhel-docker-host. For Compose patterns, see docker-compose-patterns. For operational gotchas and cross-platform issues, see docker-admin.


Container Lifecycle

# Create and start
docker run -d --name myapp -p 8080:8080 myimage:latest
docker run -it --rm ubuntu:24.04 bash          # interactive, auto-remove

# Lifecycle commands
docker start|stop|restart|pause|unpause <container>
docker kill <container>                         # SIGKILL (immediate)
docker stop -t 30 <container>                   # SIGTERM, wait 30s, then SIGKILL

# Inspect
docker ps                                       # running containers
docker ps -a                                    # all containers
docker inspect <container>                      # full JSON details
docker logs <container>                         # stdout/stderr
docker logs -f --tail 100 <container>           # follow last 100 lines
docker logs --since 1h <container>              # last hour
docker top <container>                          # running processes
docker stats                                    # live resource usage
docker stats --no-stream                        # snapshot

# Execute in running container
docker exec -it <container> bash
docker exec -it <container> sh                  # if bash not available
docker exec <container> env                     # check environment

# Copy files
docker cp <container>:/path/file ./local
docker cp ./local <container>:/path/file

# Remove
docker rm <container>
docker rm -f <container>                        # force (kills first)

Restart Policies

docker run -d --restart=unless-stopped myapp    # restart unless manually stopped
docker run -d --restart=on-failure:5 myapp      # restart on failure, max 5 times
docker run -d --restart=always myapp            # always restart
docker run -d --restart=no myapp                # never restart (default)

# Update restart policy on running container
docker update --restart=unless-stopped <container>
PolicyOn CrashOn Docker RestartOn Manual Stop
noNoNoN/A
on-failure[:N]Yes (up to N)NoN/A
alwaysYesYesYes
unless-stoppedYesYesNo

Image Management

# List and inspect
docker images                                   # local images
docker images -a                                # include intermediates
docker image inspect <image>
docker image history <image>                    # layer breakdown

# Pull and push
docker pull nginx:1.27-alpine
docker tag myapp:latest registry.example.com/myapp:v1.2.3
docker push registry.example.com/myapp:v1.2.3

# Remove
docker rmi <image>
docker image prune                              # remove dangling images
docker image prune -a                           # remove all unused images

# Save and load (offline transfer)
docker save myapp:latest | gzip > myapp.tar.gz
docker load < myapp.tar.gz

# Export/import container filesystem (loses metadata)
docker export <container> > container.tar
docker import container.tar myimage:imported

Image Tagging Strategy

# Semantic versioning + latest
docker tag myapp:latest myapp:1.0.0
docker tag myapp:latest myapp:1.0
docker tag myapp:latest myapp:1

# Git SHA for traceability
docker tag myapp:latest myapp:$(git rev-parse --short HEAD)

# Environment tags
docker tag myapp:latest myapp:staging
docker tag myapp:v1.2.3 myapp:production

Dockerfile Patterns

Basic Structure

# syntax=docker/dockerfile:1
FROM node:22-alpine AS base

# Metadata
LABEL maintainer="team@example.com"
LABEL version="1.0.0"

# Install OS dependencies
RUN apk add --no-cache tini curl

# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Set working directory
WORKDIR /app

# Copy dependency files first (layer caching)
COPY package.json package-lock.json ./

# Install dependencies
RUN npm ci --production

# Copy application code
COPY --chown=appuser:appgroup . .

# Health check
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

# Switch to non-root user
USER appuser

# Use tini as PID 1 (proper signal handling)
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "server.js"]

Multi-Stage Builds

# syntax=docker/dockerfile:1

# Stage 1: Build
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Production
FROM node:22-alpine AS production
RUN apk add --no-cache tini
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
USER app
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "dist/server.js"]

Python Multi-Stage

# syntax=docker/dockerfile:1

# Stage 1: Build with pip
FROM python:3.12-slim AS builder
WORKDIR /app
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Stage 2: Production
FROM python:3.12-slim AS production
RUN groupadd -r app && useradd -r -g app app
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
WORKDIR /app
COPY --chown=app:app . .
USER app
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "app:create_app()"]

Go Multi-Stage (Scratch Final)

# syntax=docker/dockerfile:1
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /server .

FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /server /server
ENTRYPOINT ["/server"]

BuildKit Features

# Enable BuildKit (if not default)
export DOCKER_BUILDKIT=1

# Build with progress output
docker build --progress=plain -t myapp .

# Build specific stage
docker build --target builder -t myapp:build .

# Pass build arguments
docker build --build-arg NODE_ENV=production -t myapp .

Secret Mounting (Never Bake Secrets)

# Mount secret at build time — never stored in layers
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
    npm ci --production

# Usage:
# docker build --secret id=npmrc,src=$HOME/.npmrc -t myapp .

Cache Mounts (Faster Rebuilds)

# Cache apt packages across builds
RUN --mount=type=cache,target=/var/cache/apt \
    --mount=type=cache,target=/var/lib/apt \
    apt-get update && apt-get install -y curl

# Cache npm packages
RUN --mount=type=cache,target=/root/.npm \
    npm ci --production

# Cache pip packages
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

# Cache Go modules
RUN --mount=type=cache,target=/go/pkg/mod \
    go mod download

Bind Mounts at Build Time

# Mount source code without COPY (useful for linting/testing stages)
RUN --mount=type=bind,source=.,target=/src \
    cd /src && npm run lint

Layer Caching Optimization

Principles

  1. Order by change frequency — put rarely-changing instructions first
  2. Separate dependency install from code copy — dependencies change less often
  3. Combine RUN commands — fewer layers = smaller image, but balance with caching
  4. Use .dockerignore — exclude files that invalidate cache unnecessarily

Node.js Layer Caching

# GOOD: Dependencies cached separately from code
COPY package.json package-lock.json ./
RUN npm ci
COPY . .

# BAD: Any code change invalidates npm install cache
COPY . .
RUN npm ci

Cache Busting

# Force re-fetch of packages (useful for security updates)
ARG CACHE_BUST=1
RUN apt-get update && apt-get upgrade -y

.dockerignore

# Version control
.git
.gitignore

# Dependencies (rebuild in container)
node_modules
__pycache__
*.pyc
.venv
vendor

# Build artifacts
dist
build
*.egg-info

# IDE and editor
.vscode
.idea
*.swp
*.swo

# Docker files (don't need to be in context)
Dockerfile*
docker-compose*
.dockerignore

# Environment and secrets
.env
.env.*
*.key
*.pem

# Documentation and tests (usually not needed in production image)
docs
tests
test
*.md
LICENSE

# OS files
.DS_Store
Thumbs.db

npm / Node.js Docker Patterns

npm ci vs npm install

# ALWAYS use npm ci in Docker (deterministic, faster, respects lockfile)
RUN npm ci --production

# npm install modifies lockfile — creates inconsistent builds
# RUN npm install  # DON'T USE IN DOCKERFILES

Handling node_modules Correctly

# 1. .dockerignore must exclude node_modules
#    (prevents host node_modules from overwriting container's)

# 2. For development with bind mounts, use anonymous volume:
# docker run -v $(pwd):/app -v /app/node_modules myapp:dev
# This prevents host node_modules from shadowing container's

Node.js Production Best Practices

FROM node:22-alpine

# Don't run as root
RUN addgroup -S app && adduser -S app -G app

# Set production environment
ENV NODE_ENV=production

WORKDIR /app

# Install production deps only
COPY package.json package-lock.json ./
RUN npm ci --production --ignore-scripts && npm cache clean --force

# Copy app code
COPY --chown=app:app . .

USER app

# Use exec form (proper signal handling)
CMD ["node", "server.js"]

TypeScript Build Pattern

FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json tsconfig.json ./
RUN npm ci
COPY src ./src
RUN npm run build
RUN npm prune --production

FROM node:22-alpine
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
ENV NODE_ENV=production
USER app
CMD ["node", "dist/index.js"]

Python Docker Patterns

pip with Virtual Environment

FROM python:3.12-slim
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]

Poetry

FROM python:3.12-slim AS builder
RUN pip install poetry
WORKDIR /app
COPY pyproject.toml poetry.lock ./
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
RUN python -m venv /opt/venv && /opt/venv/bin/pip install -r requirements.txt

FROM python:3.12-slim
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
WORKDIR /app
COPY . .
CMD ["gunicorn", "-w", "4", "app:app"]

Health Checks

# HTTP health check
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1

# TCP port check (no curl needed)
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD nc -z localhost 5432 || exit 1

# Custom script
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
  CMD /app/healthcheck.sh
# Check health status
docker inspect --format='{{.State.Health.Status}}' <container>
docker inspect --format='{{json .State.Health}}' <container> | jq

# Health status values: starting, healthy, unhealthy

Resource Limits

# Memory limits
docker run -d --memory=512m --memory-swap=1g myapp
docker run -d --memory=512m --memory-swap=-1 myapp    # unlimited swap

# CPU limits
docker run -d --cpus=1.5 myapp                        # 1.5 CPU cores
docker run -d --cpu-shares=512 myapp                   # relative weight (default 1024)
docker run -d --cpuset-cpus="0,1" myapp                # pin to specific CPUs

# Combined
docker run -d --memory=1g --cpus=2 --pids-limit=100 myapp

# Update limits on running container
docker update --memory=1g --cpus=2 <container>

Debugging and Troubleshooting

Container Won't Start

# Check logs (even for stopped containers)
docker logs <container>

# Check exit code
docker inspect --format='{{.State.ExitCode}}' <container>

# Run interactively to debug
docker run -it --entrypoint sh myapp

# Override entrypoint
docker run -it --entrypoint /bin/bash myapp

# Check what's in the image
docker run --rm -it myapp ls -la /app
docker run --rm -it myapp cat /app/config.yml

Debugging Running Container

# Shell into container
docker exec -it <container> sh

# Check processes
docker top <container>

# Check resource usage
docker stats <container> --no-stream

# Check networking
docker exec <container> cat /etc/hosts
docker exec <container> cat /etc/resolv.conf
docker exec <container> wget -qO- http://other-service:8080/health

# File system diff (what changed since image was created)
docker diff <container>

# Inspect full config
docker inspect <container> | jq '.[0].NetworkSettings'
docker inspect <container> | jq '.[0].Mounts'

Debug with Ephemeral Container

# Attach debug tools to a running container (Docker 25+)
docker debug <container>

# Or use a sidecar approach
docker run -it --rm --pid=container:<container> --net=container:<container> \
  nicolaka/netshoot

Image Analysis

# Check image layers and sizes
docker history --human --no-trunc myapp

# Explore image filesystem
docker run --rm -it myapp sh -c "find / -type f -size +1M 2>/dev/null | head -20"

# Use dive for interactive layer inspection
# docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive myapp

System Maintenance

# Disk usage overview
docker system df
docker system df -v                              # verbose

# Clean up
docker system prune                              # dangling images + stopped containers
docker system prune -a                           # ALL unused images
docker system prune -a --volumes                 # include volumes (DESTRUCTIVE)

# Targeted cleanup
docker container prune                           # stopped containers
docker image prune -a                            # unused images
docker volume prune                              # unused volumes
docker network prune                             # unused networks
docker builder prune                             # build cache

Environment Variables and Configuration

# Pass environment variables
docker run -e DATABASE_URL=postgres://... myapp
docker run --env-file .env myapp

# Read from host environment
docker run -e HOME myapp                         # passes host's $HOME value
# Dockerfile defaults (overridable at runtime)
ENV NODE_ENV=production
ENV PORT=3000

# ARG is build-time only (not available at runtime)
ARG VERSION=latest
LABEL version=$VERSION

Exec Form vs Shell Form

# EXEC FORM (preferred) — runs directly, proper signal handling
CMD ["node", "server.js"]
ENTRYPOINT ["python", "app.py"]

# SHELL FORM — runs via /bin/sh -c, no direct signals
CMD node server.js
ENTRYPOINT python app.py

# Shell form is needed for:
RUN echo "hello" > /tmp/test              # shell features (redirection)
RUN apt-get update && apt-get install -y curl  # shell features (&&)
Exec FormShell Form
Signal handlingDirect (PID 1)Goes to shell (PID 1 is sh)
Variable expansionNo $VAR expansion$VAR expanded by shell
Use for CMD/ENTRYPOINTYes (preferred)Avoid
Use for RUNWhen no shell features neededWhen shell features needed


Anti-Patterns

Anti-PatternWhy It FailsCorrect Approach
Running containers as root (no USER directive)Container escape gives host root access; violates CIS Docker BenchmarkAdd USER directive in Dockerfile; use rootless Docker mode for defense in depth
Using shell form for CMD/ENTRYPOINTPID 1 is the shell, not your process; signals (SIGTERM) are not forwarded; graceful shutdown failsUse exec form (JSON array): CMD ["node", "server.js"] instead of CMD node server.js
Installing packages without cleaning cache in same layerPackage manager cache (apt lists, pip cache) bloats image by hundreds of MBChain install and cleanup in one RUN: apt-get install -y pkg && rm -rf /var/lib/apt/lists/*
No .dockerignore fileBuild context includes node_modules, .git, secrets, logs; slow builds, large images, leaked credentialsCreate .dockerignore mirroring .gitignore plus .git, .env, and build artifacts
Not using multi-stage buildsFinal image contains compilers, build tools, source code; 1GB+ images that should be 100MBUse multi-stage: build in one stage, copy only artifacts to a slim runtime stage

Related Skills

TopicSkill
Docker networking (bridge, overlay, DNS)docker-networking
Volumes, bind mounts, storage driversdocker-storage
Image scanning, rootless, CIS benchmarkdocker-security
CI/CD, multi-platform builds, registriesdocker-cicd
Advanced Compose patternsdocker-compose-patterns
Compose basics, cross-platform, AD mappingdocker-admin
Docker on Ubuntu 24.04ubuntu-docker-host
Podman/Docker on RHEL 9rhel-docker-host
Skills enregistrées