<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://criu.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Saied+Kazemi</id>
	<title>CRIU - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://criu.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Saied+Kazemi"/>
	<link rel="alternate" type="text/html" href="https://criu.org/Special:Contributions/Saied_Kazemi"/>
	<updated>2026-05-13T17:41:38Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.6</generator>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2529</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2529"/>
		<updated>2015-07-16T18:01:44Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
{{Note| This page was originally written a few months ago.  Since then, interfacing with CRIU has been added to Docker's native exec driver (libcontainer) and pull requests to add checkpoint/restore functionality to Docker have been submitted.  If you just want to experiment with C/R, you can use one of the following Docker versions for your C/R experiments: &lt;br /&gt;
&lt;br /&gt;
Docker 1.5 [https://github.com/SaiedKazemi/docker/wiki]&lt;br /&gt;
Docker 1.7 [https://github.com/boucher/docker/tree/cr-combined]}}&lt;br /&gt;
&lt;br /&gt;
{{Note| The OverlayFS filesystem was merged into the upstream Linux kernel 3.18 and is now Docker's preferred filesystem (instead of AUFS).  However, there is a bug in OverlayFS that reports the wrong mnt_id in /proc/&amp;lt;pid&amp;gt;/fdinfo/&amp;lt;fd&amp;gt; and the wrong symlink target path for /proc/&amp;lt;pid&amp;gt;/&amp;lt;fd&amp;gt;.  Fortunately, these bugs have been fixed in the kernel v4.2-rc2.  See below for instructions on how to apply the relevant patches.}}&lt;br /&gt;
&lt;br /&gt;
{{Note| If your process uses async IO and your kernel is older than 3.19, you need to apply two patches.  See below for instructions.}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''1. External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done for any process tree.&lt;br /&gt;
&lt;br /&gt;
This approach is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
'''2. Native C/R''' using new &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
This approach is called native because the Docker daemon is involved in both checkpoint and restore.&lt;br /&gt;
Therefore, its notion of the container state will be corrent.  All commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.&lt;br /&gt;
You can watch this short demo&lt;br /&gt;
'''[https://www.youtube.com/watch?v=HFt9v6yqsXo video]'''&lt;br /&gt;
to see how it works.&lt;br /&gt;
Source files for Docker 1.5 C/R are&lt;br /&gt;
'''[https://github.com/SaiedKazemi/docker/tree/cr here]'''&lt;br /&gt;
and for Docker 1.7 C/R are&lt;br /&gt;
'''[https://github.com/boucher/docker/tree/cr-combined here]'''.&lt;br /&gt;
The '''[https://github.com/SaiedKazemi/docker/wiki wiki]'''&lt;br /&gt;
page provides an overview of the project history.&lt;br /&gt;
&lt;br /&gt;
== OverlayFS ==&lt;br /&gt;
&lt;br /&gt;
The following small kernel patches fix the mount id and symlink target path issues noted above:&lt;br /&gt;
&lt;br /&gt;
* {{torvalds.git|155e35d4da}} by David Howells&lt;br /&gt;
* {{torvalds.git|df1a085af1}} by David Howells&lt;br /&gt;
* {{torvalds.git|f25801ee46}} by David Howells&lt;br /&gt;
* {{torvalds.git|4bacc9c923}} by David Howells&lt;br /&gt;
* {{torvalds.git|9391dd00d1}} by Al Viro&lt;br /&gt;
&lt;br /&gt;
Assuming that you are running Ubuntu Vivid (Linux kernel 3.19), here is how you can patch your kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone  git://kernel.ubuntu.com/ubuntu/ubuntu-vivid.git&lt;br /&gt;
cd ubuntu-vivid&lt;br /&gt;
git remote add torvalds  git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git&lt;br /&gt;
git remote update&lt;br /&gt;
&lt;br /&gt;
git cherry-pick 155e35d4da&lt;br /&gt;
git cherry-pick df1a085af1&lt;br /&gt;
git cherry-pick f25801ee46&lt;br /&gt;
git cherry-pick 4bacc9c923&lt;br /&gt;
git cherry-pick 9391dd00d1&lt;br /&gt;
&lt;br /&gt;
cp /boot/config-$(uname -r) .config&lt;br /&gt;
make olddefconfig&lt;br /&gt;
make -j 8 bzImage modules&lt;br /&gt;
sudo make install modules_install&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Async IO (AIO) ==&lt;br /&gt;
&lt;br /&gt;
If you are using a kernel older than 3.19 and your container uses AIO, you need the following AIO kernel patches from 3.19:&lt;br /&gt;
&lt;br /&gt;
* {{torvalds.git|bd9b51e79c}} by Al Viro&lt;br /&gt;
* {{torvalds.git|e4a0d3e720}} by Pavel Emelyanov&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
{{Note| External C/R was done as proof-of-concept.  Its use is discouraged and the helper script mentioned below will be deprecated in the near future.}}&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it is possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
&amp;lt;code&amp;gt;/proc/''pid''/map_files&amp;lt;/code&amp;gt;, option &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt;&lt;br /&gt;
is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up &amp;lt;code&amp;gt;/etc/{hostname,hosts,resolv.conf}&amp;lt;/code&amp;gt; as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount &amp;lt;code&amp;gt;/.dockerinit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, &amp;lt;code&amp;gt;/etc/hostname&amp;lt;/code&amp;gt;&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at &amp;lt;code&amp;gt;/var/lib/docker/containers/''container_id''/hostname&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;/dev/stdin&amp;lt;/code&amp;gt; for detached containers&lt;br /&gt;
(i.e., &amp;lt;code&amp;gt;docker run -d ...&amp;lt;/code&amp;gt;).  Since earlier versions of Docker used&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; and the container &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; as the same device.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
For native C/R support, this option tells CRIU to let the restored process &amp;quot;inherit&amp;quot;&lt;br /&gt;
its specified file descriptor (instead of restoring from checkpoint).&lt;br /&gt;
&lt;br /&gt;
== Restore Prework for External C/R ==&lt;br /&gt;
&lt;br /&gt;
Docker supports many storage drivers (AKA graph drivers) including&lt;br /&gt;
AUFS, Btrfs, ZFS, DeviceMapper, OverlayFS, and VFS.  The user can&lt;br /&gt;
specify his/her desired storage driver via the &amp;lt;code&amp;gt;DOCKER_DRIVER&amp;lt;/code&amp;gt;&lt;br /&gt;
environment variable or the &amp;lt;code&amp;gt;-s (--storage-driver)&amp;lt;/code&amp;gt; command&lt;br /&gt;
line option.&lt;br /&gt;
&lt;br /&gt;
Currently C/R can only be done on containers using either AUFS, OverlayFS, or VFS.&lt;br /&gt;
In the following example, we assume AUFS.&lt;br /&gt;
&lt;br /&gt;
When Docker notices that the container has exited (due to CRIU dump),&lt;br /&gt;
it dismantles the container's filesystem.  We need to set up the container's&lt;br /&gt;
filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An External C/R Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External C/R Helper Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify &amp;lt;code&amp;gt;-v&amp;lt;/code&amp;gt; to see the commands that &amp;lt;code&amp;gt;docker_cr.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log \&lt;br /&gt;
     --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
     -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     -o restore.log --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
     -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Upstream_kernel_commits&amp;diff=2528</id>
		<title>Upstream kernel commits</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Upstream_kernel_commits&amp;diff=2528"/>
		<updated>2015-07-16T17:36:59Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Like}}&lt;br /&gt;
&lt;br /&gt;
== Pending patches ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Reference&lt;br /&gt;
! Description&lt;br /&gt;
! Status&lt;br /&gt;
|-&lt;br /&gt;
|[http://lists.openvz.org/pipermail/criu/2014-April/013655.html 013655] || tcp: allow to repair a tcp connections in closing states || ?&lt;br /&gt;
|-&lt;br /&gt;
|[http://lwn.net/Articles/633622/ 633622] || [RFC] kernel: add a netlink interface to get information about processes || ?&lt;br /&gt;
|-&lt;br /&gt;
|[https://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/commit/?h=seccomp/tip&amp;amp;id=352871545768dcb0cb2fe7065eea4101ce026e7d seccomp/tip/35287154] || seccomp: add ptrace options for suspend/resume || In maintainer's tree&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Merged patches ==&lt;br /&gt;
&lt;br /&gt;
This table lists CRIU-related kernel commits already merged to vanilla.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; class=&amp;quot;unsortable&amp;quot; | Commit&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; class=&amp;quot;unsortable&amp;quot; | Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; | Kernel version&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|7773fbc541}} || procfs: make proc_get_link to use dentry instead of inode || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|640708a2cff}} || procfs: introduce the /proc/&amp;lt;pid&amp;gt;/map_files/ directory || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|067bce1a06}} || c/r: introduce CHECKPOINT_RESTORE symbol || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|028ee4be34}} || c/r: prctl: add PR_SET_MM codes to set up mm_struct entries || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b3f7f573a2}} || c/r: procfs: add start_data, end_data, start_brk members to /proc/$pid/stat v4 || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b8f566b04d}} || sysctl: add the kernel.ns_last_pid control || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|c9da99e647}} || unix_diag: Fixup RQLEN extension report || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|885ee74d5d}} || af_unix: Move CINQ/COUTQ code to helpers || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|257b529876}} || unix_diag: Add the MEMINFO extension || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|c0636faa53}} || inet_diag: Add the SKMEMINFO extension || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|5d2e5f274f}} || sock_diag: Introduce the meminfo nla core (v2) || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|288461e154}} || unix_diag: Include unix_diag.h into header-y target || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|e6fe2371bd}} || sock_diag: Arrange sock_diag.h such that it is exportable to userspace || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|e09e9d189b}} || unix: If we happen to find peer NULL when diag dumping, write zero. || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|3b0723c12e}} || unix_diag: Fix incoming connections nla length  || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|2ea744a583}} || net: unix -- Add missing module.h inclusion || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|5d531aaa64}} || unix_diag: Write it into kbuild || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|cbf391958a}} || unix_diag: Receive queue lenght NLA || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|2aac7a2cb0}} || unix_diag: Pending connections IDs NLA || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|ac02be8d96}} || unix_diag: Unix peer inode NLA || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|5f7b056946}} || unix_diag: Unix inode info NLA || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|f5248b48a6}} || unix_diag: Unix socket name NLA || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|5d3cae8bc3}} || unix_diag: Dumping exact socket core || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|45a96b9be6}} || unix_diag: Dumping all sockets core || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|22931d3b90}} || unix_diag: Basic module skeleton || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|fa7ff56f75}} || af_unix: Export stuff required for diag module || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|f65c1b534b}} || sock_diag: Generalize requests cookies managements || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|aec8dc62f6}} || sock_diag: Fix module netlink aliases || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|e7c466e58e}} || sock_diag: Move the SOCK_DIAG_BY_FAMILY cmd declaration || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|86e62ad6b2}} || udp_diag: Fix the !ipv6 case || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|b872a2371f}} || udp_diag: Make it module when ipv6 is a module || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|507dd7961e}} || udp_diag: Wire the udp_diag module into kbuild || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|b6d640c228}} || udp_diag: Implement the dump-all functionality || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|a925aa00a5}} || udp_diag: Implement the get_exact dumping functionality || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|52b7c59bc3}} || udp_diag: Basic skeleton || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|fce823381e}} || udp: Export code sk lookup routines || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|1942c518ca}} || inet_diag: Generalize inet_diag dump and get_exact calls || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|3c4d05c805}} || inet_diag: Introduce the inet socket dumping routine || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|8d07d1518a}} || inet_diag: Introduce the byte-code run on an inet socket || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|efb3cb428d}} || inet_diag: Split inet_diag_get_exact into parts || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|476f7dbff3}} || inet_diag: Split inet_diag_get_exact into parts || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|b005ab4ef8}} || inet_diag: Export inet diag cookie checking routine || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|87c22ea52e}} || inet_diag: Reduce the number of args for bytecode run routine || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|7b35eadd7e}} || inet_diag: Remove indirect sizeof from inet diag handlers || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|8ef874bfc7}} || sock_diag: Move the sock_ code to net/core/ || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|a029fe26b6}} || inet_diag: Cleanup type2proto last user || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|d23deaa07b}} || inet_diag: Introduce socket family checks || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|25c4cd2b6d}} || inet_diag: Switch the _dump to work with new header || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|fe50ce2846}} || inet_diag: Switch the _get_exact to work with new header || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|126fdc3249}} || inet_diag: Introduce new inet_diag_req header || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|d366477a52}} || sock_diag: Initial skeleton || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|f13c95f0e2}} || inet_diag: Switch from _GETSOCK to IPPROTO_ numbers || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|37f352b5e3}} || inet_diag: Move byte-code finding up the call-stack || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|8d34172dfd}} || sock_diag: Introduce new message type || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|818411616b}} || fs, proc: Introduce /proc/&amp;lt;pid&amp;gt;/task/&amp;lt;tid&amp;gt;/children entry v9 || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|5b172087f9}} || c/r: procfs: add arg_start/end, env_start/end and exit_code members || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|fe8c7f5cbf}} || c/r: prctl: Extend PR_SET_MM to set up more mm_struct entries || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|d97b46a646}} || syscalls, x86: Add __NR_kcmp syscall || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b32dfe3771}} || c/r: prctl: Add ability to set new mm_struct::exe_file || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|79f0713d40}} || prctl: Use CAP_SYS_RESOURCE for PR_SET_MM option || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|300f786b26}} || prctl: add ability to get clear_tid_address || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|4934b0329f}} || datagram: Factor out sk queue referencing || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|3f518bf745}} || datagram: Add offset argument to __skb_recv_datagram || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|da5ef6e51b}} || skb: Add skb_peek_next helper || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ef64a54f6e}} || sock: Introduce the SO_PEEK_OFF sock option || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|f55bb7f9cb}} || unix: Support peeking offset for datagram and seqpacket sockets || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|fc0d753641}} || unix: Support peeking offset for stream sockets || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|1d151c337d}} || fcntl: Add F_GETOWNER_UIDS option v3 || 3.6&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|370816aef0}} || tcp: Move code around || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ee9952831c}} || tcp: Initial repair mode || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c0e88ff0f2}} || tcp: Repair socket queues || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|5e6a3ce657}} || tcp: Report mss_clamp with TCP_MAXSEG option in repair mode || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b139ba4e90}} || tcp: Repair connection-time negotiated parameters || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|de248a75c3}} || tcp repair: Fix unaligned access when repairing options (v2) || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|736f24d5e5}} || c/r: prctl: Drop VMA flags test on PR_SET_MM_ stack data assignment || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|5702c5eeab}} || c/r: prctl: Move PR_GET_TID_ADDRESS to a proper place || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|16fbdce62d}} || proc: report file/anon bit in /proc/pid/pagemap || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|bca1554373}} || proc/smaps: show amount of nonlinear ptes in vma || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b14f243a42}} || net: Dont use ifindices in hash fns || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9c7dafbfab}} || net: Allow to create links with given ifindex || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e6f8f1a739}} || veth: Allow to create peer link with given ifindex || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|aa79e66eee}} || net: Make ifindex generation per-net namespace || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|1fb9489bf1}} || net: Loopback ifindex is constant now || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|faf60af17f}} || procfs: Move /proc/pid/fd[info] handling code to fd.[ch] || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ddd3e0771b}} || procfs: Convert /proc/pid/fdinfo/ handling routines to seq-file || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|55985dd72a}} || procfs: Add ability to plug in auxiliary fdinfo providers || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|cbac5542d4}} || fs, eventfd: Add procfs fdinfo helper || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|138d22b586}} || fs, epoll: Add procfs fdinfo helper v2 || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|711c7bf991}} || fs, exportfs: Add export_encode_inode_fh helper || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|be77196b80}} || fs, notify: Add procfs fdinfo helper || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e6dbcafb74}} || fs, fanotify: Add @mflags field to fanotify output || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|2787b04b6c}} || packet: Introduce net/packet/internal.h header || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|96ec632714}} || packet: Diag core and basic socket info dumping || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|8a360be0c5}} || packet: Report more packet sk info via diag module || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|eea68e2f1a}} || packet: Report socket mclist info via diag module || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|16f01365fa}} || packet: Report rings cfg via diag engine || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|fff3321d75}} || packet: Report fanout status via diag engine || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|0fa7fa98db}} || packet: Protect packet sk list with mutex (v2) || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|579035dc5d}} || kernel: limit a value of ns_last_pid to (0, max_pid) || 3.6&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|bc26ccd8fc}} || tcp: restore rcv_wscale in a repair mode (v2) || 3.6&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|f7b86bfe8d}} || sockopt: Make SO_BINDTODEVICE readable || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e4e541a848}} || sock-diag: Report shutdown for inet and unix sockets (v2) || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|834f82e2aa}} || procfs: add VmFlags field in smaps output || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|06026d911c}} || tty: pty - Move TIOCPKT handling into pty.c || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c6298038bc}} || tty, ioctls -- Add new ioctl definitions for tty flags fetching || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|84fd7bdf12}} || tty: Add get- ioctls to fetch tty status v3 || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|a8fc927780}} || sk-filter: Add ability to get socket filter program (v2) || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|cacb6ba0f3}} || net: inet_diag -- Return error code if protocol handler is missed || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c454e6111d}} || tcp-repair: Handle zero-length data put in rcv queue || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ec34232575}} || tcp: fix retransmission in repair mode || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|2b9164771e}} || ipv6: adapt connect for repair move || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c91f6df2db}} || sockopt: Change getsockopt() of SO_BINDTODEVICE to return an interface name || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|3fcfe78658}} || ipc: add more comments to message copying related code || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|51eeacaa07}} || ipc: simplify message copying || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b30efe2775}} || ipc: convert prepare_copy() from macro to function || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|85398aa8de}} || ipc: simplify free_copy() call || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|3a665531a3}} || selftests: IPC message queue copy feature test || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|4a674f34ba}} || ipc: introduce message queue copy feature || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|f9dd87f473}} || ipc: message queue receive cleanup || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|03f5956680}} || ipc: add sysctl to specify desired next object id || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9afdacda02}} || ipc: remove forced assignment of selected message || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|3f7d1fe108}} || arm: Wire up kcmp syscall || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|1e142b29e2}} || kcmp: make it depend on CHECKPOINT_RESTORE || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ceaa1fef65}} || tcp: adding a per-socket timestamp offset || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|93be6ce0e9}} || tcp: set and get per-socket timestamp || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ee684b6f28}} || tcp: send packets with a socket timestamp || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|66dd34ad}} || signal: allow to send any siginfo to itself || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ae5fc987}} || net: fix *_DIAG_MAX constants || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|0f29c768}} || net: prepare netlink code for netlink diag || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|eaaa3139}} || netlink: Diag core and basic socket info dumping (v2) || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|84c751bd}} || ptrace: add ability to retrieve signals without removing from a queue (v4) || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|040fa020}} || clear_refs: Sanitize accepted commands declaration || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|af9de7eb}} || clear_refs: Introduce private struct for mm_walk || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|2b0a9f01}} || pagemap-introduce-pagemap_entry_t-without-pmshift-bits || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|0f8975ec}} || mm: soft-dirty bits for user memory changes tracking || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|541c237c}} || pagemap: prepare to reuse constant bits with page-shift || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|57b8015e}} || posix-timers: Show sigevent info in proc file || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|48f6a7a5}} || posix-timers: Introduce /proc/PID/timers file || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|5ed67f05}} || posix timers: Allocate timer id per process (v2) || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|15ef0298}} || posix-timers: Show clock ID in proc file || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|29000cae}} || ptrace: add ability to get/set signal-blocked mask (v2) || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|274038f8}} || tun: Report &amp;quot;persist&amp;quot; flag to userspace || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|179ef71c}} || mm: Save soft-dirty bits on swapped pages || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|41bb3476}} || mm: Save soft-dirty bits on file pages || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|76975e9c}} || tun: Get skfilter layout || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|849c9b6f}} || tun: Allow to skip filter on attach || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|3d407a80}} || tun: Report whether the queue is attached or not || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|fb7589a1}} || tun: Add ability to create tun device with given index || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e3e12028}} || tcp: don't apply tsoffset if rcv_tsecr is zero || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c7781a6e}} || tcp: initialize rcv_tstamp for restored sockets || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|7ed5c5ae}} || tcp: set timestamps for restored skb-s || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|6dec97dc}} || mm: move_ptes -- Set soft dirty bit depending on pte type || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c3d16e16}} || mm: migration -- Do not loose soft dirty bit if page is in migration state || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e9cdd6e7}} || mm: pagemap -- Inspect _PAGE_SOFT_DIRTY only on present pages || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|dbde4979}} || tcp: don't update snd_nxt, when a socket is switched from repair mode || 3.13&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|d9104d1c}} || mm: track vma changes with VM_SOFTDIRTY bit || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|34228d47}} || mm: Ignore VM_SOFTDIRTY on VMA merging || 3.14, 3.13-stable&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|24f91eba1}} || mm: don't lose the SOFT_DIRTY flag on mprotect || 3.14, 3.13-stable&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|49d063cb3}} || proc: show mnt_id in /proc/pid/fdinfo || 3.15&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|0bf073315}} || mm: Make freshly remapped file pages being softdirty unconditionally || 3.15&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9aed8614a}} || mm: Don't forget to set softdirty on file mapped fault || 3.17&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b43790eed}} || mm: Don't forget to save file map softdiry bit on unmap || 3.15&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c86c97ff4}} || mm: Clear VM_SOFTDIRTY flag inside clear_refs_write instead of clear_soft_dirty || 3.15&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|af9c4957c}} || timerfd: Implement show_fdinfo method || 3.17&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|854d06d9f}} || docs: Procfs -- Document timerfd output || 3.17&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|5442e9fbd}} || timerfd: Implement timerfd_ioctl method to restore timerfd_ctx::ticks, v3 || 3.17&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|64e455079}} || mm: softdirty: enable write notifications on VMAs after VM_SOFTDIRTY cleared || 3.18&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9c5990240}} || mm: introduce check_data_rlimit helper || 3.18&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|8764b338b}} || mm: use may_adjust_brk helper || 3.18&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|71fe97e18}} || prctl: PR_SET_MM -- factor out mmap_sem when updating mm::exe_file || 3.18&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|f606b77f1}} || prctl: PR_SET_MM -- introduce PR_SET_MM_MAP operation || 3.18&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9183df25f}} || shm: add memfd_create() syscall || 3.17&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e4a0d3e72}} || aio: Make it possible to remap aio ring || 3.19&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|6c8c90319}} || proc: show locks in /proc/pid/fdinfo/X || 4.1&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|155e35d4d}} || VFS: Introduce inode-getting helpers for layered/unioned fs environments || 4.0&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|df1a085af}} || VFS: Add a fallthrough flag for marking virtual dentries || 4.0&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|f25801ee4}} || overlay: Call ovl_drop_write() earlier in ovl_dentry_open() || 4.2-rc2&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|4bacc9c92}} || overlayfs: Make f_path always point to the overlay and f_inode to the underlay || 4.2-rc2&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9391dd00d}} || fix a braino in ovl_d_select_inode() || 4.2-rc2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Upstream_kernel_commits&amp;diff=2527</id>
		<title>Upstream kernel commits</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Upstream_kernel_commits&amp;diff=2527"/>
		<updated>2015-07-16T17:36:16Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Like}}&lt;br /&gt;
