[{"data":1,"prerenderedAt":201},["ShallowReactive",2],{"seo-verification":3,"blog-docker-compose-in-production-10-point-checklist-en":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"id":7,"slug":8,"slugs":9,"title":12,"excerpt":13,"readTime":14,"views":15,"isPinned":16,"publishedAt":17,"category":18,"categories":23,"featuredImage":25,"bgImage":26,"posterImage":27,"relatedSolution":25,"intro":28,"sections":29,"ctaTitle":151,"ctaBody":152,"ctaButton":153,"ctaUrl":154,"relatedPosts":155},229,"docker-compose-in-production-10-point-checklist",{"fr":10,"en":8,"ar":11},"docker-compose-production-checklist","docker-compose-في-الإنتاج-قائمة-التحقق-من-10-نقاط","Docker Compose in Production: 10-Point Checklist","10 Docker Compose settings to verify before any production deployment: restart, healthchecks, limits, secrets and logs.",14,0,false,"2026-08-06T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},3,"Deployment","deploiement","bg-success\u002F10 text-success",[24],{"id":19,"name":20,"slug":21,"color":22,"icon":21},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg","A docker-compose.yml that runs on your laptop won't survive production as-is. Restart after reboot, resource limits, secrets, log rotation: these settings are missing by default and cause silent outages once the service is exposed. This checklist gathers the 10 parameters to verify before deploying your first Compose stack on a VPS. Each takes a few lines of YAML and spares you a nighttime incident.",[30,34,48,51,85,133,136,139,142,145,148],{"type":31,"title":32,"body":33},"h2","Why a checklist before production","Docker Compose was designed for development: its defaults favor simplicity over robustness. A container will not restart after a host reboot, its logs grow without limit, it can consume all the machine's RAM, and it listens on every network interface. In development, none of these behaviors cause problems because you relaunch the stack by hand several times a day. In production, these missing settings turn into incidents: full disk at 3 a.m., database lost after a `docker compose down`, service unreachable after a power outage. The good news: hardening a Compose stack requires no rewrite, only a dozen targeted additions.",{"type":35,"title":36,"items":37},"ul","The 10 points at a glance",[38,39,40,41,42,43,44,45,46,47],"**restart: unless-stopped** — the container restarts after a host reboot or crash","**healthcheck** — Docker detects a stuck container and enables rolling restarts","**CPU\u002Fmemory limits** — a runaway service can no longer starve its neighbors","**secrets via .env or Docker secrets** — never a password in cleartext in the Compose file","**named volumes** — data survives a `docker compose down`","**log rotation** — `max-size` and `max-file` stop the disk from filling up","**network isolation** — separate `frontend` and `backend`, do not expose everything on the default bridge","**port binding** — `127.0.0.1:PORT` behind a reverse proxy, not `0.0.0.0`","**pinned image tags** — a version or digest, never `latest`","**depends_on with condition** — `service_healthy` avoids startup races",{"type":31,"title":49,"body":50},"Prerequisites","Before applying this checklist, ensure you have a VPS with Docker Engine and the Compose v2 plugin installed (the command is `docker compose`, no hyphen, since 2022). Check the version with `docker compose version`: the `deploy.resources` syntax outside Swarm requires Compose v2. Place your file in a dedicated project folder, for example `\u002Fopt\u002Fmyapp`, with a `.env` file beside it and restricted permissions (`chmod 600 .env`). Plan for a reverse proxy upstream — Traefik, Caddy, or Nginx — because several settings, notably port binding, assume that public traffic never hits your containers directly. Keep a copy of your Compose file under version control.",{"type":52,"title":53,"steps":54},"steps","The 10 detailed steps",[55,58,61,64,67,70,73,76,79,82],{"title":56,"body":57},"1. Restart policy","Add `restart: unless-stopped` to each service. The container restarts after a crash or host reboot, but stays stopped if you stopped it intentionally. Avoid `restart: always`, which would relaunch even a container you intended to keep off.",{"title":59,"body":60},"2. Healthcheck","Declare a `healthcheck:` block with a `test` (for example `curl -f http:\u002F\u002Flocalhost:8080\u002Fhealth || exit 1`), an `interval`, a `timeout`, and `retries`. Docker then marks the container `healthy` or `unhealthy`, allowing other services to react to a stall.",{"title":62,"body":63},"3. Resource limits","Under `deploy.resources.limits`, set `cpus` and `memory` (for example `memory: 512M`). Without a limit, a leaking service can consume all the RAM and get the others killed by the OOM killer. Also add `reservations` to guarantee a minimum.",{"title":65,"body":66},"4. Secrets out of the file","Never put a password in cleartext in the YAML. Reference them via `env_file: .env` or `${VARIABLE}`, or use Docker's `secrets:` mechanism that mounts the secret as a file in the container. Add `.env` to your `.gitignore`.",{"title":68,"body":69},"5. Named volumes","Declare your data in named volumes with an explicit driver rather than an anonymous bind-mount. A named volume survives `docker compose down`; only `down -v` deletes it. Document each volume to know what you are backing up.",{"title":71,"body":72},"6. Log rotation","Add a `logging:` block with `driver: json-file` and options `max-size: \"10m\"` and `max-file: \"3\"`. Without it, a chatty container's logs fill the disk until failure. Apply it to every service.",{"title":74,"body":75},"7. Network isolation","Create named networks — a `frontend` for what is exposed, a `backend` for the database — and attach each service only to the networks it needs. Your database should only be reachable by the application, never from the shared default bridge.",{"title":77,"body":78},"8. Port binding","Behind a reverse proxy, publish on `127.0.0.1:8080:8080`, not `8080:8080` (which equals `0.0.0.0`). Otherwise the port remains reachable from the internet despite the proxy, bypassing your TLS and authentication rules.",{"title":80,"body":81},"9. Pinned image tags","Replace `image: postgres:latest` with a specific version (`postgres:16.3`) or, better, a digest (`postgres@sha256:...`). `latest` changes without warning and makes your deployments non-reproducible. Combine with `pull_policy: missing` for predictable behavior.",{"title":83,"body":84},"10. Startup order","Use `depends_on` with `condition: service_healthy` so a service waits not just for launch but for the real availability of its dependency. This requires a healthcheck on the dependent service (step 2) and eliminates startup races.",{"type":86,"title":87,"headers":88,"rows":92},"comparison","Dev defaults vs production settings",[89,90,91],"Setting","Dev default","Recommended for prod",[93,97,101,105,109,113,117,121,125,129],[94,95,96],"restart","no","unless-stopped",[98,99,100],"healthcheck","absent","defined with interval and retries",[102,103,104],"memory","unrestricted","limit set (e.g. 512M)",[106,107,108],"secrets","cleartext possible",".env or Docker secrets",[110,111,112],"volumes","anonymous","named with driver",[114,115,116],"logs","unbounded","max-size + max-file",[118,119,120],"network","default bridge","separate frontend \u002F backend",[122,123,124],"ports","0.0.0.0","127.0.0.1 behind proxy",[126,127,128],"image","latest","pinned version or digest",[130,131,132],"depends_on","launch only","condition: service_healthy",{"type":134,"body":135},"tip","Always test your hardened stack locally before pushing to production: run `docker compose config` to validate the syntax, then `docker compose up` and simulate a reboot with `docker compose restart`. Verify that containers come back `healthy` and that data persists after a `down` followed by an `up`.",{"type":31,"title":137,"body":138},"Troubleshooting","If a container stays stuck in `starting`, your healthcheck is failing: test the `test` command manually with `docker compose exec service sh` and verify it returns 0. A service restarting in a loop (`Restarting`) usually hides a startup error — check `docker compose logs -f service`. If `deploy.resources.limits` seems ignored, remember that in Compose v2 outside Swarm, limits are applied but `reservations` only take effect in Swarm mode. A port still reachable despite `127.0.0.1` usually signals a missing firewall or a Docker rule bypassing UFW — check with `ss -tlnp`. If `docker compose down` deleted your data, it is almost always because `-v` was appended or the volume was anonymous rather than named.",{"type":31,"title":140,"body":141},"CVE-2026-17106 (CopyEscape): update Docker Engine now","\u003Ca href=\"https:\u002F\u002Fwww.imperva.com\u002Fblog\u002Fcopyescape-docker-vulnerability-cve-2026-17106\u002F\">CVE-2026-17106\u003C\u002Fa>, nicknamed **CopyEscape**, is a race condition in `docker cp` disclosed on 10 August 2026. An untrusted container can produce a malformed tar archive that follows a symlink outside the destination, resulting in arbitrary file overwrite on the host — including the `runc` binary. Surface: any VPS running `docker cp` from a container whose content you do not control. The fix is in **Docker Engine ≥ 29.7.2** and **Docker Desktop ≥ 4.86.0**. Check your version with `docker version` and upgrade before exposing a new service. If an immediate upgrade is not possible, avoid `docker cp` from untrusted containers and enforce least privilege (`--cap-drop ALL`).",{"type":31,"title":143,"body":144},"Docker secrets management: rotation without downtime","Cleartext environment variables in a Compose file are the most common production secret leak: they appear in `docker inspect`, error logs, and process dumps. Docker's `secrets:` mechanism — or an external manager such as \u003Ca href=\"https:\u002F\u002Fmarkaicode.com\u002Fdocker-secrets-production-compose\u002F\">Vault or Infisical\u003C\u002Fa> — mounts secrets as files under `\u002Frun\u002Fsecrets\u002F`, out of reach of `inspect`. For **rotation without downtime**, version the secret (create `db_password_v2` in parallel with `v1`), update the service to read `v2`, redeploy with a rolling update (`docker compose up -d --no-deps service`), then remove `v1` once the deployment is validated. No service interruption, no window where the secret is exposed between versions.",{"type":31,"title":146,"body":147},"Backing up volumes without corruption","Copying files from a PostgreSQL or MySQL volume **while running** with `rsync` or `tar` almost always produces a corrupt backup: the engine writes continuously and data pages are captured at different checkpoints. The rule is to **always run a SQL dump before snapshotting the volume**: `pg_dump` or `mysqldump` produce a consistent state you can archive or transfer. To automate this on a Docker VPS, tools like \u003Ca href=\"https:\u002F\u002Fpistack.xyz\u002Fposts\u002F2026-05-11-self-hosted-docker-volume-backup-offen-nautical-loomchild-guide\u002F\">Restic and Offen Docker Backup\u003C\u002Fa> orchestrate database quiesce, SQL dump, encrypted snapshot, and upload to remote storage. Document each named volume (step 5 of the checklist) and pair it with a tested restore procedure: a backup without a restore test is unprotected data.",{"type":31,"title":149,"body":150},"Conclusion","These ten settings turn a development Compose file into a production stack able to survive reboots, load spikes, and unsupervised nights. None requires an extra tool: everything fits in the YAML you already have. Get into the habit of running this checklist before every go-live, ideally as a `docker compose config` review built into your deployment. Once these foundations are in place, you can add a reverse proxy like Traefik or Caddy, or an orchestration layer like Coolify, with full confidence.","Deploy your Compose stack in production","A ServOrbit VPS gives you the root access, RAM and network control needed to run a hardened Docker Compose stack. Pick your configuration and deploy in minutes.","Deploy on ServOrbit VPS","\u002Fvps-cloud",[156,169,185],{"id":157,"slug":158,"slugs":159,"title":162,"excerpt":163,"readTime":19,"views":15,"isPinned":16,"publishedAt":164,"category":165,"categories":166,"featuredImage":25,"bgImage":26,"posterImage":168,"relatedSolution":25},38,"deploy-your-applications-with-traefik-on-a-vps",{"fr":160,"en":158,"ar":161},"deployer-avec-traefik","انشر-تطبيقاتك-باستخدام-traefik-على-خادم-vps","Deploy your applications with Traefik on a VPS","Deploy Traefik as a reverse proxy on your VPS: automatic routing of Docker containers, Let's Encrypt SSL certificates and load balancing.","2026-05-13T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},[167],{"id":19,"name":20,"slug":21,"color":22,"icon":21},"\u002Fblog\u002Fcovers\u002Fdeployer-avec-traefik-poster.svg",{"id":170,"slug":171,"slugs":172,"title":175,"excerpt":176,"readTime":19,"views":15,"isPinned":16,"publishedAt":177,"category":178,"categories":179,"featuredImage":25,"bgImage":26,"posterImage":181,"relatedSolution":182},39,"deploy-your-applications-with-caddy-on-a-vps",{"fr":173,"en":171,"ar":174},"deployer-avec-caddy","انشر-تطبيقاتك-باستخدام-caddy-على-خادم-vps","Deploy your applications with Caddy on a VPS","Deploy Caddy on your VPS: web server and reverse proxy with automatic HTTPS. A Caddyfile of a few lines is enough to go into production.","2026-05-12T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},[180],{"id":19,"name":20,"slug":21,"color":22,"icon":21},"\u002Fblog\u002Fcovers\u002Fdeployer-avec-caddy-poster.svg",{"categorySlug":183,"appSlug":184},"application-deployment-devops","caddy",{"id":186,"slug":187,"slugs":188,"title":191,"excerpt":192,"readTime":193,"views":15,"isPinned":16,"publishedAt":194,"category":195,"categories":196,"featuredImage":25,"bgImage":26,"posterImage":198,"relatedSolution":199},41,"deploy-your-applications-with-coolify-on-a-vps",{"fr":189,"en":187,"ar":190},"deployer-avec-coolify","نشر-تطبيقاتك-باستخدام-coolify-على-vps","Deploy Your Applications with Coolify on a VPS","Deploy Coolify on a VPS: installation, HTTPS configuration, Git connection, deploying your first application, databases, backups, and troubleshooting.",10,"2026-05-10T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},[197],{"id":19,"name":20,"slug":21,"color":22,"icon":21},"\u002Fblog\u002Fcovers\u002Fdeployer-avec-coolify-poster.svg",{"categorySlug":183,"appSlug":200},"coolify",1787580996858]