Save and Restore a Container with docker checkpoint
You want to freeze a running container mid-flight and bring it back exactly where it left off, and docker checkpoint is the command that promises it. This guide takes you through saving a running Docker container as a checkpoint, checking that it exists, and restoring from it. The command is experimental and depends on daemon support, CRIU and kernel features, so success on one host is not a portability guarantee.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about twenty minutes for a first test. You need:
- Docker CLI 29.8.1 or a compatible release.
- Daemon access. The examples are unprivileged Docker commands, but your account may need membership of the Docker group or
sudoaccess to the daemon. Docker group membership is effectively root-equivalent, so do not grant it casually. - A disposable running container.
- Enough disk space for checkpoint data.
Safety boundary
Creating a checkpoint changes the container's runtime state and normally pauses it while the state is captured. Removing a checkpoint is destructive. Do not test against a production container until its pause, restore and rollback behaviour are understood.
1. Check the installed CLI and daemon
Start with read-only checks. They do not create, stop or modify a container:
$ docker --version
Docker version 29.8.1, build 4a63305
$ docker info --format '{{.ServerVersion}} {{.ExperimentalBuild}}'
29.8.1 false
The exact build identifier and daemon values vary. The installed package here is docker-ce-cli 5:29.8.1-1~ubuntu.24.04~noble.
The catch is in that trailing false. Checkpoint commands are experimental, and the client can be installed while the connected daemon has experimental features disabled, as in the output above.
- Support lives in the daemon.
docker checkpointcannot enable it for itself. - If the command says checkpointing needs experimental daemon features, stop. Ask the Docker administrator to assess the daemon configuration, CRIU package and kernel rather than retrying a state-changing command. Changing daemon configuration can disrupt every container and may require a controlled restart.
- CRIU is required. Docker's current documentation requires at least CRIU 2.0, but the kernel, runtime and container workload still affect whether a capture succeeds.
- Some containers will not capture. The command may fail for containers using unsupported features, including some terminal setups.
2. Choose a disposable running container
List running containers and select one whose workload can tolerate a pause. This is read-only:
$ docker ps --format '{{.ID}}\t{{.Names}}\t{{.Status}}'
CONTAINER_ID CONTAINER_NAME STATUS
Replace the labels in the example with a real container name or ID. Do not guess a name, and do not use a service container simply because it is convenient.
Warning
A checkpoint captures process state, not a portable image. Volumes, external services, network peers and host dependencies still need their own recovery plan.
Confirm that the selected container is running immediately before capture:
$ CONTAINER_NAME='replace-with-disposable-container'
$ docker inspect --format '{{.State.Status}}' "$CONTAINER_NAME"
running
Checkpoint
The result must be running. If it is not, stop and choose another container or start it through its normal operational procedure. Do not use docker start merely to make an unplanned production test possible.
3. Create the checkpoint
Choose a descriptive checkpoint name and capture the running container:
$ CHECKPOINT_NAME='before-maintenance-2026-09-23'
$ docker checkpoint create "$CONTAINER_NAME" "$CHECKPOINT_NAME"
before-maintenance-2026-09-23
The command takes the container and checkpoint name as positional arguments. The optional --checkpoint-dir DIRECTORY selects custom checkpoint storage. The default is managed by Docker, so do not assume the files are in your current directory.
By default, the container is not left running after capture. Treat it as paused or stopped until you have checked its state. If the workload must keep serving while you capture it, the documented option is:
$ docker checkpoint create --leave-running "$CONTAINER_NAME" "$CHECKPOINT_NAME"
before-maintenance-2026-09-23
Tip
Use --leave-running only when you have considered consistency. It changes the post-capture state, not the fact that a point-in-time copy was made. For a first test, a short planned pause is easier to observe and recover.
Inspect the container after creation:
$ docker inspect --format '{{.State.Status}}' "$CONTAINER_NAME"
exited
Checkpoint
The status is host- and option-dependent. The useful check is that it matches the choice you made.
Recovery
If creation fails, preserve the error, inspect daemon logs and check CRIU support. Do not delete partial files by hand from Docker's data directory.
4. List checkpoints before restoring
Ask Docker for the checkpoints belonging to this container:
$ docker checkpoint ls "$CONTAINER_NAME"
CHECKPOINT NAME ID
before-maintenance-2026-09-23 before-maintenance-2026-09-23
Column formatting and identifiers can vary by Docker release. The checkpoint name you supplied should be identifiable in the result.
Tip
If the list is empty, check that you are using the same container, Docker context and checkpoint directory. A checkpoint belongs to its container; it is not an image tag that can be applied to an unrelated container.
5. Restore the container from the checkpoint
Restoration uses docker start, not another checkpoint subcommand. First confirm that the container is stopped and that you have recorded any application-level recovery steps. Then run:
$ docker start --checkpoint "$CHECKPOINT_NAME" "$CONTAINER_NAME"
replace-with-disposable-container
A successful result prints the container name or ID. Verify that it is running:
$ docker inspect --format '{{.State.Status}}' "$CONTAINER_NAME"
running
$ docker logs --tail 20 "$CONTAINER_NAME"
The restored process should continue from the captured point, but application output is workload-specific. Check the application's own health endpoint, queue position, open connections and data consistency. A Docker exit status of zero is not proof that an external dependency accepted the restored session.
Recovery
If restore fails, do not immediately remove the checkpoint. Keep it while you collect the daemon error, CRIU diagnostics and the container's state. You may be able to start the container normally with docker start "$CONTAINER_NAME", but only if its normal startup path is acceptable, and remember that this is not a checkpoint restore.
6. Remove an obsolete checkpoint
Destructive action
Removing a checkpoint cannot be undone through Docker. Only remove it after the restored container and its replacement recovery evidence have been checked.
$ docker checkpoint rm "$CONTAINER_NAME" "$CHECKPOINT_NAME"
before-maintenance-2026-09-23
$ docker checkpoint ls "$CONTAINER_NAME"
CHECKPOINT NAME ID
The final list should no longer include the removed checkpoint. If it does, check the container name and any custom --checkpoint-dir value. Never use broad filesystem deletion under Docker's data root as a substitute for this command.
Common traps
- Experimental daemon support. A current client does not enable the feature on the daemon. Treat the exact error as a capability check.
- Terminal-backed containers. Docker documents limitations for external terminals. A command that works for a detached test container may fail for one created with an attached terminal.
- Custom storage.
--checkpoint-dirmust be repeated for create, list and remove when you use it. Omitting it can make a valid checkpoint appear to be missing. - Destructive names. Checkpoint names are identifiers, not backups with automatic retention. Record them in the change notes and retain the one needed for recovery.
- Privilege confusion.
sudomay solve daemon access, but it cannot add CRIU support, repair an incompatible workload or make a missing checkpoint appear.
Done means
- Versions recorded. The connected daemon and CLI versions were noted, and experimental support was confirmed.
- Safe target chosen. A disposable running container was selected and its state checked before capture.
- Checkpoint exists. A named checkpoint was created and found with
docker checkpoint ls. - Restore worked. The container came back with
docker start --checkpoint, and its running state and application health were checked. - Cleanup was deliberate. Only an obsolete checkpoint was removed, using
docker checkpoint rmafter recovery was verified.