Docker Compose Tip #29: Container capabilities and security options

Secure containers with principle of least privilege! Control exactly what your containers can do. Understanding capabilities Linux capabilities break down root privileges into distinct units: services: # Drop all capabilities, then add only what's needed secure-app: image: myapp cap_drop: - ALL cap_add: - NET_BIND_SERVICE # Bind to ports < 1024 - CHOWN # Change file ownership # Default Docker capabilities (for reference) default-app: image: myapp # Implicitly has: CHOWN, DAC_OVERRIDE, FSETID, FOWNER, # MKNOD, NET_RAW, SETGID, SETUID, SETFCAP, SETPCAP, # NET_BIND_SERVICE, SYS_CHROOT, KILL, AUDIT_WRITE Common capability patterns Web server (needs port 80/443): ...

February 12, 2026 · 3 min · 524 words · Guillaume Lours

Docker Compose Tip #15: Blue-green deployments with Traefik

Deploy with zero downtime using Traefik’s dynamic routing. Switch traffic between blue and green deployments by updating environment variables, with automatic health checks. The setup Traefik automatically discovers services and routes traffic based on labels: # compose.yml services: traefik: image: traefik:v3.0 command: - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" ports: - "80:80" - "8080:8080" # Traefik dashboard volumes: - /var/run/docker.sock:/var/run/docker.sock:ro networks: - web app-blue: image: myapp:${BLUE_VERSION:-v1.0} labels: - "traefik.enable=${BLUE_ENABLED:-true}" - "traefik.http.routers.app-blue.rule=Host(`app.localhost`)" - "traefik.http.routers.app-blue.priority=1" - "traefik.http.services.app-blue.loadbalancer.server.port=3000" networks: - web environment: VERSION: blue app-green: image: myapp:${GREEN_VERSION:-v2.0} labels: - "traefik.enable=${GREEN_ENABLED:-false}" # Start disabled - "traefik.http.routers.app-green.rule=Host(`app.localhost`)" - "traefik.http.routers.app-green.priority=2" # Higher priority when enabled - "traefik.http.services.app-green.loadbalancer.server.port=3000" networks: - web environment: VERSION: green networks: web: driver: bridge Deployment workflow Switch traffic by recreating containers with updated labels: ...

January 23, 2026 · 2 min · 351 words · Guillaume Lours

Docker Compose Tip #8: Healthchecks with Docker Hardened Images

Docker Hardened Images (DHI) maximize security by removing shells and package managers. But how do you add healthchecks? Use a secure sidecar with shared network namespace. The problem Your hardened Node.js application: services: app: image: dhi.io/node:25-debian13-sfw-ent-dev healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] # FAILS: No curl in hardened image! The solution: Network namespace sidecar Use a hardened curl image that shares the app’s network: services: app: image: dhi.io/node:25-debian13-sfw-ent-dev ports: - "3000:3000" environment: NODE_ENV: production app-health: image: dhi.io/curl:8-debian13-dev entrypoint: ["sleep", "infinity"] network_mode: "service:app" # Shares app's network namespace! healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 3s retries: 3 start_period: 10s The network_mode: "service:app" allows the sidecar to access localhost:3000 directly - they share the same network stack! ...

January 14, 2026 · 3 min · 478 words · Guillaume Lours