Duplicating docker container for debugging

currently broken again

below only works with version from around Dec 20 '17. I have not yet looked into this after Jan 18.

docker commit is fine for saving file changes into a new image, but it will not preserve changes in memory, open processes etc. Contrary to the popular opinion, the latter is feasible with docker checkpoint. Documentation and example.

Note: right now, the --checkpoint-dir option is broken: issue, pull. That is why a workaround like checkpoint_dir (see code) is necessary here. This answer should probably be updated in a few weeks.

It is not possible to checkpoint a TTY. This might change soon. However, you can attach a new TTY after the restoring process using exec.

You need to have criu installed. After, first,

echo "{\"experimental\": true}" >> /etc/docker/daemon.json
systemctl restart docker

, then

#!/bin/bash

# tty (-t) not supported
docker run -i -d --name sleeper\
     busybox sh -c 'sleep 10000'

# Makes a snapshot and stops the container (except if --leave-running is active). --checkpoint-dir is broken.
docker checkpoint create sleeper cp
# sleeper container exited

# Create the clone
docker create -i --rm --name clone\
    busybox

# Start the clone
checkpoint_dir="/var/lib/docker/containers/$(docker ps -aq --no-trunc -f name=sleeper)/checkpoints"
docker start --checkpoint-dir=$checkpoint_dir --checkpoint=cp clone

# Attach new TTY
docker exec -it clone sh

Now in the tty, type ps -e and you will see the process which started in the sleeper container and now continues in the clone.

checkpoint makes a complete blueprint of the container to hard drive, exchangable between machines. This feature uses criu and is experimental. Criu cannot create a blueprint of X11 applications natively.

pause on the other hand only freezes the container internally. There is nothing you can do with a paused container other than unpause it.


  1. Create a base image and run it

    docker run -it <base_image> /bin/bash
    
  2. Make necessary changes

    yum install ping
    
  3. Commit it with a new name

    docker commit <hash tag of running container> new_image
    

Now if you open new_image by running

docker run -it new_image /bin/bash

You can see ping is installed in it.

Open base_image and there is no ping installed in it.

Hope it answered your question.


If you want to save your modifications, you can use docker commit, see the doc http://docs.docker.com/reference/commandline/cli/#commit and you can also save a container, http://docs.docker.com/reference/commandline/cli/#save

Tags:

Docker