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.

Allow about twenty minutes for a first test. You need:

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.

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

Done means