&lt;br /&gt;
== Pending patches ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Reference&lt;br /&gt;
! Description&lt;br /&gt;
! Status&lt;br /&gt;
|-&lt;br /&gt;
|[http://lists.openvz.org/pipermail/criu/2014-April/013655.html 013655] || tcp: allow to repair a tcp connections in closing states || ?&lt;br /&gt;
|-&lt;br /&gt;
|[http://lwn.net/Articles/633622/ 633622] || [RFC] kernel: add a netlink interface to get information about processes || ?&lt;br /&gt;
|-&lt;br /&gt;
|[https://git.kernel.org/cgit/linux/kernel/git/kees/linux.git/commit/?h=seccomp/tip&amp;amp;id=352871545768dcb0cb2fe7065eea4101ce026e7d seccomp/tip/35287154] || seccomp: add ptrace options for suspend/resume || In maintainer's tree&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Merged patches ==&lt;br /&gt;
&lt;br /&gt;
This table lists CRIU-related kernel commits already merged to vanilla.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; class=&amp;quot;unsortable&amp;quot; | Commit&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; class=&amp;quot;unsortable&amp;quot; | Description&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; | Kernel version&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|7773fbc541}} || procfs: make proc_get_link to use dentry instead of inode || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|640708a2cff}} || procfs: introduce the /proc/&amp;lt;pid&amp;gt;/map_files/ directory || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|067bce1a06}} || c/r: introduce CHECKPOINT_RESTORE symbol || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|028ee4be34}} || c/r: prctl: add PR_SET_MM codes to set up mm_struct entries || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b3f7f573a2}} || c/r: procfs: add start_data, end_data, start_brk members to /proc/$pid/stat v4 || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b8f566b04d}} || sysctl: add the kernel.ns_last_pid control || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|c9da99e647}} || unix_diag: Fixup RQLEN extension report || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|885ee74d5d}} || af_unix: Move CINQ/COUTQ code to helpers || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|257b529876}} || unix_diag: Add the MEMINFO extension || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|c0636faa53}} || inet_diag: Add the SKMEMINFO extension || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|5d2e5f274f}} || sock_diag: Introduce the meminfo nla core (v2) || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|288461e154}} || unix_diag: Include unix_diag.h into header-y target || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|e6fe2371bd}} || sock_diag: Arrange sock_diag.h such that it is exportable to userspace || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|e09e9d189b}} || unix: If we happen to find peer NULL when diag dumping, write zero. || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|3b0723c12e}} || unix_diag: Fix incoming connections nla length  || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|2ea744a583}} || net: unix -- Add missing module.h inclusion || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|5d531aaa64}} || unix_diag: Write it into kbuild || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|cbf391958a}} || unix_diag: Receive queue lenght NLA || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|2aac7a2cb0}} || unix_diag: Pending connections IDs NLA || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|ac02be8d96}} || unix_diag: Unix peer inode NLA || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|5f7b056946}} || unix_diag: Unix inode info NLA || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|f5248b48a6}} || unix_diag: Unix socket name NLA || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|5d3cae8bc3}} || unix_diag: Dumping exact socket core || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|45a96b9be6}} || unix_diag: Dumping all sockets core || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|22931d3b90}} || unix_diag: Basic module skeleton || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|fa7ff56f75}} || af_unix: Export stuff required for diag module || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|f65c1b534b}} || sock_diag: Generalize requests cookies managements || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|aec8dc62f6}} || sock_diag: Fix module netlink aliases || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|e7c466e58e}} || sock_diag: Move the SOCK_DIAG_BY_FAMILY cmd declaration || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|86e62ad6b2}} || udp_diag: Fix the !ipv6 case || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|b872a2371f}} || udp_diag: Make it module when ipv6 is a module || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|507dd7961e}} || udp_diag: Wire the udp_diag module into kbuild || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|b6d640c228}} || udp_diag: Implement the dump-all functionality || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|a925aa00a5}} || udp_diag: Implement the get_exact dumping functionality || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|52b7c59bc3}} || udp_diag: Basic skeleton || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|fce823381e}} || udp: Export code sk lookup routines || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|1942c518ca}} || inet_diag: Generalize inet_diag dump and get_exact calls || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|3c4d05c805}} || inet_diag: Introduce the inet socket dumping routine || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|8d07d1518a}} || inet_diag: Introduce the byte-code run on an inet socket || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|efb3cb428d}} || inet_diag: Split inet_diag_get_exact into parts || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|476f7dbff3}} || inet_diag: Split inet_diag_get_exact into parts || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|b005ab4ef8}} || inet_diag: Export inet diag cookie checking routine || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|87c22ea52e}} || inet_diag: Reduce the number of args for bytecode run routine || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|7b35eadd7e}} || inet_diag: Remove indirect sizeof from inet diag handlers || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|8ef874bfc7}} || sock_diag: Move the sock_ code to net/core/ || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|a029fe26b6}} || inet_diag: Cleanup type2proto last user || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|d23deaa07b}} || inet_diag: Introduce socket family checks || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|25c4cd2b6d}} || inet_diag: Switch the _dump to work with new header || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|fe50ce2846}} || inet_diag: Switch the _get_exact to work with new header || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|126fdc3249}} || inet_diag: Introduce new inet_diag_req header || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|d366477a52}} || sock_diag: Initial skeleton || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|f13c95f0e2}} || inet_diag: Switch from _GETSOCK to IPPROTO_ numbers || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|37f352b5e3}} || inet_diag: Move byte-code finding up the call-stack || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{net-next.git|8d34172dfd}} || sock_diag: Introduce new message type || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|818411616b}} || fs, proc: Introduce /proc/&amp;lt;pid&amp;gt;/task/&amp;lt;tid&amp;gt;/children entry v9 || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|5b172087f9}} || c/r: procfs: add arg_start/end, env_start/end and exit_code members || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|fe8c7f5cbf}} || c/r: prctl: Extend PR_SET_MM to set up more mm_struct entries || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|d97b46a646}} || syscalls, x86: Add __NR_kcmp syscall || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b32dfe3771}} || c/r: prctl: Add ability to set new mm_struct::exe_file || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|79f0713d40}} || prctl: Use CAP_SYS_RESOURCE for PR_SET_MM option || 3.3&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|300f786b26}} || prctl: add ability to get clear_tid_address || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|4934b0329f}} || datagram: Factor out sk queue referencing || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|3f518bf745}} || datagram: Add offset argument to __skb_recv_datagram || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|da5ef6e51b}} || skb: Add skb_peek_next helper || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ef64a54f6e}} || sock: Introduce the SO_PEEK_OFF sock option || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|f55bb7f9cb}} || unix: Support peeking offset for datagram and seqpacket sockets || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|fc0d753641}} || unix: Support peeking offset for stream sockets || 3.4&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|1d151c337d}} || fcntl: Add F_GETOWNER_UIDS option v3 || 3.6&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|370816aef0}} || tcp: Move code around || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ee9952831c}} || tcp: Initial repair mode || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c0e88ff0f2}} || tcp: Repair socket queues || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|5e6a3ce657}} || tcp: Report mss_clamp with TCP_MAXSEG option in repair mode || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b139ba4e90}} || tcp: Repair connection-time negotiated parameters || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|de248a75c3}} || tcp repair: Fix unaligned access when repairing options (v2) || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|736f24d5e5}} || c/r: prctl: Drop VMA flags test on PR_SET_MM_ stack data assignment || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|5702c5eeab}} || c/r: prctl: Move PR_GET_TID_ADDRESS to a proper place || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|16fbdce62d}} || proc: report file/anon bit in /proc/pid/pagemap || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|bca1554373}} || proc/smaps: show amount of nonlinear ptes in vma || 3.5&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b14f243a42}} || net: Dont use ifindices in hash fns || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9c7dafbfab}} || net: Allow to create links with given ifindex || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e6f8f1a739}} || veth: Allow to create peer link with given ifindex || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|aa79e66eee}} || net: Make ifindex generation per-net namespace || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|1fb9489bf1}} || net: Loopback ifindex is constant now || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|faf60af17f}} || procfs: Move /proc/pid/fd[info] handling code to fd.[ch] || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ddd3e0771b}} || procfs: Convert /proc/pid/fdinfo/ handling routines to seq-file || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|55985dd72a}} || procfs: Add ability to plug in auxiliary fdinfo providers || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|cbac5542d4}} || fs, eventfd: Add procfs fdinfo helper || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|138d22b586}} || fs, epoll: Add procfs fdinfo helper v2 || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|711c7bf991}} || fs, exportfs: Add export_encode_inode_fh helper || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|be77196b80}} || fs, notify: Add procfs fdinfo helper || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e6dbcafb74}} || fs, fanotify: Add @mflags field to fanotify output || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|2787b04b6c}} || packet: Introduce net/packet/internal.h header || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|96ec632714}} || packet: Diag core and basic socket info dumping || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|8a360be0c5}} || packet: Report more packet sk info via diag module || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|eea68e2f1a}} || packet: Report socket mclist info via diag module || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|16f01365fa}} || packet: Report rings cfg via diag engine || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|fff3321d75}} || packet: Report fanout status via diag engine || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|0fa7fa98db}} || packet: Protect packet sk list with mutex (v2) || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|579035dc5d}} || kernel: limit a value of ns_last_pid to (0, max_pid) || 3.6&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|bc26ccd8fc}} || tcp: restore rcv_wscale in a repair mode (v2) || 3.6&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|f7b86bfe8d}} || sockopt: Make SO_BINDTODEVICE readable || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e4e541a848}} || sock-diag: Report shutdown for inet and unix sockets (v2) || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|834f82e2aa}} || procfs: add VmFlags field in smaps output || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|06026d911c}} || tty: pty - Move TIOCPKT handling into pty.c || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c6298038bc}} || tty, ioctls -- Add new ioctl definitions for tty flags fetching || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|84fd7bdf12}} || tty: Add get- ioctls to fetch tty status v3 || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|a8fc927780}} || sk-filter: Add ability to get socket filter program (v2) || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|cacb6ba0f3}} || net: inet_diag -- Return error code if protocol handler is missed || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c454e6111d}} || tcp-repair: Handle zero-length data put in rcv queue || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ec34232575}} || tcp: fix retransmission in repair mode || 3.7&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|2b9164771e}} || ipv6: adapt connect for repair move || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c91f6df2db}} || sockopt: Change getsockopt() of SO_BINDTODEVICE to return an interface name || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|3fcfe78658}} || ipc: add more comments to message copying related code || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|51eeacaa07}} || ipc: simplify message copying || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b30efe2775}} || ipc: convert prepare_copy() from macro to function || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|85398aa8de}} || ipc: simplify free_copy() call || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|3a665531a3}} || selftests: IPC message queue copy feature test || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|4a674f34ba}} || ipc: introduce message queue copy feature || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|f9dd87f473}} || ipc: message queue receive cleanup || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|03f5956680}} || ipc: add sysctl to specify desired next object id || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9afdacda02}} || ipc: remove forced assignment of selected message || 3.8&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|3f7d1fe108}} || arm: Wire up kcmp syscall || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|1e142b29e2}} || kcmp: make it depend on CHECKPOINT_RESTORE || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ceaa1fef65}} || tcp: adding a per-socket timestamp offset || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|93be6ce0e9}} || tcp: set and get per-socket timestamp || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ee684b6f28}} || tcp: send packets with a socket timestamp || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|66dd34ad}} || signal: allow to send any siginfo to itself || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|ae5fc987}} || net: fix *_DIAG_MAX constants || 3.9&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|0f29c768}} || net: prepare netlink code for netlink diag || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|eaaa3139}} || netlink: Diag core and basic socket info dumping (v2) || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|84c751bd}} || ptrace: add ability to retrieve signals without removing from a queue (v4) || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|040fa020}} || clear_refs: Sanitize accepted commands declaration || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|af9de7eb}} || clear_refs: Introduce private struct for mm_walk || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|2b0a9f01}} || pagemap-introduce-pagemap_entry_t-without-pmshift-bits || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|0f8975ec}} || mm: soft-dirty bits for user memory changes tracking || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|541c237c}} || pagemap: prepare to reuse constant bits with page-shift || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|57b8015e}} || posix-timers: Show sigevent info in proc file || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|48f6a7a5}} || posix-timers: Introduce /proc/PID/timers file || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|5ed67f05}} || posix timers: Allocate timer id per process (v2) || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|15ef0298}} || posix-timers: Show clock ID in proc file || 3.10&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|29000cae}} || ptrace: add ability to get/set signal-blocked mask (v2) || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|274038f8}} || tun: Report &amp;quot;persist&amp;quot; flag to userspace || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|179ef71c}} || mm: Save soft-dirty bits on swapped pages || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|41bb3476}} || mm: Save soft-dirty bits on file pages || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|76975e9c}} || tun: Get skfilter layout || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|849c9b6f}} || tun: Allow to skip filter on attach || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|3d407a80}} || tun: Report whether the queue is attached or not || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|fb7589a1}} || tun: Add ability to create tun device with given index || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e3e12028}} || tcp: don't apply tsoffset if rcv_tsecr is zero || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c7781a6e}} || tcp: initialize rcv_tstamp for restored sockets || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|7ed5c5ae}} || tcp: set timestamps for restored skb-s || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|6dec97dc}} || mm: move_ptes -- Set soft dirty bit depending on pte type || 3.11&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c3d16e16}} || mm: migration -- Do not loose soft dirty bit if page is in migration state || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e9cdd6e7}} || mm: pagemap -- Inspect _PAGE_SOFT_DIRTY only on present pages || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|dbde4979}} || tcp: don't update snd_nxt, when a socket is switched from repair mode || 3.13&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|d9104d1c}} || mm: track vma changes with VM_SOFTDIRTY bit || 3.12&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|34228d47}} || mm: Ignore VM_SOFTDIRTY on VMA merging || 3.14, 3.13-stable&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|24f91eba1}} || mm: don't lose the SOFT_DIRTY flag on mprotect || 3.14, 3.13-stable&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|49d063cb3}} || proc: show mnt_id in /proc/pid/fdinfo || 3.15&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|0bf073315}} || mm: Make freshly remapped file pages being softdirty unconditionally || 3.15&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9aed8614a}} || mm: Don't forget to set softdirty on file mapped fault || 3.17&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|b43790eed}} || mm: Don't forget to save file map softdiry bit on unmap || 3.15&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|c86c97ff4}} || mm: Clear VM_SOFTDIRTY flag inside clear_refs_write instead of clear_soft_dirty || 3.15&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|af9c4957c}} || timerfd: Implement show_fdinfo method || 3.17&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|854d06d9f}} || docs: Procfs -- Document timerfd output || 3.17&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|5442e9fbd}} || timerfd: Implement timerfd_ioctl method to restore timerfd_ctx::ticks, v3 || 3.17&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|64e455079}} || mm: softdirty: enable write notifications on VMAs after VM_SOFTDIRTY cleared || 3.18&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9c5990240}} || mm: introduce check_data_rlimit helper || 3.18&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|8764b338b}} || mm: use may_adjust_brk helper || 3.18&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|71fe97e18}} || prctl: PR_SET_MM -- factor out mmap_sem when updating mm::exe_file || 3.18&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|f606b77f1}} || prctl: PR_SET_MM -- introduce PR_SET_MM_MAP operation || 3.18&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9183df25f}} || shm: add memfd_create() syscall || 3.17&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|e4a0d3e72}} || aio: Make it possible to remap aio ring || 3.19&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|6c8c90319}} || proc: show locks in /proc/pid/fdinfo/X || 4.1&lt;br /&gt;
|-&lt;br /&gt;
|{{torvadls.git|155e35d4d}} || VFS: Introduce inode-getting helpers for layered/unioned fs environments || 4.0&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|df1a085af}} || VFS: Add a fallthrough flag for marking virtual dentries || 4.0&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|f25801ee4}} || overlay: Call ovl_drop_write() earlier in ovl_dentry_open() || 4.2-rc2&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|4bacc9c92}} || overlayfs: Make f_path always point to the overlay and f_inode to the underlay || 4.2-rc2&lt;br /&gt;
|-&lt;br /&gt;
|{{torvalds.git|9391dd00d}} || fix a braino in ovl_d_select_inode() || 4.2-rc2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2526</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2526"/>
		<updated>2015-07-15T22:55:28Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
{{Note| This page was originally written a few months ago.  Since then, interfacing with CRIU has been added to Docker's native exec driver (libcontainer) and pull requests to add checkpoint/restore functionality to Docker have been submitted.  If you just want to experiment with C/R, you can use one of the following Docker versions for your C/R experiments: &lt;br /&gt;
&lt;br /&gt;
Docker 1.5 [https://github.com/SaiedKazemi/docker/wiki]&lt;br /&gt;
Docker 1.7 [https://github.com/boucher/docker/tree/cr-combined]}}&lt;br /&gt;
&lt;br /&gt;
{{Note| The OverlayFS filesystem was merged into the upstream Linux kernel 3.18 and is now Docker's preferred filesystem (instead of AUFS).  However, there is a bug in OverlayFS that reports the wrong mnt_id in /proc/&amp;lt;pid&amp;gt;/fdinfo/&amp;lt;fd&amp;gt; and the wrong symlink target path for /proc/&amp;lt;pid&amp;gt;/&amp;lt;fd&amp;gt;.  Fortunately, these bugs have been fixed in the kernel v4.2-rc2.  See below for instructions on how to apply the relevant patches.}}&lt;br /&gt;
&lt;br /&gt;
{{Note| If your process uses async IO and your kernel is older than 3.19, you need to apply two patches.  See below for instructions.}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''1. External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done for any process tree.&lt;br /&gt;
&lt;br /&gt;
This approach is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
'''2. Native C/R''' using new &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
This approach is called native because the Docker daemon is involved in both checkpoint and restore.&lt;br /&gt;
Therefore, its notion of the container state will be corrent.  All commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.&lt;br /&gt;
You can watch this short demo&lt;br /&gt;
'''[https://www.youtube.com/watch?v=HFt9v6yqsXo video]'''&lt;br /&gt;
to see how it works.&lt;br /&gt;
Source files for Docker 1.5 C/R are&lt;br /&gt;
'''[https://github.com/SaiedKazemi/docker/tree/cr here]'''&lt;br /&gt;
and for Docker 1.7 C/R are&lt;br /&gt;
'''[https://github.com/boucher/docker/tree/cr-combined here]'''.&lt;br /&gt;
The '''[https://github.com/SaiedKazemi/docker/wiki wiki]'''&lt;br /&gt;
page provides an overview of the project history.&lt;br /&gt;
&lt;br /&gt;
== OverlayFS ==&lt;br /&gt;
&lt;br /&gt;
The following small kernel patches fix the mount id and symlink target path issues noted above:&lt;br /&gt;
&lt;br /&gt;
* {{torvalds.git|155e35d4da}} by David Howells&lt;br /&gt;
* {{torvalds.git|df1a085af1}} by David Howells&lt;br /&gt;
* {{torvalds.git|f25801ee46}} by David Howells&lt;br /&gt;
* {{torvalds.git|4bacc9c923}} by David Howells&lt;br /&gt;
* {{torvalds.git|9391dd00d1}} by Al Viro&lt;br /&gt;
&lt;br /&gt;
Assuming that you are running Ubuntu Vivid (Linux kernel 3.19), here is how you can patch your kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone  git://kernel.ubuntu.com/ubuntu/ubuntu-vivid.git&lt;br /&gt;
cd ubuntu-vivid&lt;br /&gt;
git remote add torvalds  git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git&lt;br /&gt;
git remote update&lt;br /&gt;
&lt;br /&gt;
git cherry-pick 155e35d4da&lt;br /&gt;
git cherry-pick df1a085af1&lt;br /&gt;
git cherry-pick f25801ee46&lt;br /&gt;
git cherry-pick 4bacc9c923&lt;br /&gt;
git cherry-pick 9391dd00d1&lt;br /&gt;
&lt;br /&gt;
cp /boot/config-$(uname -r) .config&lt;br /&gt;
make olddefconfig&lt;br /&gt;
make -j 8 bzImage modules&lt;br /&gt;
sudo make install modules_install&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Async IO (AIO) ==&lt;br /&gt;
&lt;br /&gt;
If you are using a kernel older than 3.19 and your container uses AIO, you need the following AIO kernel patches from 3.19:&lt;br /&gt;
&lt;br /&gt;
* {{torvalds.git|bd9b51e79c}} by Al Viro&lt;br /&gt;
* {{torvalds.git|e4a0d3e720}} by Pavel Emelyanov&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
{{Note| External C/R was done as proof-of-concept.  Its use is discouraged and the helper script mentioned below will be deprecated in the near future.}}&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it is possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
&amp;lt;code&amp;gt;/proc/''pid''/map_files&amp;lt;/code&amp;gt;, option &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt;&lt;br /&gt;
is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up &amp;lt;code&amp;gt;/etc/{hostname,hosts,resolv.conf}&amp;lt;/code&amp;gt; as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount &amp;lt;code&amp;gt;/.dockerinit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, &amp;lt;code&amp;gt;/etc/hostname&amp;lt;/code&amp;gt;&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at &amp;lt;code&amp;gt;/var/lib/docker/containers/''container_id''/hostname&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;/dev/stdin&amp;lt;/code&amp;gt; for detached containers&lt;br /&gt;
(i.e., &amp;lt;code&amp;gt;docker run -d ...&amp;lt;/code&amp;gt;).  Since earlier versions of Docker used&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; and the container &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; as the same device.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
For native C/R support, this option tells CRIU to let the restored process &amp;quot;inherit&amp;quot;&lt;br /&gt;
its specified file descriptor (instead of restoring from checkpoint).&lt;br /&gt;
&lt;br /&gt;
== Restore Prework for External C/R ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to CRIU dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An External C/R Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External C/R Helper Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify &amp;lt;code&amp;gt;-v&amp;lt;/code&amp;gt; to see the commands that &amp;lt;code&amp;gt;docker_cr.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log \&lt;br /&gt;
     --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
     -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     -o restore.log --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
     -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2525</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2525"/>
		<updated>2015-07-15T22:53:38Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
{{Note| This page was originally written a few months ago.  Since then, interfacing with CRIU has been added to Docker's native exec driver (libcontainer) and pull requests to add checkpoint/restore functionality to Docker have been submitted.  If you just want to experiment with C/R, you can use one of the following Docker versions for your C/R experiments: &lt;br /&gt;
&lt;br /&gt;
Docker 1.5 [https://github.com/SaiedKazemi/docker/wiki]&lt;br /&gt;
Docker 1.7 [https://github.com/boucher/docker/tree/cr-combined]}}&lt;br /&gt;
&lt;br /&gt;
{{Note| The OverlayFS filesystem was merged into the upstream Linux kernel 3.18 and is now Docker's preferred filesystem (instead of AUFS).  However, there is a bug in OverlayFS that reports the wrong mnt_id in /proc/&amp;lt;pid&amp;gt;/fdinfo/&amp;lt;fd&amp;gt; and the wrong symlink target path for /proc/&amp;lt;pid&amp;gt;/&amp;lt;fd&amp;gt;.  Fortunately, these bugs have been fixed in the kernel v4.2-rc2.  See below for instructions on how to apply the relevant patches.}}&lt;br /&gt;
&lt;br /&gt;
{{Note| If your process uses async IO and your kernel is older than 3.19, you need to apply two patches.  See below for instructions.}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''1. External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done for any process tree.&lt;br /&gt;
&lt;br /&gt;
This approach is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
'''2. Native C/R''' using new &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
This approach is called native because the Docker daemon is involved in both checkpoint and restore.&lt;br /&gt;
Therefore, its notion of the container state will be corrent.  All commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.&lt;br /&gt;
You can watch this short demo&lt;br /&gt;
'''[https://www.youtube.com/watch?v=HFt9v6yqsXo video]'''&lt;br /&gt;
to see how it works.&lt;br /&gt;
Source files for Docker 1.5 C/R are&lt;br /&gt;
'''[https://github.com/SaiedKazemi/docker/tree/cr here]'''&lt;br /&gt;
and for Docker 1.7 C/R are&lt;br /&gt;
'''https://github.com/boucher/docker/tree/cr-combined here]'''.&lt;br /&gt;
The '''[https://github.com/SaiedKazemi/docker/wiki wiki]'''&lt;br /&gt;
page provides an overview of the project history.&lt;br /&gt;
&lt;br /&gt;
== OverlayFS ==&lt;br /&gt;
&lt;br /&gt;
The following small kernel patches fix the mount id and symlink target path issues noted above:&lt;br /&gt;
&lt;br /&gt;
* {{torvalds.git|155e35d4da}} by David Howells&lt;br /&gt;
* {{torvalds.git|df1a085af1}} by David Howells&lt;br /&gt;
* {{torvalds.git|f25801ee46}} by David Howells&lt;br /&gt;
* {{torvalds.git|4bacc9c923}} by David Howells&lt;br /&gt;
* {{torvalds.git|9391dd00d1}} by Al Viro&lt;br /&gt;
&lt;br /&gt;
Assuming that you are running Ubuntu Vivid (Linux kernel 3.19), here is how you can patch your kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone  git://kernel.ubuntu.com/ubuntu/ubuntu-vivid.git&lt;br /&gt;
cd ubuntu-vivid&lt;br /&gt;
git remote add torvalds  git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git&lt;br /&gt;
git remote update&lt;br /&gt;
&lt;br /&gt;
git cherry-pick 155e35d4da&lt;br /&gt;
git cherry-pick df1a085af1&lt;br /&gt;
git cherry-pick f25801ee46&lt;br /&gt;
git cherry-pick 4bacc9c923&lt;br /&gt;
git cherry-pick 9391dd00d1&lt;br /&gt;
&lt;br /&gt;
cp /boot/config-$(uname -r) .config&lt;br /&gt;
make olddefconfig&lt;br /&gt;
make -j 8 bzImage modules&lt;br /&gt;
sudo make install modules_install&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Async IO (AIO) ==&lt;br /&gt;
&lt;br /&gt;
If you are using a kernel older than 3.19 and your container uses AIO, you need the following AIO kernel patches from 3.19:&lt;br /&gt;
&lt;br /&gt;
* {{torvalds.git|bd9b51e79c}} by Al Viro&lt;br /&gt;
* {{torvalds.git|e4a0d3e720}} by Pavel Emelyanov&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
{{Note| External C/R was done as proof-of-concept.  Its use is discouraged and the helper script mentioned below will be deprecated in the near future.}}&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it is possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
&amp;lt;code&amp;gt;/proc/''pid''/map_files&amp;lt;/code&amp;gt;, option &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt;&lt;br /&gt;
is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up &amp;lt;code&amp;gt;/etc/{hostname,hosts,resolv.conf}&amp;lt;/code&amp;gt; as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount &amp;lt;code&amp;gt;/.dockerinit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, &amp;lt;code&amp;gt;/etc/hostname&amp;lt;/code&amp;gt;&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at &amp;lt;code&amp;gt;/var/lib/docker/containers/''container_id''/hostname&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;/dev/stdin&amp;lt;/code&amp;gt; for detached containers&lt;br /&gt;
(i.e., &amp;lt;code&amp;gt;docker run -d ...&amp;lt;/code&amp;gt;).  Since earlier versions of Docker used&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; and the container &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; as the same device.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
For native C/R support, this option tells CRIU to let the restored process &amp;quot;inherit&amp;quot;&lt;br /&gt;
its specified file descriptor (instead of restoring from checkpoint).&lt;br /&gt;
&lt;br /&gt;
== Restore Prework for External C/R ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to CRIU dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An External C/R Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External C/R Helper Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify &amp;lt;code&amp;gt;-v&amp;lt;/code&amp;gt; to see the commands that &amp;lt;code&amp;gt;docker_cr.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log \&lt;br /&gt;
     --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
     -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     -o restore.log --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
     -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2524</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2524"/>
		<updated>2015-07-15T22:51:48Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
{{Note| This page was originally written a few months ago.  Since then, interfacing with CRIU has been added to Docker's native exec driver (libcontainer) and pull requests to add checkpoint/restore functionality to Docker have been submitted.  If you just want to experiment with C/R, you can use one of the following Docker versions for your C/R experiments: &lt;br /&gt;
&lt;br /&gt;
Docker 1.5 [https://github.com/SaiedKazemi/docker/wiki]&lt;br /&gt;
Docker 1.7 [https://github.com/boucher/docker/tree/cr-combined]}}&lt;br /&gt;
&lt;br /&gt;
{{OverlayFS| The OverlayFS filesystem was merged into the upstream Linux kernel 3.18 and is now Docker's preferred filesystem (instead of AUFS).  However, there is a bug in OverlayFS that reports the wrong mnt_id in /proc/&amp;lt;pid&amp;gt;/fdinfo/&amp;lt;fd&amp;gt; and the wrong symlink target path for /proc/&amp;lt;pid&amp;gt;/&amp;lt;fd&amp;gt;.  Fortunately, these bugs have been fixed in the kernel v4.2-rc2.  See below for instructions on how to apply the relevant patches.}}&lt;br /&gt;
&lt;br /&gt;
{{Async IO| If your process uses async IO and your kernel is older than 3.19, you need to apply two patches.  See below for instructions.}}&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''1. External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done for any process tree.&lt;br /&gt;
&lt;br /&gt;
This approach is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
'''2. Native C/R''' using new &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
This approach is called native because the Docker daemon is involved in both checkpoint and restore.&lt;br /&gt;
Therefore, its notion of the container state will be corrent.  All commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.&lt;br /&gt;
You can watch this short demo&lt;br /&gt;
'''[https://www.youtube.com/watch?v=HFt9v6yqsXo video]'''&lt;br /&gt;
to see how it works.&lt;br /&gt;
Source files for Docker 1.5 C/R are&lt;br /&gt;
'''[https://github.com/SaiedKazemi/docker/tree/cr here]'''&lt;br /&gt;
and for Docker 1.7 C/R are&lt;br /&gt;
'''https://github.com/boucher/docker/tree/cr-combined here]'''.&lt;br /&gt;
The '''[https://github.com/SaiedKazemi/docker/wiki wiki]'''&lt;br /&gt;
page provides an overview of the project history.&lt;br /&gt;
&lt;br /&gt;
== OverlayFS ==&lt;br /&gt;
&lt;br /&gt;
The following small kernel patches fix the mount id and symlink target path issues noted above:&lt;br /&gt;
&lt;br /&gt;
* {{torvalds.git|155e35d4da}} by David Howells&lt;br /&gt;
* {{torvalds.git|df1a085af1}} by David Howells&lt;br /&gt;
* {{torvalds.git|f25801ee46}} by David Howells&lt;br /&gt;
* {{torvalds.git|4bacc9c923}} by David Howells&lt;br /&gt;
* {{torvalds.git|9391dd00d1}} by Al Viro&lt;br /&gt;
&lt;br /&gt;
Assuming that you are running Ubuntu Vivid (Linux kernel 3.19), here is how you can patch your kernel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone  git://kernel.ubuntu.com/ubuntu/ubuntu-vivid.git&lt;br /&gt;
cd ubuntu-vivid&lt;br /&gt;
git remote add torvalds  git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git&lt;br /&gt;
git remote update&lt;br /&gt;
&lt;br /&gt;
git cherry-pick 155e35d4da&lt;br /&gt;
git cherry-pick df1a085af1&lt;br /&gt;
git cherry-pick f25801ee46&lt;br /&gt;
git cherry-pick 4bacc9c923&lt;br /&gt;
git cherry-pick 9391dd00d1&lt;br /&gt;
&lt;br /&gt;
cp /boot/config-$(uname -r) .config&lt;br /&gt;
make olddefconfig&lt;br /&gt;
make -j 8 bzImage modules&lt;br /&gt;
sudo make install modules_install&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Async IO (AIO) ==&lt;br /&gt;
&lt;br /&gt;
If you are using a kernel older than 3.19 and your container uses AIO, you need the following AIO kernel patches from 3.19:&lt;br /&gt;
&lt;br /&gt;
* {{torvalds.git|bd9b51e79c}} by Al Viro&lt;br /&gt;
* {{torvalds.git|e4a0d3e720}} by Pavel Emelyanov&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
{{Note| External C/R was done as proof-of-concept.  Its use is discouraged and the helper script mentioned below will be deprecated in the near future.}}&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it is possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
&amp;lt;code&amp;gt;/proc/''pid''/map_files&amp;lt;/code&amp;gt;, option &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt;&lt;br /&gt;
is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up &amp;lt;code&amp;gt;/etc/{hostname,hosts,resolv.conf}&amp;lt;/code&amp;gt; as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount &amp;lt;code&amp;gt;/.dockerinit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, &amp;lt;code&amp;gt;/etc/hostname&amp;lt;/code&amp;gt;&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at &amp;lt;code&amp;gt;/var/lib/docker/containers/''container_id''/hostname&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;/dev/stdin&amp;lt;/code&amp;gt; for detached containers&lt;br /&gt;
(i.e., &amp;lt;code&amp;gt;docker run -d ...&amp;lt;/code&amp;gt;).  Since earlier versions of Docker used&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; and the container &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; as the same device.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
For native C/R support, this option tells CRIU to let the restored process &amp;quot;inherit&amp;quot;&lt;br /&gt;
its specified file descriptor (instead of restoring from checkpoint).&lt;br /&gt;
&lt;br /&gt;
== Restore Prework for External C/R ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to CRIU dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An External C/R Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External C/R Helper Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify &amp;lt;code&amp;gt;-v&amp;lt;/code&amp;gt; to see the commands that &amp;lt;code&amp;gt;docker_cr.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log \&lt;br /&gt;
     --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
     -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     -o restore.log --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
     -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2510</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2510"/>
		<updated>2015-06-18T04:24:53Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
Last update: June 17, 2015&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
{{Note| This page was originally written a few months ago.  Since then, interfacing with CRIU has been added to Docker's native exec driver (libcontainer) and pull requests to add checkpoint/restore functionality to Docker have been submitted.  You can use one of the following Docker versions for your C/R experiments: &lt;br /&gt;
&lt;br /&gt;
Docker 1.5 [https://github.com/SaiedKazemi/docker/wiki]&lt;br /&gt;
Docker 1.7 [https://github.com/boucher/docker/tree/cr-combined]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done.&lt;br /&gt;
&lt;br /&gt;
This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
{{Note| External C/R was done as proof-of-concept.  Its use is discouraged and the helper script mentioned below will be deprecated in the near future.}}&lt;br /&gt;
&lt;br /&gt;
'''Native C/R''' using the newly added &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and all commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
'''[https://www.youtube.com/watch?v=HFt9v6yqsXo video]'''&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R are at this&lt;br /&gt;
'''[https://github.com/SaiedKazemi/docker/tree/cr repo]'''.&lt;br /&gt;
The '''[https://github.com/SaiedKazemi/docker/wiki wiki]'''&lt;br /&gt;
page provides an overview of the project history.&lt;br /&gt;
Work in underway to integrate C/R into the new &amp;lt;code&amp;gt;libcontainer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For native C/R support, additional functionality was added to CRIU.&lt;br /&gt;
The most notable addition is the &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; command line option.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it is possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
&amp;lt;code&amp;gt;/proc/''pid''/map_files&amp;lt;/code&amp;gt;, option &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt;&lt;br /&gt;
is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up &amp;lt;code&amp;gt;/etc/{hostname,hosts,resolv.conf}&amp;lt;/code&amp;gt; as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount &amp;lt;code&amp;gt;/.dockerinit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, &amp;lt;code&amp;gt;/etc/hostname&amp;lt;/code&amp;gt;&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at &amp;lt;code&amp;gt;/var/lib/docker/containers/''container_id''/hostname&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;/dev/stdin&amp;lt;/code&amp;gt; for detached containers&lt;br /&gt;
(i.e., &amp;lt;code&amp;gt;docker run -d ...&amp;lt;/code&amp;gt;).  Since earlier versions of Docker used&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; and the container &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to CRIU dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify &amp;lt;code&amp;gt;-v&amp;lt;/code&amp;gt; to see the commands that &amp;lt;code&amp;gt;docker_cr.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log \&lt;br /&gt;
     --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
     -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     -o restore.log --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
     -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== OverlayFS ==&lt;br /&gt;
&lt;br /&gt;
The OverlayFS filesystem was merged into the upstream Linux kernel 3.18 and is now Docker's preferred filesystem (instead of AUFS).  For successful C/R, however, you need to apply the following kernel patch:&lt;br /&gt;
&lt;br /&gt;
OverlayFS patch [https://lkml.org/lkml/2015/3/20/372]&lt;br /&gt;
&lt;br /&gt;
== Async IO (AIO) ==&lt;br /&gt;
&lt;br /&gt;
If you are using a kernel older than 3.19 and your container uses AIO, you need the following AIO kernel patches from 3.19:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Al Viro's bd9b51e7&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;Pavel Emelyanov's e4a0d3e72&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2509</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2509"/>
		<updated>2015-06-18T04:23:31Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
Last update: June 17, 2015&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
{{Note| This page was originally written a few months ago.  Since then, interfacing with CRIU has been added to Docker's native exec driver (libcontainer) and pull requests to add checkpoint/restore functionality to Docker have been submitted.  You can use one of the following Docker versions for your C/R experiments: &lt;br /&gt;
&lt;br /&gt;
Docker 1.5 [https://github.com/SaiedKazemi/docker/wiki]&lt;br /&gt;
Docker 1.7 [https://github.com/boucher/docker/tree/cr-combined]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done.&lt;br /&gt;
&lt;br /&gt;
This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
{{Note| External C/R was done as proof-of-concept.  Its use is discouraged and the helper script mentioned below will be deprecated in the near future.}}&lt;br /&gt;
&lt;br /&gt;
'''Native C/R''' using the newly added &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and all commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
'''[https://www.youtube.com/watch?v=HFt9v6yqsXo video]'''&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R are at this&lt;br /&gt;
'''[https://github.com/SaiedKazemi/docker/tree/cr repo]'''.&lt;br /&gt;
The '''[https://github.com/SaiedKazemi/docker/wiki wiki]'''&lt;br /&gt;
page provides an overview of the project history.&lt;br /&gt;
Work in underway to integrate C/R into the new &amp;lt;code&amp;gt;libcontainer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For native C/R support, additional functionality was added to CRIU.&lt;br /&gt;
The most notable addition is the &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; command line option.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it is possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
&amp;lt;code&amp;gt;/proc/''pid''/map_files&amp;lt;/code&amp;gt;, option &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt;&lt;br /&gt;
is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up &amp;lt;code&amp;gt;/etc/{hostname,hosts,resolv.conf}&amp;lt;/code&amp;gt; as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount &amp;lt;code&amp;gt;/.dockerinit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, &amp;lt;code&amp;gt;/etc/hostname&amp;lt;/code&amp;gt;&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at &amp;lt;code&amp;gt;/var/lib/docker/containers/''container_id''/hostname&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;/dev/stdin&amp;lt;/code&amp;gt; for detached containers&lt;br /&gt;
(i.e., &amp;lt;code&amp;gt;docker run -d ...&amp;lt;/code&amp;gt;).  Since earlier versions of Docker used&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; and the container &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to CRIU dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify &amp;lt;code&amp;gt;-v&amp;lt;/code&amp;gt; to see the commands that &amp;lt;code&amp;gt;docker_cr.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log \&lt;br /&gt;
     --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
     -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     -o restore.log --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
     -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== OverlayFS ==&lt;br /&gt;
&lt;br /&gt;
The OverlayFS filesystem was merged into the upstream Linux kernel 3.18 and is now Docker's preferred filesystem (instead of AUFS).  For successful C/R, however, you need to apply the following kernel patch:&lt;br /&gt;
&lt;br /&gt;
OverlayFS patch [https://lkml.org/lkml/2015/3/20/372]&lt;br /&gt;
&lt;br /&gt;
== Async IO (AIO) ==&lt;br /&gt;
&lt;br /&gt;
If you are using a kernel older than 3.19 and your container uses AIO, you need the following AIO kernel patches from 3.19:&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;Al Viro's bd9b51e7&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;code&amp;gt;Pavel Emelyanov's e4a0d3e72&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2508</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2508"/>
		<updated>2015-06-18T04:12:47Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
Last update: June 17, 2015&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
{{Note| This page was originally written a few months ago.  Since then, interfacing with CRIU has been added to Docker's native exec driver (libcontainer) and pull requests to add checkpoint/restore functionality to Docker have been submitted.  You can use one of the following Docker versions for your C/R experiments: &lt;br /&gt;
&lt;br /&gt;
Docker 1.5 [https://github.com/SaiedKazemi/docker/wiki]&lt;br /&gt;
Docker 1.7 [https://github.com/boucher/docker/tree/cr-combined]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done.&lt;br /&gt;
&lt;br /&gt;
This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
{{Note| External C/R was done as proof-of-concept.  Its use is discouraged and the helper script mentioned below will be deprecated in the near future.}}&lt;br /&gt;
&lt;br /&gt;
'''Native C/R''' using the newly added &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and all commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
'''[https://www.youtube.com/watch?v=HFt9v6yqsXo video]'''&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R are at this&lt;br /&gt;
'''[https://github.com/SaiedKazemi/docker/tree/cr repo]'''.&lt;br /&gt;
The '''[https://github.com/SaiedKazemi/docker/wiki wiki]'''&lt;br /&gt;
page provides an overview of the project history.&lt;br /&gt;
Work in underway to integrate C/R into the new &amp;lt;code&amp;gt;libcontainer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For native C/R support, additional functionality was added to CRIU.&lt;br /&gt;
The most notable addition is the &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; command line option.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it is possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
&amp;lt;code&amp;gt;/proc/''pid''/map_files&amp;lt;/code&amp;gt;, option &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt;&lt;br /&gt;
is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up &amp;lt;code&amp;gt;/etc/{hostname,hosts,resolv.conf}&amp;lt;/code&amp;gt; as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount &amp;lt;code&amp;gt;/.dockerinit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, &amp;lt;code&amp;gt;/etc/hostname&amp;lt;/code&amp;gt;&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at &amp;lt;code&amp;gt;/var/lib/docker/containers/''container_id''/hostname&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;/dev/stdin&amp;lt;/code&amp;gt; for detached containers&lt;br /&gt;
(i.e., &amp;lt;code&amp;gt;docker run -d ...&amp;lt;/code&amp;gt;).  Since earlier versions of Docker used&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; and the container &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to CRIU dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify &amp;lt;code&amp;gt;-v&amp;lt;/code&amp;gt; to see the commands that &amp;lt;code&amp;gt;docker_cr.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log \&lt;br /&gt;
     --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
     -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     -o restore.log --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
     -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2507</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2507"/>
		<updated>2015-06-18T04:09:47Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
Last update: June 17, 2015&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
{{Note| This page was originally written a few months ago.  Since then, interfacing with CRIU has been added to Docker's native exec driver (libcontainer) and pull requests to add checkpoint/restore functionality to Docker have been submitted.  You can use one of the following Docker versions for your C/R experiments: &lt;br /&gt;
&lt;br /&gt;
Docker 1.5 [https://github.com/SaiedKazemi/docker/wiki]&lt;br /&gt;
Docker 1.7 [https://github.com/boucher/docker/tree/cr-combined]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done.&lt;br /&gt;
&lt;br /&gt;
This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
External C/R was done as a proof-of-concept.&lt;br /&gt;
&lt;br /&gt;
'''Native C/R''' using the newly added &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and all commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
'''[https://www.youtube.com/watch?v=HFt9v6yqsXo video]'''&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R are at this&lt;br /&gt;
'''[https://github.com/SaiedKazemi/docker/tree/cr repo]'''.&lt;br /&gt;
The '''[https://github.com/SaiedKazemi/docker/wiki wiki]'''&lt;br /&gt;
page provides an overview of the project history.&lt;br /&gt;
Work in underway to integrate C/R into the new &amp;lt;code&amp;gt;libcontainer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For native C/R support, additional functionality was added to CRIU.&lt;br /&gt;
The most notable addition is the &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; command line option.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it is possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
&amp;lt;code&amp;gt;/proc/''pid''/map_files&amp;lt;/code&amp;gt;, option &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt;&lt;br /&gt;
is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up &amp;lt;code&amp;gt;/etc/{hostname,hosts,resolv.conf}&amp;lt;/code&amp;gt; as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount &amp;lt;code&amp;gt;/.dockerinit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, &amp;lt;code&amp;gt;/etc/hostname&amp;lt;/code&amp;gt;&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at &amp;lt;code&amp;gt;/var/lib/docker/containers/''container_id''/hostname&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;/dev/stdin&amp;lt;/code&amp;gt; for detached containers&lt;br /&gt;
(i.e., &amp;lt;code&amp;gt;docker run -d ...&amp;lt;/code&amp;gt;).  Since earlier versions of Docker used&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; and the container &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to CRIU dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify &amp;lt;code&amp;gt;-v&amp;lt;/code&amp;gt; to see the commands that &amp;lt;code&amp;gt;docker_cr.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log \&lt;br /&gt;
     --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
     -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     -o restore.log --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
     -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2506</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2506"/>
		<updated>2015-06-18T04:07:06Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
Last update: June 17, 2015&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
{{Note| This page was originally written a few months ago.  Since then, interfacing&lt;br /&gt;
with CRIU has been added to Docker's native exec driver (libcontainer) and pull requests&lt;br /&gt;
to add checkpoint/restore functionality to Docker have been submitted.  Therefore, you&lt;br /&gt;
can use one of the following Docker versions for your C/R experiments. &lt;br /&gt;
&lt;br /&gt;
Docker 1.5 [https://github.com/SaiedKazemi/docker/wiki]&lt;br /&gt;
Docker 1.7 [https://github.com/boucher/docker/tree/cr-combined]&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done.&lt;br /&gt;
&lt;br /&gt;
This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
External C/R was done as a proof-of-concept.&lt;br /&gt;
&lt;br /&gt;
'''Native C/R''' using the newly added &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and all commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
'''[https://www.youtube.com/watch?v=HFt9v6yqsXo video]'''&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R are at this&lt;br /&gt;
'''[https://github.com/SaiedKazemi/docker/tree/cr repo]'''.&lt;br /&gt;
The '''[https://github.com/SaiedKazemi/docker/wiki wiki]'''&lt;br /&gt;
page provides an overview of the project history.&lt;br /&gt;
Work in underway to integrate C/R into the new &amp;lt;code&amp;gt;libcontainer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For native C/R support, additional functionality was added to CRIU.&lt;br /&gt;
The most notable addition is the &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; command line option.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it is possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
&amp;lt;code&amp;gt;/proc/''pid''/map_files&amp;lt;/code&amp;gt;, option &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt;&lt;br /&gt;
is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up &amp;lt;code&amp;gt;/etc/{hostname,hosts,resolv.conf}&amp;lt;/code&amp;gt; as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount &amp;lt;code&amp;gt;/.dockerinit&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, &amp;lt;code&amp;gt;/etc/hostname&amp;lt;/code&amp;gt;&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at &amp;lt;code&amp;gt;/var/lib/docker/containers/''container_id''/hostname&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; on &amp;lt;code&amp;gt;/dev/stdin&amp;lt;/code&amp;gt; for detached containers&lt;br /&gt;
(i.e., &amp;lt;code&amp;gt;docker run -d ...&amp;lt;/code&amp;gt;).  Since earlier versions of Docker used&lt;br /&gt;
&amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; and the container &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt; as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to CRIU dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Helper Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify &amp;lt;code&amp;gt;-v&amp;lt;/code&amp;gt; to see the commands that &amp;lt;code&amp;gt;docker_cr.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log \&lt;br /&gt;
     --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
     -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     -o restore.log --manage-cgroups --evasive-devices \&lt;br /&gt;
     --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf \&lt;br /&gt;
     --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts \&lt;br /&gt;
     --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname \&lt;br /&gt;
     --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
     -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf \&lt;br /&gt;
     --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Action_scripts&amp;diff=2355</id>
		<title>Action scripts</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Action_scripts&amp;diff=2355"/>
		<updated>2015-04-08T16:16:48Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: /* RPC */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;With the --action-script command line option, CRIU can call your action scripts (also known as hooks) at various stages of dumping/restoring. Hooks can be one of&lt;br /&gt;
&lt;br /&gt;
;network-lock&lt;br /&gt;
: request to lock a container network (used by Docker and [[LXC]])&lt;br /&gt;
&lt;br /&gt;
;network-unlock&lt;br /&gt;
: requested to unlock a container network (used by Docker and [[LXC]])&lt;br /&gt;
&lt;br /&gt;
;post-dump&lt;br /&gt;
: called when CRIU finished dumping tasks before unfreezing them&lt;br /&gt;
&lt;br /&gt;
;post-restore&lt;br /&gt;
: called when CRIU has finished restoring tasks before unlocking the network&lt;br /&gt;
&lt;br /&gt;
;setup-namespaces&lt;br /&gt;
: called when the root task is alive and new set of namespaces is created to set them up&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CLI ==&lt;br /&gt;
These hooks are added with the --action-script shell-code-to-execute option. When called, the CRTOOLS_SCRIPT_ACTION environment is set to a value determining which type of action is performed.&lt;br /&gt;
&lt;br /&gt;
== RPC ==&lt;br /&gt;
&lt;br /&gt;
In case of RPC, action scripts are implemented as notifications -- once CRIU service wants to execute a script it sends an RPC message to caller and waits for it to respond with &amp;lt;code&amp;gt;criu_req&amp;lt;/code&amp;gt; message having &amp;lt;code&amp;gt;notify_success = true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Library ==&lt;br /&gt;
&lt;br /&gt;
When using a library one can setup a callback using the &amp;lt;code&amp;gt;criu_set_notify&amp;lt;/code&amp;gt; routine.&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2261</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2261"/>
		<updated>2015-03-19T21:33:36Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container as of March 2015.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done.&lt;br /&gt;
&lt;br /&gt;
This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
External C/R was done as a proof-of-concept.&lt;br /&gt;
&lt;br /&gt;
'''Native C/R''' using the newly added &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and all commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
'''[https://www.youtube.com/watch?v=HFt9v6yqsXo video]'''&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R is at this&lt;br /&gt;
'''[https://github.com/SaiedKazemi/docker/tree/cr repo]'''.&lt;br /&gt;
The '''[https://github.com/SaiedKazemi/docker/wiki wiki]'''&lt;br /&gt;
page provides an overview of the project history.&lt;br /&gt;
Work in underway to integrate C/R into the new libcontainer.&lt;br /&gt;
&lt;br /&gt;
For native C/R support, additional functionality was added to CRIU.&lt;br /&gt;
The most notable addition is the &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; command line option.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it's possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
Work is in progress to add native checkpoint and restore support&lt;br /&gt;
to Docker.  Once ready, specific commands (for example, &amp;quot;docker&lt;br /&gt;
checkpoint&amp;quot; and &amp;quot;docker restore&amp;quot;) will use CRIU to do the actual&lt;br /&gt;
C/R operations while Docker continues to maintain its parent-child&lt;br /&gt;
relationship and container states.&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
/proc/&amp;lt;pid&amp;gt;/map_files, --root is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up /etc/{hostname,hosts,resolv.conf} as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount /.dockerinit.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, /etc/hostname&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at /var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts /dev/null on /dev/stdin for detached containers&lt;br /&gt;
(i.e., docker run -d ...).  Since earlier versions of Docker used&lt;br /&gt;
/dev/null in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global /dev/null and the container /dev/null as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to criu dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Help Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify -v to see the commands that docker_cr.sh&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/etc/resolv.conf --ext-mount-map /etc/hosts:/etc/hosts --ext-mount-map /etc/hostname:/etc/hostname --ext-mount-map /.dockerinit:/.dockerinit -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o restore.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2260</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2260"/>
		<updated>2015-03-19T21:27:41Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container as of March 2015.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done.&lt;br /&gt;
&lt;br /&gt;
This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
External C/R was done as a proof-of-concept.&lt;br /&gt;
&lt;br /&gt;
'''Native C/R''' using the newly added &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and all commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
[https://www.youtube.com/watch?v=HFt9v6yqsXo video]&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R is at this&lt;br /&gt;
[https://github.com/SaiedKazemi/docker/tree/cr repo].&lt;br /&gt;
Work in underway to integrate C/R into the new libcontainer.&lt;br /&gt;
&lt;br /&gt;
For native C/R support, additional functionality was added to CRIU.&lt;br /&gt;
The most notable addition is the &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; command line option.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it's possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
Work is in progress to add native checkpoint and restore support&lt;br /&gt;
to Docker.  Once ready, specific commands (for example, &amp;quot;docker&lt;br /&gt;
checkpoint&amp;quot; and &amp;quot;docker restore&amp;quot;) will use CRIU to do the actual&lt;br /&gt;
C/R operations while Docker continues to maintain its parent-child&lt;br /&gt;
relationship and container states.&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
/proc/&amp;lt;pid&amp;gt;/map_files, --root is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up /etc/{hostname,hosts,resolv.conf} as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount /.dockerinit.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, /etc/hostname&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at /var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts /dev/null on /dev/stdin for detached containers&lt;br /&gt;
(i.e., docker run -d ...).  Since earlier versions of Docker used&lt;br /&gt;
/dev/null in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global /dev/null and the container /dev/null as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to criu dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Help Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify -v to see the commands that docker_cr.sh&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/etc/resolv.conf --ext-mount-map /etc/hosts:/etc/hosts --ext-mount-map /etc/hostname:/etc/hostname --ext-mount-map /.dockerinit:/.dockerinit -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o restore.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2259</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2259"/>
		<updated>2015-03-19T21:23:56Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done.&lt;br /&gt;
&lt;br /&gt;
This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt;&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
External C/R was done as a proof-of-concept.&lt;br /&gt;
&lt;br /&gt;
'''Native C/R''' using the newly added &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; and&lt;br /&gt;
&amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; commands.&lt;br /&gt;
&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and all commands such as&lt;br /&gt;
&amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
[https://www.youtube.com/watch?v=HFt9v6yqsXo video]&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R is at this&lt;br /&gt;
[https://github.com/SaiedKazemi/docker/tree/cr repo].&lt;br /&gt;
Work in underway to integrate C/R into the new libcontainer.&lt;br /&gt;
&lt;br /&gt;
For native C/R support, additional functionality was added to CRIU.&lt;br /&gt;
The most notable addition is the &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; command line option.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it's possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
Work is in progress to add native checkpoint and restore support&lt;br /&gt;
to Docker.  Once ready, specific commands (for example, &amp;quot;docker&lt;br /&gt;
checkpoint&amp;quot; and &amp;quot;docker restore&amp;quot;) will use CRIU to do the actual&lt;br /&gt;
C/R operations while Docker continues to maintain its parent-child&lt;br /&gt;
relationship and container states.&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
/proc/&amp;lt;pid&amp;gt;/map_files, --root is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up /etc/{hostname,hosts,resolv.conf} as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount /.dockerinit.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, /etc/hostname&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at /var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts /dev/null on /dev/stdin for detached containers&lt;br /&gt;
(i.e., docker run -d ...).  Since earlier versions of Docker used&lt;br /&gt;
/dev/null in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global /dev/null and the container /dev/null as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to criu dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Help Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify -v to see the commands that docker_cr.sh&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/etc/resolv.conf --ext-mount-map /etc/hosts:/etc/hosts --ext-mount-map /etc/hostname:/etc/hostname --ext-mount-map /.dockerinit:/.dockerinit -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o restore.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2258</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2258"/>
		<updated>2015-03-19T21:21:56Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done.&lt;br /&gt;
&lt;br /&gt;
This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as&lt;br /&gt;
=== &amp;lt;code&amp;gt;docker ps, stop, kill&amp;lt;/code&amp;gt; === and === &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; ===&lt;br /&gt;
will not work correctly.&lt;br /&gt;
&lt;br /&gt;
External C/R was done as a proof-of-concept.&lt;br /&gt;
&lt;br /&gt;
'''Native C/R''' using the newly added === &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; === and&lt;br /&gt;
=== &amp;lt;code&amp;gt;docker restore&amp;lt;/code&amp;gt; === commands.&lt;br /&gt;
&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and all commands such as&lt;br /&gt;
=== &amp;lt;code&amp;gt;docker ps, stop, kill &amp;lt;/code&amp;gt; === and === &amp;lt;code&amp;gt;logs&amp;lt;/code&amp;gt; ===&lt;br /&gt;
will work.&lt;br /&gt;
This is obviously the preferred method of checkpointing and restoring Docker containers.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
[https://www.youtube.com/watch?v=HFt9v6yqsXo video]&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R is at this&lt;br /&gt;
[https://github.com/SaiedKazemi/docker/tree/cr repo].&lt;br /&gt;
Work in underway to integrate C/R into the new libcontainer.&lt;br /&gt;
&lt;br /&gt;
For native C/R support, additional functionality was added to CRIU.&lt;br /&gt;
The most notable addition is the === &amp;lt;code&amp;gt;--inherit-fd&amp;lt;/code&amp;gt; ===&lt;br /&gt;
command line option.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it's possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
Work is in progress to add native checkpoint and restore support&lt;br /&gt;
to Docker.  Once ready, specific commands (for example, &amp;quot;docker&lt;br /&gt;
checkpoint&amp;quot; and &amp;quot;docker restore&amp;quot;) will use CRIU to do the actual&lt;br /&gt;
C/R operations while Docker continues to maintain its parent-child&lt;br /&gt;
relationship and container states.&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
/proc/&amp;lt;pid&amp;gt;/map_files, --root is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up /etc/{hostname,hosts,resolv.conf} as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount /.dockerinit.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, /etc/hostname&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at /var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts /dev/null on /dev/stdin for detached containers&lt;br /&gt;
(i.e., docker run -d ...).  Since earlier versions of Docker used&lt;br /&gt;
/dev/null in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global /dev/null and the container /dev/null as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to criu dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Help Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify -v to see the commands that docker_cr.sh&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/etc/resolv.conf --ext-mount-map /etc/hosts:/etc/hosts --ext-mount-map /etc/hostname:/etc/hostname --ext-mount-map /.dockerinit:/.dockerinit -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o restore.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2257</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2257"/>
		<updated>2015-03-19T21:12:58Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R''' using CRIU directly on the command line as it's typically&lt;br /&gt;
done.&lt;br /&gt;
&lt;br /&gt;
This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as ''docker ps''&lt;br /&gt;
and ''docker logs'' will not work correctly.&lt;br /&gt;
&lt;br /&gt;
External C/R was done as a proof-of-concept.&lt;br /&gt;
&lt;br /&gt;
'''Native C/R''' using ''docker checkpoint'' and ''docker restore'' commands.&lt;br /&gt;
&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and commands such as&lt;br /&gt;
''docker ps'' and ''docker logs'' will work.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
[https://www.youtube.com/watch?v=HFt9v6yqsXo video]&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R is at this&lt;br /&gt;
[https://github.com/SaiedKazemi/docker/tree/cr repo].&lt;br /&gt;
Work in underway to integrate C/R into the new libcontainer.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it's possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
Work is in progress to add native checkpoint and restore support&lt;br /&gt;
to Docker.  Once ready, specific commands (for example, &amp;quot;docker&lt;br /&gt;
checkpoint&amp;quot; and &amp;quot;docker restore&amp;quot;) will use CRIU to do the actual&lt;br /&gt;
C/R operations while Docker continues to maintain its parent-child&lt;br /&gt;
relationship and container states.&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
/proc/&amp;lt;pid&amp;gt;/map_files, --root is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up /etc/{hostname,hosts,resolv.conf} as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount /.dockerinit.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, /etc/hostname&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at /var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts /dev/null on /dev/stdin for detached containers&lt;br /&gt;
(i.e., docker run -d ...).  Since earlier versions of Docker used&lt;br /&gt;
/dev/null in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global /dev/null and the container /dev/null as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to criu dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Help Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify -v to see the commands that docker_cr.sh&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/etc/resolv.conf --ext-mount-map /etc/hosts:/etc/hosts --ext-mount-map /etc/hostname:/etc/hostname --ext-mount-map /.dockerinit:/.dockerinit -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o restore.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2256</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2256"/>
		<updated>2015-03-19T21:09:58Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
There are two ways to checkpoint and restore a Docker container:&lt;br /&gt;
&lt;br /&gt;
'''External C/R:''' Using CRIU directly on the command line as it's typically&lt;br /&gt;
done.  This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as ''docker ps''&lt;br /&gt;
and ''docker logs'' will not work correctly.&lt;br /&gt;
&lt;br /&gt;
External C/R was done as a proof-of-concept.&lt;br /&gt;
&lt;br /&gt;
'''Native C/R:''' Using ''docker checkpoint'' and ''docker restore'' commands.&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and commands such as&lt;br /&gt;
''docker ps'' and ''docker logs'' will work.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
[https://www.youtube.com/watch?v=HFt9v6yqsXo video]&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R is at this&lt;br /&gt;
[https://github.com/SaiedKazemi/docker/tree/cr repo].&lt;br /&gt;
Work in underway to integrate C/R into the new libcontainer.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it's possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
Work is in progress to add native checkpoint and restore support&lt;br /&gt;
to Docker.  Once ready, specific commands (for example, &amp;quot;docker&lt;br /&gt;
checkpoint&amp;quot; and &amp;quot;docker restore&amp;quot;) will use CRIU to do the actual&lt;br /&gt;
C/R operations while Docker continues to maintain its parent-child&lt;br /&gt;
relationship and container states.&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
/proc/&amp;lt;pid&amp;gt;/map_files, --root is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up /etc/{hostname,hosts,resolv.conf} as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount /.dockerinit.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, /etc/hostname&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at /var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts /dev/null on /dev/stdin for detached containers&lt;br /&gt;
(i.e., docker run -d ...).  Since earlier versions of Docker used&lt;br /&gt;
/dev/null in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global /dev/null and the container /dev/null as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to criu dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Help Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify -v to see the commands that docker_cr.sh&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/etc/resolv.conf --ext-mount-map /etc/hosts:/etc/hosts --ext-mount-map /etc/hostname:/etc/hostname --ext-mount-map /.dockerinit:/.dockerinit -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o restore.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2255</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2255"/>
		<updated>2015-03-19T21:08:02Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
&lt;br /&gt;
1. External C/R: Using CRIU directly on the command line as it's typically&lt;br /&gt;
done.  This is called external because it's happening external to the&lt;br /&gt;
Docker daemon.  After checkpoint, the Docker daemon thinks that the&lt;br /&gt;
container has exited.  After restore, the Docker daemon doesn't know that&lt;br /&gt;
the container is running again.  Therefore, commands such as ''docker ps''&lt;br /&gt;
and ''docker logs'' will not work correctly.&lt;br /&gt;
&lt;br /&gt;
External C/R was done as a proof-of-concept.&lt;br /&gt;
&lt;br /&gt;
2. Native C/R: Using ''docker checkpoint'' and ''docker restore'' commands.&lt;br /&gt;
Because the Docker daemon is involved in both checkpoint and restore,&lt;br /&gt;
its notion of the container state will be consistent and commands such as&lt;br /&gt;
''docker ps'' and ''docker logs'' will work.&lt;br /&gt;
&lt;br /&gt;
Native C/R is work in progress, say pre-alpha quality.  You can&lt;br /&gt;
watch this short demo&lt;br /&gt;
[https://www.youtube.com/watch?v=HFt9v6yqsXo video]&lt;br /&gt;
to see how it works.  Source files for Docker 1.5 C/R is at this&lt;br /&gt;
[https://github.com/SaiedKazemi/docker/tree/cr repo].&lt;br /&gt;
Work in underway to integrate C/R into the new libcontainer.&lt;br /&gt;
&lt;br /&gt;
== External C/R ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it's possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
Work is in progress to add native checkpoint and restore support&lt;br /&gt;
to Docker.  Once ready, specific commands (for example, &amp;quot;docker&lt;br /&gt;
checkpoint&amp;quot; and &amp;quot;docker restore&amp;quot;) will use CRIU to do the actual&lt;br /&gt;
C/R operations while Docker continues to maintain its parent-child&lt;br /&gt;
relationship and container states.&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
/proc/&amp;lt;pid&amp;gt;/map_files, --root is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up /etc/{hostname,hosts,resolv.conf} as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount /.dockerinit.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, /etc/hostname&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at /var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts /dev/null on /dev/stdin for detached containers&lt;br /&gt;
(i.e., docker run -d ...).  Since earlier versions of Docker used&lt;br /&gt;
/dev/null in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global /dev/null and the container /dev/null as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to criu dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Help Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify -v to see the commands that docker_cr.sh&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/etc/resolv.conf --ext-mount-map /etc/hosts:/etc/hosts --ext-mount-map /etc/hostname:/etc/hostname --ext-mount-map /.dockerinit:/.dockerinit -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o restore.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Main_Page&amp;diff=1913</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Main_Page&amp;diff=1913"/>
		<updated>2015-01-02T17:18:45Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Download box|right}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&amp;lt;big&amp;gt;Welcome to CRIU, a project to implement checkpoint/restore functionality for Linux in userspace.&lt;br /&gt;
&lt;br /&gt;
Checkpoint/Restore In Userspace, or CRIU (pronounced kree-oo, IPA: /krɪʊ/, Russian: криу), is a software tool for Linux operating system. Using this tool, you can freeze a running application (or part of it) and checkpoint it to a hard drive as a collection of files. You can then use the files to restore and run the application from the point it was frozen at. The distinctive feature of the CRIU project is that it is mainly implemented in user space.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #f6f6f6; padding: 1em; text-align: left;&amp;quot; class=&amp;quot;plainlinks&amp;quot;&amp;gt;&lt;br /&gt;
[http://criu.org http://static.openvz.org/criu_88x31.gif] is a project of [https://openvz.org http://static.openvz.org/openvz_88x31.gif] and is supported by [http://www.parallels.com http://static.openvz.org/parallels_88x31.gif] and [https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;amp;hosted_button_id=FZ8W4VU9AS2XL your donations].&amp;lt;/div&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
{{Like}}&lt;br /&gt;
&amp;lt;br clear=&amp;quot;both&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 33%&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
;Getting [[packages]] for your distribution&lt;br /&gt;
: Or try manual [[installation]] to have CRIU on your system&lt;br /&gt;
&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;[[Usage|CLI]], [[RPC]] and [[C API]]&lt;br /&gt;
: Three ways to start using the C/R functionality&lt;br /&gt;
&lt;br /&gt;
;[[Usage scenarios]]&lt;br /&gt;
: Ideas how criu can be used (some are crazy indeed)&lt;br /&gt;
&lt;br /&gt;
;[[What software is supported]]&lt;br /&gt;
: Describes TODO list in higher level terms&lt;br /&gt;
&lt;br /&gt;
;[[:Category:HOWTO]]&lt;br /&gt;
: Collection of real world examples of how to use CRIU. Some are complex, some are not. HOW TO dump a [[simple loop]] might be the best one to start with.&lt;br /&gt;
&lt;br /&gt;
;[[:Category:API]]&lt;br /&gt;
: Collection of pages about CRIU's API.&lt;br /&gt;
&lt;br /&gt;
;[[When C/R fails]]&lt;br /&gt;
: A sort of troubleshooting guide&lt;br /&gt;
&lt;br /&gt;
;[[What can change after C/R]]&lt;br /&gt;
: CRIU cannot (yet) save and restore every single bit of tasks' state. This page describes what bits visible through standard kernel API are such.&lt;br /&gt;
&lt;br /&gt;
;[[What cannot be checkpointed]]&lt;br /&gt;
: What an application could do to make CRIU refuse to dump it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 33%; margin-left: 0.5%;&amp;quot;&amp;gt;&lt;br /&gt;
== Developing ==&lt;br /&gt;
If you're interested in CRIU development, please subscribe to the criu mailing list: http://lists.openvz.org/mailman/listinfo/criu&lt;br /&gt;
&lt;br /&gt;
;[[Images]]&lt;br /&gt;
: Description of image files format&lt;br /&gt;
&lt;br /&gt;
;[[Plugins]]&lt;br /&gt;
: CRIU can call plugins provided by people&lt;br /&gt;
&lt;br /&gt;
;[[Upstream kernel commits]]&lt;br /&gt;
: Mainline kernel commits tracker&lt;br /&gt;
&lt;br /&gt;
;[[Recent commits]]&lt;br /&gt;
: CRIU tool repository commits&lt;br /&gt;
&lt;br /&gt;
;[[Manpages]]&lt;br /&gt;
: Kernel's manpages commits tracker&lt;br /&gt;
&lt;br /&gt;
;[[ZDTM Test Suite]]&lt;br /&gt;
: Zero downtime test suite&lt;br /&gt;
&lt;br /&gt;
;[[Todo|TODO]]&lt;br /&gt;
: Current TODO list&lt;br /&gt;
&lt;br /&gt;
;[[UserNamespace|User namespace]]&lt;br /&gt;
: Implementing user namespace support&lt;br /&gt;
&lt;br /&gt;
;[[Postulates]]&lt;br /&gt;
: What to keep in mind when writing new code&lt;br /&gt;
&lt;br /&gt;
;[http://criu.org/cov/ Code coverage results]&lt;br /&gt;
: Shows how zdtm run covers the criu code paths&lt;br /&gt;
&lt;br /&gt;
;[[How to submit patches]]&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 33%&amp;quot;&amp;gt;&lt;br /&gt;
{{News block 2}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;both&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 33%&amp;quot;&amp;gt;&lt;br /&gt;
== [[:Category:Under the hood|Under the hood]] ==&lt;br /&gt;
* [[Sockets]]&lt;br /&gt;
* [[Memory dumping and restoring]]&lt;br /&gt;
* [[Checkpoint/Restore]]&lt;br /&gt;
* [[TCP connection]]&lt;br /&gt;
* [[Files]]&lt;br /&gt;
* [[Pending signals]]&lt;br /&gt;
* [[Stages of restoring]]&lt;br /&gt;
* [[COW]]&lt;br /&gt;
* [[Code blobs]]&lt;br /&gt;
* [[Comparison to other CR projects]]&lt;br /&gt;
* [[Memory changes tracking]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:left; width: 33%; margin-left: 0.5%;&amp;quot;&amp;gt;&lt;br /&gt;
== External links ==&lt;br /&gt;
{{:Articles}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right; width: 33%;&amp;quot;&amp;gt;&lt;br /&gt;
== Other ==&lt;br /&gt;
* Project [[history]]&lt;br /&gt;
* [[Logo]] description&lt;br /&gt;
* [[Events]]&lt;br /&gt;
* Join the [[CRIU acronym fun]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Action_scripts&amp;diff=1911</id>
		<title>Action scripts</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Action_scripts&amp;diff=1911"/>
		<updated>2015-01-02T17:14:18Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;With the --action-script command line option, CRIU can call your action scripts (also known as hooks) at various stages of dumping/restoring. Hooks can be one of&lt;br /&gt;
&lt;br /&gt;
;network-lock&lt;br /&gt;
: request to lock a container network (used by Docker and [[LXC]])&lt;br /&gt;
&lt;br /&gt;
;network-unlock&lt;br /&gt;
: requested to unlock a container network (used by Docker and [[LXC]])&lt;br /&gt;
&lt;br /&gt;
;post-dump&lt;br /&gt;
: called when CRIU finished dumping tasks before unfreezing them&lt;br /&gt;
&lt;br /&gt;
;post-restore&lt;br /&gt;
: called when CRIU has finished restoring tasks before unlocking the network&lt;br /&gt;
&lt;br /&gt;
;setup-namespaces&lt;br /&gt;
: called when the root task is alive and new set of namespaces is created to set them up&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CLI ==&lt;br /&gt;
These hooks are added with the --action-script shell-code-to-execute option. When called, the CRTOOLS_SCRIPT_ACTION environment is set to a value determining which type of action is performed.&lt;br /&gt;
&lt;br /&gt;
== RPC ==&lt;br /&gt;
&lt;br /&gt;
In case or RPC, action scripts are implemented as notifications -- once CRIU service wants to execute a script it send an RPC message to caller and waits for it to respond with &amp;lt;code&amp;gt;criu_req&amp;lt;/code&amp;gt; message having &amp;lt;code&amp;gt;notify_success = true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Library ==&lt;br /&gt;
&lt;br /&gt;
When using a library one can setup a callback using the &amp;lt;code&amp;gt;criu_set_notify&amp;lt;/code&amp;gt; routine.&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;br /&gt;
[[Category:API]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Action_scripts&amp;diff=1885</id>
		<title>Action scripts</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Action_scripts&amp;diff=1885"/>
		<updated>2014-12-30T18:33:33Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;With the --action-script command line option, CRIU can call your action scripts (also known as hooks) at various stages of dumping/restoring. Hooks can be one of&lt;br /&gt;
&lt;br /&gt;
;network-lock&lt;br /&gt;
: request to lock an [[LXC]] container network&lt;br /&gt;
&lt;br /&gt;
;network-unlock&lt;br /&gt;
: requested to unlock an [[LXC]] container network&lt;br /&gt;
&lt;br /&gt;
;post-dump&lt;br /&gt;
: called when CRIU finished dumping tasks before unfreezing them&lt;br /&gt;
&lt;br /&gt;
;post-restore&lt;br /&gt;
: called when CRIU has finished restoring tasks before unlocking the network&lt;br /&gt;
&lt;br /&gt;
;setup-namespaces&lt;br /&gt;
: called when the root task is alive and new set of namespaces is created to set them up&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CLI ==&lt;br /&gt;
These hooks are added with the --action-script shell-code-to-execute option. When called, the CRTOOLS_SCRIPT_ACTION environment is set to a value determining which type of action is performed.&lt;br /&gt;
&lt;br /&gt;
== RPC ==&lt;br /&gt;
&lt;br /&gt;
In case or RPC, action scripts are implemented as notifications -- once CRIU service wants to execute a script it send an RPC message to caller and waits for it to respond with &amp;lt;code&amp;gt;criu_req&amp;lt;/code&amp;gt; message having &amp;lt;code&amp;gt;notify_success = true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Library ==&lt;br /&gt;
&lt;br /&gt;
When using a library one can setup a callback using the &amp;lt;code&amp;gt;criu_set_notify&amp;lt;/code&amp;gt; routine.&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=1697</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=1697"/>
		<updated>2014-09-12T20:30:13Z</updated>

		<summary type="html">&lt;p&gt;Saied Kazemi: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This HOWTO page describes how to checkpoint and restore a Docker container.&lt;br /&gt;
&lt;br /&gt;
== Background ==&lt;br /&gt;
&lt;br /&gt;
Starting with CRIU 1.3, it's possible to checkpoint and restore a&lt;br /&gt;
process tree running inside a Docker container.  However, it's&lt;br /&gt;
important to note that Docker needs native support for checkpoint&lt;br /&gt;
and restore in order to maintain its parent-child relationship and&lt;br /&gt;
to correctly keep track of container states.  In other words, while&lt;br /&gt;
CRIU can C/R a process tree, the restored tree will not become a&lt;br /&gt;
child of Docker and, from Docker's point of view, the container's&lt;br /&gt;
state will remain &amp;quot;Exited&amp;quot; (even after successful restore).&lt;br /&gt;
&lt;br /&gt;
Work is in progress to add native checkpoint and restore support&lt;br /&gt;
to Docker.  Once ready, specific commands (for example, &amp;quot;docker&lt;br /&gt;
checkpoint&amp;quot; and &amp;quot;docker restore&amp;quot;) will use CRIU to do the actual&lt;br /&gt;
C/R operations while Docker continues to maintain its parent-child&lt;br /&gt;
relationship and container states.&lt;br /&gt;
&lt;br /&gt;
It's important to re-emphasize that by checkpointing and restoring&lt;br /&gt;
a Docker container, we mean C/R of a process tree running inside a&lt;br /&gt;
container, excluding the Docker daemon itself.  As CRIU currently&lt;br /&gt;
does not support nested PID namespaces, the C/R process tree cannot&lt;br /&gt;
include the Docker daemon which runs in the global PID namespace.&lt;br /&gt;
&lt;br /&gt;
== Command Line Options ==&lt;br /&gt;
&lt;br /&gt;
In addition to the usual CRIU command line options used when&lt;br /&gt;
checkpointing and restoring a process tree, the following command&lt;br /&gt;
line options are needed for Docker containers.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--root&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option has been used in the past only for restore operations&lt;br /&gt;
that wanted to change the root of the mount namespace.  It was not&lt;br /&gt;
used for checkpoint operations.&lt;br /&gt;
&lt;br /&gt;
However, because Docker by default uses the AUFS graph driver and&lt;br /&gt;
the AUFS module in the kernel reveals branch pathnames in&lt;br /&gt;
/proc/&amp;lt;pid&amp;gt;/map_files, --root is used to specify the root of the&lt;br /&gt;
mount namespace.  Once the kernel AUFS module is fixed, it won't&lt;br /&gt;
be necessary to specify this option anymore.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--ext-mount-map&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This option is used to specify the path of the external bind mounts.&lt;br /&gt;
Docker sets up /etc/{hostname,hosts,resolv.conf} as targets with&lt;br /&gt;
source files outside the container's mount namespace.  Older versions&lt;br /&gt;
of Docker also bind mount /.dockerinit.&lt;br /&gt;
&lt;br /&gt;
For example, assuming the default Docker configuration, /etc/hostname&lt;br /&gt;
in the container's mount namespace is bind mounted from the source&lt;br /&gt;
at /var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--manage-cgroups&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
When a process tree exits after a checkpoint operation, the cgroups&lt;br /&gt;
that Docker had created for the container are removed.  This option&lt;br /&gt;
is needed during restore to move the process tree into its cgroups,&lt;br /&gt;
re-creating them if necessary.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;--evasive-devices&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Docker bind mounts /dev/null on /dev/stdin for detached containers&lt;br /&gt;
(i.e., docker run -d ...).  Since earlier versions of Docker used&lt;br /&gt;
/dev/null in the global namespace, this option tells CRIU to treat&lt;br /&gt;
the global /dev/null and the container /dev/null as the same device.&lt;br /&gt;
&lt;br /&gt;
== Restore Prework ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, by default Docker uses AUFS to set up the&lt;br /&gt;
container's filesystem.  When Docker notices that the process has&lt;br /&gt;
exited (due to criu dump), it dismantles the filesystem.  We need&lt;br /&gt;
to set up the filesystem again before attempting to restore.&lt;br /&gt;
&lt;br /&gt;
== An Example ==&lt;br /&gt;
&lt;br /&gt;
Below is an example to show C/R operations for a shell script that&lt;br /&gt;
continuously appends a number to a file.  You can use tail -f to&lt;br /&gt;
see the process in action.&lt;br /&gt;
&lt;br /&gt;
As you will see below, after restore, the process's parent is PID&lt;br /&gt;
1 (init), not Docker.  Also, although the process has been successfully&lt;br /&gt;
restored, Docker still thinks that the container has exited.&lt;br /&gt;
&lt;br /&gt;
To set up the container's AUFS filesystem before restore, its branch&lt;br /&gt;
information should be saved before checkpointing the container.&lt;br /&gt;
For convenience, however, AUFS branch information is saved in the&lt;br /&gt;
dump.log file.  So we can examine dump.log to set up the filesystem&lt;br /&gt;
again.&lt;br /&gt;
&lt;br /&gt;
For brevity, the 64-character long container ID is replaced by the&lt;br /&gt;
string &amp;lt;container_id&amp;gt; in the following lines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ docker run -d busybox:latest /bin/sh -c 'i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done'&lt;br /&gt;
&amp;lt;container_id&amp;gt;&lt;br /&gt;
$ &lt;br /&gt;
$ docker ps&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 seconds ago  Up 4 seconds&lt;br /&gt;
$ &lt;br /&gt;
$ sudo criu dump -o dump.log -v4 -t 17810 \&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/etc/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/etc/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/etc/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/.dockerinit \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/dump.log&lt;br /&gt;
(00.020103) Dumping finished successfully&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 6 minutes ago  Exited (-1) 4 minutes ago&lt;br /&gt;
$&lt;br /&gt;
$ sudo mount -t aufs -o br=\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;:\&lt;br /&gt;
/var/lib/docker/aufs/diff/&amp;lt;container_id&amp;gt;-init:\&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721:\&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16:\&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229:\&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158:\&lt;br /&gt;
none /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt;&lt;br /&gt;
$&lt;br /&gt;
$ sudo criu restore -o restore.log -v4 -d&lt;br /&gt;
	-D /tmp/img/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--root /var/lib/docker/aufs/mnt/&amp;lt;container_id&amp;gt; \&lt;br /&gt;
	--ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/resolv.conf \&lt;br /&gt;
	--ext-mount-map /etc/hosts:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hosts \&lt;br /&gt;
	--ext-mount-map /etc/hostname:/var/lib/docker/containers/&amp;lt;container_id&amp;gt;/hostname \&lt;br /&gt;
	--ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 \&lt;br /&gt;
	--manage-cgroups \&lt;br /&gt;
	--evasive-devices&lt;br /&gt;
$&lt;br /&gt;
$ sudo grep successful /tmp/img/&amp;lt;container_id&amp;gt;/restore.log&lt;br /&gt;
(00.424428) Restore finished successfully. Resuming tasks.&lt;br /&gt;
$&lt;br /&gt;
$ ps -ef | grep /bin/sh&lt;br /&gt;
root     18580     1  0 12:38 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
$&lt;br /&gt;
$ docker ps -a&lt;br /&gt;
CONTAINER ID  IMAGE           COMMAND           CREATED        STATUS&lt;br /&gt;
168aefb8881b  busybox:latest  &amp;quot;/bin/sh -c 'i=0; 7 minutes ago  Exited (-1) 5 minutes ago&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Help Script ==&lt;br /&gt;
&lt;br /&gt;
As seen in the above examples, the CRIU command line for checkpointing and&lt;br /&gt;
restoring a Docker container is pretty long.  For restore, there is also&lt;br /&gt;
an additional step to set up the root filesystem before invoking CRIU.&lt;br /&gt;
&lt;br /&gt;
To automate the C/R process, there is a helper script in the contrib&lt;br /&gt;
subdirectory of CRIU sources, called docker_cr.sh.  In addition to&lt;br /&gt;
invoking CRIU, this helper script sets up the root filesystem for AUFS,&lt;br /&gt;
UnionFS, and VFS for restore.&lt;br /&gt;
&lt;br /&gt;
With docker_cr.sh, all you have to provide is the container ID.&lt;br /&gt;
If you don't specify a container ID, docker_cr.sh will list all running&lt;br /&gt;
containers and prompt you to choose one.  Also, as shown in the help&lt;br /&gt;
output below, by setting the appropriate environment variable, it's&lt;br /&gt;
possible to tell docker_cr.sh which Docker and CRIU binaries to use,&lt;br /&gt;
where Docker's home directory is, and where CRIU should save and look&lt;br /&gt;
for its image files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh --help&lt;br /&gt;
Usage:&lt;br /&gt;
	docker_cr.sh -c|-r [-hv] [&amp;lt;container_id&amp;gt;]&lt;br /&gt;
	-c, --checkpoint	checkpoint container&lt;br /&gt;
	-h, --help		print help message&lt;br /&gt;
	-r, --restore		restore container&lt;br /&gt;
	-v, --verbose		enable verbose mode&lt;br /&gt;
&lt;br /&gt;
Environment:&lt;br /&gt;
	DOCKER_HOME		(default /var/lib/docker)&lt;br /&gt;
	CRIU_IMG_DIR		(default /var/lib/docker/criu_img)&lt;br /&gt;
	DOCKER_BINARY		(default docker)&lt;br /&gt;
	CRIU_BINARY		(default criu)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Below is an example to checkpoint and restore Docker container 4397:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c 4397&lt;br /&gt;
dump successful&lt;br /&gt;
# docker_cr.sh -r 4397&lt;br /&gt;
restore successful&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally, you can specify -v to see the commands that docker_cr.sh&lt;br /&gt;
executes.  For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# docker_cr.sh -c -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu dump -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o dump.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/etc/resolv.conf --ext-mount-map /etc/hosts:/etc/hosts --ext-mount-map /etc/hostname:/etc/hostname --ext-mount-map /.dockerinit:/.dockerinit -t 5991 --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
dump successful&lt;br /&gt;
(00.020827) Dumping finished successfully&lt;br /&gt;
&lt;br /&gt;
# docker_cr.sh -r -v 40d3&lt;br /&gt;
docker binary: docker&lt;br /&gt;
criu binary: criu&lt;br /&gt;
image directory: /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
container root directory: /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
mount -t aufs -o&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
/var/lib/docker/aufs/diff/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf-init&lt;br /&gt;
/var/lib/docker/aufs/diff/a9eb172552348a9a49180694790b33a1097f546456d041b6e82e4d7716ddb721&lt;br /&gt;
/var/lib/docker/aufs/diff/120e218dd395ec314e7b6249f39d2853911b3d6def6ea164ae05722649f34b16&lt;br /&gt;
/var/lib/docker/aufs/diff/42eed7f1bf2ac3f1610c5e616d2ab1ee9c7290234240388d6297bc0f32c34229&lt;br /&gt;
/var/lib/docker/aufs/diff/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158&lt;br /&gt;
none&lt;br /&gt;
/var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf&lt;br /&gt;
&lt;br /&gt;
criu restore -v4 -D /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf -o restore.log --manage-cgroups --evasive-devices --ext-mount-map /etc/resolv.conf:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/resolv.conf --ext-mount-map /etc/hosts:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hosts --ext-mount-map /etc/hostname:/var/lib/docker/containers/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/hostname --ext-mount-map /.dockerinit:/var/lib/docker/init/dockerinit-1.0.0 -d --root /var/lib/docker/aufs/mnt/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf --pidfile /var/lib/docker/criu_img/40d363f564e00a2f893579fa012a200e475dcf8df47f2a22b7dd0860ffc3d7bf/restore.pid&lt;br /&gt;
&lt;br /&gt;
restore successful&lt;br /&gt;
(00.408807) Restore finished successfully. Resuming tasks.&lt;br /&gt;
&lt;br /&gt;
root      6206     1  1 10:49 ?        00:00:00 /bin/sh -c i=0; while true; do echo $i &amp;gt;&amp;gt; /foo; i=$(expr $i + 1); sleep 3; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Saied Kazemi</name></author>
	</entry>
</feed>