Docker Compose Tip #49: Mixed platforms with Linux containers and Wasm

Compose can orchestrate more than just Linux containers. By combining platform and runtime, you can run traditional containers alongside WebAssembly (Wasm) modules in the same stack. The platform key The platform key at service level tells Docker which platform the service targets: services: # Regular Linux container (default) web: image: nginx platform: linux/amd64 # WebAssembly module api: image: wasmedge/example-wasi-http runtime: io.containerd.wasmedge.v1 Mixing Linux and Wasm services Here’s a practical stack where a traditional nginx reverse proxy sits in front of a Wasm-based API: ...

April 6, 2026 · 2 min · 339 words · Guillaume Lours

Docker Compose Tip #47: Sidecar container patterns

A sidecar is a helper container that runs alongside your main application, adding capabilities without modifying the application itself. Compose has specific features to make sidecars work seamlessly. Shared network namespace with network_mode Use network_mode: service:<name> to share the network stack with another container, they share the same IP address and can communicate over localhost: services: app: image: myapp # No ports needed — proxy handles public traffic proxy: image: nginx network_mode: service:app ports: - "443:443" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro - ./certs:/etc/nginx/certs:ro Since both containers share the same network namespace, nginx can proxy to localhost:3000 without any DNS resolution. The app doesn’t need to know about TLS at all, the proxy sidecar handles it. ...

April 1, 2026 · 2 min · 360 words · Guillaume Lours

Docker Compose Tip #39: Combining include, extends, and overrides

The real power comes from using all three mechanisms together, each doing what it does best. The scenario A team maintaining a web application with: Shared infrastructure (database, monitoring) reused across projects Common service configuration (logging, labels) applied to all services Different settings for local development vs CI vs production Project structure my-project/ ├── compose.yml # Main entry point ├── compose.override.yml # Local dev overrides ├── compose.ci.yml # CI-specific overrides ├── base/ │ └── service-base.yml # Shared service config (extends) └── infra/ ├── database.yml # Postgres stack (include) └── monitoring.yml # Prometheus + Grafana (include) Step 1: Shared service config with extends Define common configuration once: ...

March 13, 2026 · 2 min · 324 words · Guillaume Lours

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