A Docker Compose backup should protect the application definition and the state the application cannot recreate. That usually means more than copying compose.yaml, but less than trying to archive every container, image layer, and runtime file on the host.
The production goal is to make a Compose stack rebuildable on a clean VM. If the original host disappears, the team should know which files define the stack, which data must be restored, which secrets and external dependencies are required, and in what order the services return.
This guide owns that Compose-level recovery model. It does not replace the broader Cloud Backup Strategy, database-native recovery in Database Backup Strategy for SaaS Apps, or the storage choice in Docker Volumes vs Bind Mounts.
A Docker Compose backup has four separate parts
A Compose application is easier to recover when its assets are divided by responsibility.
| Layer | Examples | Recovery job |
|---|---|---|
| Application definition | compose.yaml, overrides, profiles, service settings | Recreate the service topology |
| Runtime configuration | environment values, configs, secrets, certificates | Reconnect services safely |
| Persistent state | named volumes, bind-mounted data, database backups | Restore data that containers cannot recreate |
| External dependencies | object storage, managed databases, DNS, external APIs | Reconnect the rebuilt stack |
The Compose file recreates containers; it does not automatically recreate all application state.
A clean recovery design should therefore answer four questions:
- Can we reconstruct the final Compose model?
- Can we retrieve the required secrets and configuration?
- Can we restore durable data to the expected paths or volumes?
- Can the rebuilt stack reconnect to external systems safely?
If one of those answers depends on remembering what was configured manually on the old VM, the stack is not fully recoverable yet.
Back up the Compose source, not only the running containers
Containers are deployment artifacts. The source of truth should be the files and image references that create them.
Protect at least:
compose.yamlordocker-compose.yaml;- production override files;
.envtemplates or documented variable names;- reverse-proxy configuration;
- application config files mounted into containers;
- scripts used during deployment or migration;
- image names and version tags or digests;
- documented Compose project name where it matters;
- any systemd or host wrapper used to start the stack.
Keep these files in version control where possible. Version control is usually a better recovery source for Compose configuration than copying the running container filesystem.
Docker's current docker compose config command is useful because it resolves multiple Compose files, variable interpolation, and shorthand into the actual model Docker will apply. Before a major change, rendering the resolved model gives the team a concrete record of what the production deployment currently means.
For example:
docker compose config > resolved-compose.yaml
The rendered file should be treated as recovery evidence, not necessarily as the primary source file. Secrets may be interpolated into resolved output depending on how configuration is defined, so store it only where access is appropriate.
A safer long-term pattern is:
Git repository ├── compose.yaml ├── compose.production.yaml ├── proxy config └── deployment scripts Secret manager / protected file store └── production credentials Backup destination └── persistent application data
That separation is easier to audit than one large archive copied from /var/lib/docker.
Do not treat Docker's internal data directory as the backup format
Docker manages images, writable layers, metadata, networks, and volumes under its own data root. Copying that internal directory may look like a complete backup, but it tightly couples recovery to Docker's internal layout, storage driver, host state, and timing of the copy.
For most Compose applications, recovery is cleaner when the team can:
- provision a new VM;
- install Docker;
- retrieve the Compose definition;
- pull or rebuild images;
- recreate networks and volumes from Compose;
- restore persistent data;
- start services in a controlled order.
This approach makes the backup portable across replacement hosts and avoids depending on undocumented assumptions about Docker's runtime metadata.
Back up the application's source of truth and durable state, not the Docker daemon's working directory as your only recovery method.
There are exceptions for specialized host-level imaging or forensic workflows, but they should be treated as infrastructure recovery, not the normal Compose backup design.
Images should normally be reproducible or pullable
Container images can consume significant backup space, but they are often rebuildable or available from a registry.
A production recovery plan should record:
- image registry;
- repository name;
- version tag;
- image digest where deterministic rollback matters;
- credentials required to pull the image;
- source/build instructions if the registry is unavailable.
If an image exists only on one production host and cannot be rebuilt, that image has become irreplaceable state and should be protected accordingly. That is a warning sign in the release process.
A good default is:
| Image situation | Recovery approach |
|---|---|
| Public upstream image | Pull again by trusted version |
| Private application image | Pull from protected registry |
| Internally built image | Registry + reproducible build source |
| One-off local-only image | Export temporarily, then fix the release process |
Do not turn every routine image layer into backup data just because it happens to exist on the VM.
Named volumes need an explicit backup owner
Docker volumes persist beyond the lifecycle of an individual container, but persistence is not historical recovery.
Docker's current documentation includes a supported pattern for backing up and restoring a volume by mounting it into a temporary container and creating an archive. The exact command is less important than the operating rule: the volume must be copied to a recovery destination outside the workload that uses it.
For a file-oriented volume, a simple model is:
Compose service ↓ Named volume ↓ controlled backup job Archive or backup repository ↓ Off-host recovery destination
Before backing up a volume, identify what owns consistency.
| Volume contents | Better backup method |
|---|---|
| Static uploads or documents | File-level backup can fit |
| Application-generated files | File-level backup plus app validation |
| Database data directory | Database-native backup should lead |
| Cache | Usually rebuild, not back up |
| Queue state | Depends on durability/business requirement |
| Search index | Often rebuild from primary data |
For the detailed storage choice, use Docker Volumes vs Bind Mounts. This guide only defines where volume recovery fits in the complete Compose stack.
Database containers require database-aware backups
A database running inside Docker Compose is still a database. The container boundary does not change its transaction or recovery semantics.
Do not make a raw archive of a live PostgreSQL or MySQL data directory your only recovery method.
Depending on the engine and required recovery target, use methods such as:
- logical dumps;
- physical/base backups;
- write-ahead-log or binary-log retention;
- point-in-time recovery;
- application-coordinated maintenance or snapshot procedures.
Then store the resulting backup artifacts outside the database container and preferably outside the VM.
A clean architecture looks like:
Compose database container ↓ Database-aware backup ↓ Protected backup destination ↓ Restore into clean database container or managed database
The Compose backup should document where the database backup comes from and how the application reconnects after restore. It should not duplicate the database engine's own recovery documentation.
For that layer, use Database Backup Strategy for SaaS Apps.
Bind mounts need path-level recovery documentation
Bind mounts expose host filesystem paths directly into containers. Their recovery model therefore depends on the host path, not on Docker volume metadata.
For every important bind mount, record:
- host path;
- container path;
- ownership and permissions;
- whether the directory is generated or durable;
- backup destination;
- restore order;
- any dependency on host users or groups.
For example:
services: app: volumes: - /srv/app/uploads:/app/uploads
A successful host replacement requires /srv/app/uploads to exist with the expected data and permissions before the application depends on it.
This is one reason bind mounts can be operationally clear for teams that intentionally manage host paths, but fragile when important paths are created manually without documentation.
Secrets should be recoverable without living in the backup archive
A Compose stack often needs database passwords, API keys, TLS private keys, registry credentials, OAuth secrets, and other sensitive values.
The recovery plan must prove those values are retrievable, but the general backup archive should not become an uncontrolled copy of every production secret.
Use a separate protected recovery path for secrets:
Compose definition ↓ references Secret source ↓ Application containers
The secret source may be a protected secret manager, encrypted configuration repository, password vault, or tightly controlled backup file.
Record:
- which secrets are required;
- where they are retrieved;
- who can access them during recovery;
- how access works if the normal identity path is unavailable;
- which secrets should be rotated after a compromise.
Do not put actual secret values into the recovery runbook.
Docker Compose supports secrets and configs as explicit service resources. Whether the source is a file, environment value, external object, or another system, the recovery question stays the same: can a replacement host obtain the required value without relying on the failed host?
Project names and volume names can affect restore behavior
Compose normally scopes resource names by project. That can affect network names, container names, and named volumes.
A volume defined as:
volumes: app_data:
may be created with a project-scoped name such as:
myproject_app_data
If a recovery process restores an archive into a differently named volume, the data can exist on disk while the Compose application still mounts an empty newly created volume.
Therefore document either:
- the expected Compose project name; or
- explicit external/named resources where stable naming is required.
Do not hard-code resource names unless there is a reason. The goal is not to defeat Compose's project isolation; it is to make sure the restore process knows which volume the rebuilt service will actually mount.
A useful recovery check is:
docker compose config --volumes
and then compare the intended volume names with the restored resources before starting stateful services.
docker compose down -v is a data-destruction operation
Named volumes normally persist when a Compose stack is brought down and recreated. Docker's current documentation shows that docker compose down -v removes named volumes associated with the project.
The -v flag can permanently delete stored application data.
Treat it like a destructive storage command, not a routine cleanup option.
Before using it on a production stack, confirm:
- which volumes will be removed;
- whether each volume contains durable state;
- whether a current backup exists;
- whether the recovery procedure has been tested;
- whether the removal is intentional rather than an attempt to fix an unrelated deployment issue.
This risk is separate from general disk cleanup. For prune and disk-pressure policy, use Docker Resource Limits, Logging, and Disk Management.
The restore sequence should rebuild dependencies in order
A Compose backup is only useful when there is a defined restore path.
A practical fresh-host sequence is:
1. Provision clean VM 2. Install supported Docker Engine + Compose plugin 3. Restore Compose files and deployment configuration 4. Retrieve secrets and registry credentials 5. Pull or rebuild required images 6. Recreate expected networks and empty volumes 7. Restore file/volume data 8. Restore database using database-native method 9. Start stateful dependencies 10. Start application services 11. Validate health and data 12. Re-enable public traffic
The exact order depends on the application.
For example, a web container may be able to start before PostgreSQL is restored, but repeatedly crash while migrations or connection attempts run against an empty database. A worker may begin consuming jobs before the application is ready. A scheduler may send duplicate notifications in a recovery environment.
Document which services should remain stopped until validation is complete.
Compose startup dependencies can help with normal boot sequencing, but disaster recovery still needs a human-readable order that includes data restore and external systems.
Restore into a clean host to prove portability
The strongest Compose recovery test is not restarting the existing stack. It is rebuilding the application on a clean host using only approved recovery sources.
That test proves whether the team has accidentally depended on:
- an untracked host package;
- a manually edited config file;
- a local-only image;
- a forgotten bind-mount path;
- an undocumented firewall or reverse-proxy change;
- credentials stored only on the failed VM;
- a named volume whose real identity is unknown;
- a database backup that cannot be restored;
- an external dependency that no longer accepts the restored credentials.
A clean-host test should end only after application-level validation.
Check:
- expected services are running;
- application health endpoint responds;
- database contains the expected recovery point;
- uploads or durable files are present;
- queues and workers behave correctly;
- reverse proxy and TLS work;
- external integrations are controlled;
- logs and monitoring are visible;
- no production side effects are triggered accidentally.
For the broader evidence framework, use Restore Testing Checklist for Production VMs.
Keep backup destinations outside the Compose host
A backup stored only on the same VM shares too much failure risk with production.
If the disk, VM, account, or administrator action that damages production can also delete the only backup, the recovery boundary is weak.
A Compose recovery design can use:
- object storage;
- a dedicated backup host;
- a remote backup repository;
- managed database recovery;
- infrastructure-level VM backup as an additional layer.
The correct choice depends on the data type and recovery requirements.
On Raff, a practical model is:
Raff VM running Docker Compose ↓ Compose definition in version control ↓ Database-aware backups / file backups ↓ Off-host recovery destination ↓ Clean-host restore test
Use Raff Object Storage when the backup tool or application can write compatible artifacts to S3-compatible storage. Use Raff Data Protection for VM-level recovery when the workload also needs infrastructure recovery.
At Raff, we treat Compose recovery and VM recovery as separate controls: VM recovery can bring back a server image, while Compose recovery proves the application can be rebuilt even when the original server is not trusted or available.
A Docker Compose backup inventory prevents missing state
Use this inventory before calling the stack recoverable:
| Item | Back up? | Preferred source |
|---|---|---|
| Compose files | Yes | Version control |
| Production overrides | Yes | Version control |
| Resolved config snapshot | Useful before major changes | Protected recovery evidence |
| Image source/build definition | Yes | Git + registry |
| Private images | Yes, via registry or reproducible build | Container registry |
| Secrets | Yes, separately | Secret manager / protected store |
| Named-volume durable data | Yes | Workload-aware backup |
| Bind-mounted durable data | Yes | File-level backup |
| Database data | Yes | Database-native backup |
| Cache | Usually no | Rebuild |
| Container writable layer | Usually no | Recreate container |
| Logs | Only when required for retention/audit | Logging system |
| External object data | Separate policy | Object storage recovery plan |
| DNS/TLS/network config | Document/source control | Infrastructure configuration |
The purpose of the inventory is to distinguish reproducible artifacts from irreplaceable state.
Backing up everything wastes storage and still may miss the one secret or external dependency required for recovery. Backing up only compose.yaml produces the opposite failure: perfect infrastructure definition with no business data.
Production recovery baseline
A Docker Compose stack is reasonably prepared for host loss when all of the following are true:
- Compose files are versioned outside the VM.
- Image tags or digests are known and pullable.
- Required private registry access can be recovered.
- Secrets are stored outside the failed host.
- Every durable volume or bind mount has an owner.
- Database containers have database-aware backups.
- Backup copies exist outside the Compose VM.
- Destructive
down -vor prune operations require deliberate review. - Compose project/resource naming is understood.
- The restore order is documented.
- Stateful services can be restored before workers or schedulers create side effects.
- A clean VM has been used to test the recovery path.
- Application-level validation completes before traffic returns.
This is the boundary of this guide: reconstructing a Docker Compose application from clean infrastructure and protected state.
Generic retention schedules, RPO/RTO policy, provider-wide backup architecture, and detailed database recovery remain separate topics so the pages do not compete with one another.