Line 5: |
Line 5: |
| Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. | | Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. |
| | | |
− | == Docker 1.10 == | + | == Docker Experimental == |
| | | |
− | The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the <code>DOCKER_EXPERIMENTAL</code> build tag.
| + | Checkpoint & Restore is now available in the _experimental_ runtime mode for Docker. Simply start your docker daemon with '''--experimental''' to enable the feature. |
− | | |
− | To install, download the <code>docker-1.10.0-dev</code> binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:
| |
− | | |
− | $ docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock
| |
− | | |
− | The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:
| |
− | | |
− | $ docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top
| |
| | | |
| === Dependencies === | | === Dependencies === |
| | | |
− | In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of <code>ldd</code> on my system: | + | In addition to installing version 1.13 of Docker, you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of <code>ldd</code> on my system: |
| | | |
| $ ldd `which criu` | | $ ldd `which criu` |
Line 33: |
Line 25: |
| === checkpoint === | | === checkpoint === |
| | | |
− | Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. From this point forward, commands are show using '''docker''' instead of '''docker-dev-1.10''', but if you have not installed this version globally you can use the latter.
| + | There's a top level <code>checkpoint</code> sub-command in Docker, which lets you create a new checkpoint, and list or delete an existing checkpoint. These checkpoints are stored and managed by Docker, unless you specify a custom storage path. |
| + | |
| + | Here's an example of creating a checkpoint, from a container that simply logs an integer in a loop. |
| | | |
| First, we create container: | | First, we create container: |
Line 46: |
Line 40: |
| If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container: | | If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container: |
| | | |
− | $ docker checkpoint looper | + | $ docker checkpoint create looper checkpoint1 |
| | | |
| You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed. | | You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed. |
Line 52: |
Line 46: |
| === restore === | | === restore === |
| | | |
− | Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:
| + | Unlike creating a checkpoint, restoring from a checkpoint is just a flag provided to the normal container '''start''' call. Here's an example: |
| | | |
− | $ docker restore looper | + | $ docker start --checkpoint checkpoint1 looper |
| | | |
| If we then print the logs, you should see they start from where we left off and continue to increase. | | If we then print the logs, you should see they start from where we left off and continue to increase. |
Line 60: |
Line 54: |
| ==== Restoring into a '''new''' container ==== | | ==== Restoring into a '''new''' container ==== |
| | | |
− | Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the <code>--force</code> option, in conjunction with the <code>--image-dir</code> option. Here's a slightly revised example from before: | + | Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. This is done by providing a custom storage path with the <code>--checkpoint-dir</code> option. Here's a slightly revised example from before: |
| | | |
| $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox \ | | $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox \ |
Line 66: |
Line 60: |
| | | |
| # wait a few seconds to give the container an opportunity to print a few lines, then | | # wait a few seconds to give the container an opportunity to print a few lines, then |
− | $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2 | + | $ docker checkpoint create --checkpoint-dir=/tmp looper2 checkpoint2 |
| | | |
− | $ docker create --name looper-force --security-opt seccomp:unconfined busybox \ | + | $ docker create --name looper-clone --security-opt seccomp:unconfined busybox \ |
| /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done' | | /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done' |
| | | |
− | $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force | + | $ docker start --checkpoint-dir=/tmp --checkpoint=checkpoint2 looper-clone |
| | | |
| | | |
− | You should be able to print the logs from <code>looper-force</code> and see that they start from wherever the logs of <code>looper</code> end. | + | You should be able to print the logs from <code>looper-clone</code> and see that they start from wherever the logs of <code>looper</code> end. |
| | | |
| === usage === | | === usage === |
| | | |
− | # docker checkpoint --help
| + | Checkpoint |
− | Usage: docker checkpoint [OPTIONS] CONTAINER
| |
− |
| |
− | Checkpoint one or more running containers
| |
− |
| |
− | --help Print usage
| |
− | --image-dir directory for storing checkpoint image files
| |
− | --leave-running leave the container running after checkpoint
| |
− | --work-dir directory for storing log file
| |
| | | |
− | # docker restore --help
| + | # docker checkpoint create --help |
− | Usage: docker restore [OPTIONS] CONTAINER
| + | Usage: docker checkpoint create [OPTIONS] CONTAINER CHECKPOINT |
− |
| |
− | Restore one or more checkpointed containers
| |
− |
| |
− | --force bypass checks for current container state
| |
− | --help Print usage
| |
− | --image-dir directory to restore image files from
| |
− | --work-dir directory for restore log
| |
| | | |
− | == Docker 1.12 ==
| + | Create a checkpoint from a running container |
| | | |
− | More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env <code>DOCKER_EXPERIMENTAL=1</code>.
| + | Options: |
| + | --checkpoint-dir string Use a custom checkpoint storage directory |
| + | --help Print usage |
| + | --leave-running Leave the container running after checkpoint |
| | | |
− | The command line interface has changed from the 1.10 version. <code>docker checkpoint</code> is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the <code>docker checkpoint create</code> command, which takes <code>container_id</code> and <code>checkpoint_id</code> as non-optional arguments. Example:
| + | Restore |
| | | |
− | docker checkpoint create my_container my_first_checkpoint
| + | # docker start --help |
| + | Usage: docker start [OPTIONS] CONTAINER [CONTAINER...] |
| | | |
− | Restoring a container is now performed just as an option to <code>docker start</code>. Although typically you may create and start a container in a single step using <code>docker run</code>, under the hood this is actually two steps: <code>docker create</code> followed by <code>docker start</code>. You can also call <code>start</code> on a container that was previously running and has since been stopped or killed. That looks something like this:
| + | Start one or more stopped containers |
| | | |
− | docker start --checkpoint my_first_checkpoint my_container
| + | Options: |
| + | -a, --attach Attach STDOUT/STDERR and forward signals |
| + | --checkpoint string Restore from this checkpoint |
| + | --checkpoint-dir string Use a custom checkpoint storage directory |
| + | --detach-keys string Override the key sequence for detaching a container |
| + | --help Print usage |
| + | -i, --interactive Attach container's STDIN |
| | | |
| == Integration Status == | | == Integration Status == |