<?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=Boucher</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=Boucher"/>
	<link rel="alternate" type="text/html" href="https://criu.org/Special:Contributions/Boucher"/>
	<updated>2026-05-13T16:21:49Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.6</generator>
	<entry>
		<id>https://criu.org/index.php?title=Installation&amp;diff=4209</id>
		<title>Installation</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Installation&amp;diff=4209"/>
		<updated>2017-05-17T13:35:34Z</updated>

		<summary type="html">&lt;p&gt;Boucher: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;code&amp;gt;criu&amp;lt;/code&amp;gt; is an utility to checkpoint/restore a process tree. This page describes how to manually build and install prerequisites and the tool itself.&lt;br /&gt;
&lt;br /&gt;
== Installing from packages ==&lt;br /&gt;
&lt;br /&gt;
Some distributions provide ready-to-use [[packages]]. If no, or the CRIU version you want is not yet there, you will need to get CRIU sources and compile it.&lt;br /&gt;
&lt;br /&gt;
== Obtaining CRIU Source ==&lt;br /&gt;
&lt;br /&gt;
You can download the source code as a release tarball or sync the [https://github.com/xemul/criu git repository]. If you plan to modify CRIU sources the latter way is highly recommended.&lt;br /&gt;
&lt;br /&gt;
=== Getting source tarball ===&lt;br /&gt;
: {{Latest release}}&lt;br /&gt;
&lt;br /&gt;
=== Cloning git repository ===&lt;br /&gt;
 git clone https://github.com/xemul/criu&lt;br /&gt;
&lt;br /&gt;
== Dependencies ==&lt;br /&gt;
&lt;br /&gt;
=== Compiler and C Library ===&lt;br /&gt;
&lt;br /&gt;
CRIU is mostly written in C and the build system is based on Makefiles. Thus just install standard &amp;lt;code&amp;gt;gcc&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; packages (on Debian, &amp;lt;code&amp;gt;[https://packages.debian.org/build-essential build-essential]&amp;lt;/code&amp;gt; will pull in both at once).&lt;br /&gt;
&lt;br /&gt;
For building on x86 with compatible 32-bit applications C/R support you will need &amp;lt;code&amp;gt;libc6-dev-i386, gcc-multilib&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;gcc&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you are cross compiling for ARM, use distribution packages or download prebuilt toolchains from Linaro.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px&amp;quot;&amp;gt;&lt;br /&gt;
Downloading Linaro toolchains&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
 sudo apt-get install lib32stdc++6 lib32z1 # These are ia32 binaries&lt;br /&gt;
 mkdir -p deps/`uname -m`-linux-gnu&lt;br /&gt;
 cd deps&lt;br /&gt;
 wget http://releases.linaro.org/14.09/components/toolchain/binaries/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux.tar.xz&lt;br /&gt;
 tar --strip=1 -C `uname -m`-linux-gnu -xf gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux.tar.xz&lt;br /&gt;
 wget http://releases.linaro.org/14.09/components/toolchain/binaries/gcc-linaro-aarch64-linux-gnu-4.9-2014.09_linux.tar.xz&lt;br /&gt;
 tar --strip=1 -C `uname -m`-linux-gnu -xf gcc-linaro-aarch64-linux-gnu-4.9-2014.09_linux.tar.xz&lt;br /&gt;
 cd ..&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protocol Buffers ===&lt;br /&gt;
&lt;br /&gt;
CRIU uses the [https://developers.google.com/protocol-buffers/ Google Protocol Buffers] to read and write [[images]] and thus requires [https://github.com/protobuf-c/protobuf-c C language bindings]. The &amp;lt;code&amp;gt;protoc&amp;lt;/code&amp;gt; tool is required at build time and the &amp;lt;code&amp;gt;libprotobuf-c.so&amp;lt;/code&amp;gt; shared object is required at build and run time. [[CRIT]] also uses python language bindings for protocol buffers and requires the &amp;lt;code&amp;gt;descriptor.proto&amp;lt;/code&amp;gt; file typically provided by a distribution's protobuf development package.&lt;br /&gt;
&lt;br /&gt;
==== Distribution Packages ====&lt;br /&gt;
The easiest way is to install distribution packages.&lt;br /&gt;
&lt;br /&gt;
* RPM package names&lt;br /&gt;
** &amp;lt;code&amp;gt;group Development\ Tools&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;protobuf&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;protobuf-c&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;protobuf-c-devel&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;protobuf-compiler&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;protobuf-devel&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;protobuf-python&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;libnet-devel&amp;lt;/code&amp;gt;&lt;br /&gt;
* Debian package names&lt;br /&gt;
** &amp;lt;code&amp;gt;build-essential&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;libprotobuf-dev&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;libprotobuf-c0-dev&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;protobuf-c-compiler&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;protobuf-compiler&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;python-protobuf&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;libnet1-dev&amp;lt;/code&amp;gt;&lt;br /&gt;
* Ubuntu&lt;br /&gt;
** The below will get your freshly installed Ubuntu host ready to compile criu. &amp;quot;--no-install-recommends&amp;quot; parameter is to avoid asciidoc pulling in a lot of dependencies.&lt;br /&gt;
** sudo apt-get install --no-install-recommends git build-essential libprotobuf-dev libprotobuf-c0-dev protobuf-c-compiler protobuf-compiler python-protobuf libnl-3-dev libpth-dev pkg-config libcap-dev asciidoc libnet-dev&lt;br /&gt;
&lt;br /&gt;
==== Building Protocol Buffers From Source ====&lt;br /&gt;
If you would like to build from source, you can use the following commands to obtain the source code repositories, configure, and build the code. On a Debian based system, you may have to install &amp;lt;code&amp;gt;autoconf curl g++ libtool&amp;lt;/code&amp;gt; packages first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px&amp;quot;&amp;gt;&lt;br /&gt;
To build protobuf&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
 cd deps&lt;br /&gt;
 git clone https://github.com/google/protobuf.git protobuf&lt;br /&gt;
 cd protobuf&lt;br /&gt;
 ./autogen.sh&lt;br /&gt;
 ./configure --prefix=`pwd`/../`uname -m`-linux-gnu&lt;br /&gt;
 make&lt;br /&gt;
 make install&lt;br /&gt;
 cd ../..&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px&amp;quot;&amp;gt;&lt;br /&gt;
To build protobuf-c&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
 cd deps&lt;br /&gt;
 git clone https://github.com/protobuf-c/protobuf-c.git protobuf-c&lt;br /&gt;
 cd protobuf-c&lt;br /&gt;
 ./autogen.sh&lt;br /&gt;
 mkdir ../pbc-`uname -m`&lt;br /&gt;
 cd ../pbc-`uname -m`&lt;br /&gt;
 ../protobuf-c/configure --prefix=`pwd`/../`uname -m`-linux-gnu \&lt;br /&gt;
   PKG_CONFIG_PATH=`pwd`/../`uname -m`-linux-gnu/lib/pkgconfig&lt;br /&gt;
 make&lt;br /&gt;
 make install&lt;br /&gt;
 cd ../..&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px&amp;quot;&amp;gt;&lt;br /&gt;
To cross-compile for ARM some more tricks will be required.&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
For ARMv7&lt;br /&gt;
&lt;br /&gt;
 cd deps&lt;br /&gt;
 mkdir -p pbc-arm&lt;br /&gt;
 cd pbc-arm&lt;br /&gt;
 ../protobuf-c/configure --host=arm-linux-gnueabihf --prefix=`pwd`/../arm-linux-gnueabihf \&lt;br /&gt;
                         --disable-protoc PATH=`pwd`/../`uname -m`-linux-gnu/bin:$PATH&lt;br /&gt;
 make PATH=`pwd`/../`uname -m`-linux-gnu/bin:$PATH&lt;br /&gt;
 make install PATH=`pwd`/../`uname -m`-linux-gnu/bin:$PATH&lt;br /&gt;
 cd ../..&lt;br /&gt;
&lt;br /&gt;
For ARM8&lt;br /&gt;
&lt;br /&gt;
 cd deps&lt;br /&gt;
 mkdir -p pbc-aarch64&lt;br /&gt;
 cd pbc-aarch64&lt;br /&gt;
  ../protobuf-c/configure --host=aarch64-linux-gnu --prefix=`pwd`/../aarch64-linux-gnu \&lt;br /&gt;
                          --disable-protoc PATH=`pwd`/../`uname -m`-linux-gnu/bin:$PATH&lt;br /&gt;
 make PATH=`pwd`/../`uname -m`-linux-gnu/bin:$PATH&lt;br /&gt;
 make install PATH=`pwd`/../`uname -m`-linux-gnu/bin:$PATH&lt;br /&gt;
 cd ../..&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Other deps ===&lt;br /&gt;
* &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt; to check on build library dependencies.&lt;br /&gt;
* &amp;lt;code&amp;gt;libnl3&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;libnl3-devel&amp;lt;/code&amp;gt; (RPM distros) or &amp;lt;code&amp;gt;libnl-3-dev&amp;lt;/code&amp;gt; (DEB distros) for network operations.&lt;br /&gt;
* &amp;lt;code&amp;gt;python-ipaddr&amp;lt;/code&amp;gt; is used by CRIT to pretty-print ip.&lt;br /&gt;
* If &amp;lt;code&amp;gt;libbsd&amp;lt;/code&amp;gt; available, CRIU will be compiled with setproctitle() support. It will allow to make process titles of service workers to be more verbose.&lt;br /&gt;
* The iproute2 tool version 3.5.0 or higher is needed for dumping network namespaces. The latest one can be cloned from [http://git.kernel.org/?p=linux/kernel/git/shemminger/iproute2.git;a=summary iproute2]. It should be compiled and a path to ip written in the environment variable &amp;lt;code&amp;gt;CR_IP_TOOL&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;libcap-devel&amp;lt;/code&amp;gt; (RPM) or &amp;lt;code&amp;gt;libcap-dev&amp;lt;/code&amp;gt; (DEB)&lt;br /&gt;
* If you would like to use &amp;lt;code&amp;gt;make test&amp;lt;/code&amp;gt; you should install &amp;lt;code&amp;gt;libaio-devel&amp;lt;/code&amp;gt; (RPM) or &amp;lt;code&amp;gt;libaio-dev&amp;lt;/code&amp;gt; (DEB).&lt;br /&gt;
* For test launcher &amp;lt;code&amp;gt;zdtm.py&amp;lt;/code&amp;gt; you need &amp;lt;code&amp;gt;PyYAML&amp;lt;/code&amp;gt; (RPM) or &amp;lt;code&amp;gt;python-yaml&amp;lt;/code&amp;gt; (DEB).&lt;br /&gt;
&lt;br /&gt;
== Linux Kernel ==&lt;br /&gt;
&lt;br /&gt;
Linux kernel v3.11 or newer is required, with some specific options set. If your distribution does not provide needed kernel, you might want to compile one yourself.&lt;br /&gt;
&lt;br /&gt;
=== Configuring the kernel ===&lt;br /&gt;
&lt;br /&gt;
Most likely the first thing to enable is the &amp;lt;code&amp;gt;CONFIG_EXPERT=y&amp;lt;/code&amp;gt; (General setup -&amp;gt; Configure standard kernel features (expert users)) option, which on x86_64 depends on the &amp;lt;code&amp;gt;CONFIG_EMBEDDED=y&amp;lt;/code&amp;gt; (General setup -&amp;gt; Embedded system) one (welcome to Kconfig reverse chains hell).&lt;br /&gt;
&lt;br /&gt;
The following options must be enabled for CRIU to work:&lt;br /&gt;
&lt;br /&gt;
* ''General setup'' options&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_CHECKPOINT_RESTORE=y&amp;lt;/code&amp;gt; (Checkpoint/restore support)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_NAMESPACES=y&amp;lt;/code&amp;gt; (Namespaces support)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_UTS_NS=y&amp;lt;/code&amp;gt; (Namespaces support -&amp;gt; UTS namespace)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_IPC_NS=y&amp;lt;/code&amp;gt; (Namespaces support -&amp;gt; IPC namespace)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_PID_NS=y&amp;lt;/code&amp;gt; (Namespaces support -&amp;gt; PID namespaces)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_NET_NS=y&amp;lt;/code&amp;gt; (Namespaces support -&amp;gt; Network namespace)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_FHANDLE=y&amp;lt;/code&amp;gt; (Open by fhandle syscalls)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_EVENTFD=y&amp;lt;/code&amp;gt; (Enable eventfd() system call)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_EPOLL=y&amp;lt;/code&amp;gt; (Enable eventpoll support)&lt;br /&gt;
* ''Networking support -&amp;gt; Networking options'' options for sock-diag subsystem&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_UNIX_DIAG=y&amp;lt;/code&amp;gt; (Unix domain sockets -&amp;gt; UNIX: socket monitoring interface)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_INET_DIAG=y&amp;lt;/code&amp;gt; (TCP/IP networking -&amp;gt; INET: socket monitoring interface)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_INET_UDP_DIAG=y&amp;lt;/code&amp;gt; (TCP/IP networking -&amp;gt; INET: socket monitoring interface -&amp;gt; UDP: socket monitoring interface)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_PACKET_DIAG=y&amp;lt;/code&amp;gt; (Packet socket -&amp;gt; Packet: sockets monitoring interface)&lt;br /&gt;
** &amp;lt;code&amp;gt;CONFIG_NETLINK_DIAG=y&amp;lt;/code&amp;gt; (Netlink socket -&amp;gt; Netlink: sockets monitoring interface)&lt;br /&gt;
&lt;br /&gt;
Other options not required by CRIU, but C/R supported ([[ZDTM test suite]] may fail without them):&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFIG_INOTIFY_USER=y&amp;lt;/code&amp;gt; (File systems -&amp;gt; Inotify support for userspace)&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFIG_FANOTIFY=y&amp;lt;/code&amp;gt; (File systems -&amp;gt; Filesystem wide access notification)&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFIG_NETFILTER_XT_MARK=y&amp;lt;/code&amp;gt; (Networking support -&amp;gt; Networking options -&amp;gt; Network packet filtering framework (Netfilter) -&amp;gt; Core Netfilter Configuration -&amp;gt; Netfilter Xtables support (required for ip_tables) -&amp;gt; nfmark target and match support)&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFIG_MEMCG=y&amp;lt;/code&amp;gt; (General setup -&amp;gt; Control Group support -&amp;gt; Memory controller)&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFIG_CGROUP_DEVICE=y&amp;lt;/code&amp;gt; (General setup -&amp;gt; Control Group support -&amp;gt; Device controller)&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFIG_MACVLAN=y&amp;lt;/code&amp;gt; (Device Drivers -&amp;gt; Network device support -&amp;gt; Network core driver support -&amp;gt; MAC-VLAN support)&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFIG_BRIDGE=y&amp;lt;/code&amp;gt; (Networking support -&amp;gt; Networking options -&amp;gt; 802.1d Ethernet Bridging)&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFIG_BINFMT_MISC=y&amp;lt;/code&amp;gt; (Userspace binary formats -&amp;gt; Kernel support for MISC binaries)&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFIG_IA32_EMULATION=y&amp;lt;/code&amp;gt; (x86 only) (Executable file formats -&amp;gt; Emulations -&amp;gt; IA32 Emulation)&lt;br /&gt;
&lt;br /&gt;
For some [[usage scenarios]] there is an ability to track memory changes and produce [[incremental dumps]]. Need to enable the &amp;lt;code&amp;gt;CONFIG_MEM_SOFT_DIRTY=y&amp;lt;/code&amp;gt; (optional) (Processor type and features -&amp;gt; Track memory changes).&lt;br /&gt;
&lt;br /&gt;
Note we also have our [[custom kernel]], which might contain some experimental CRIU related patches.&lt;br /&gt;
&lt;br /&gt;
== Building CRIU From Source ==&lt;br /&gt;
&lt;br /&gt;
=== Native Compilation ===&lt;br /&gt;
Simply run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; in the CRIU source directory.&lt;br /&gt;
&lt;br /&gt;
=== Compilation in Docker container ===&lt;br /&gt;
&lt;br /&gt;
There's a ''docker-build'' target in Makefile which builds CRIU in Ubuntu Docker container. Just run &amp;lt;code&amp;gt;make docker-build&amp;lt;/code&amp;gt; and that's it.&lt;br /&gt;
&lt;br /&gt;
=== Non-standard compilation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px&amp;quot;&amp;gt;&lt;br /&gt;
Building natively, but specifying built dependencies manually&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
 cd deps&lt;br /&gt;
 rsync -a --exclude=.git --exclude=deps .. criu-`uname -m`&lt;br /&gt;
 cd criu-`uname -m`&lt;br /&gt;
 make \&lt;br /&gt;
   USERCFLAGS=&amp;quot;-I`pwd`/../`uname -m`-linux-gnu/include -L`pwd`/../`uname -m`-linux-gnu/lib&amp;quot; \&lt;br /&gt;
   PATH=&amp;quot;`pwd`/../`uname -m`-linux-gnu/bin:$PATH&amp;quot;&lt;br /&gt;
 sudo LD_LIBRARY_PATH=`pwd`/../`uname -m`-linux-gnu/lib ./criu check&lt;br /&gt;
 cd ../..&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width:800px&amp;quot;&amp;gt;&lt;br /&gt;
Cross Compilation for ARM&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
ARMv7&lt;br /&gt;
 cd deps&lt;br /&gt;
 rsync -a --exclude=.git --exclude=deps .. criu-arm&lt;br /&gt;
 cd criu-arm&lt;br /&gt;
 make \&lt;br /&gt;
   ARCH=arm \&lt;br /&gt;
   CROSS_COMPILE=`pwd`/../`uname -m`-linux-gnu/bin/arm-linux-gnueabihf- \&lt;br /&gt;
   USERCFLAGS=&amp;quot;-I`pwd`/../arm-linux-gnueabihf/include -L`pwd`/../arm-linux-gnueabihf/lib&amp;quot; \&lt;br /&gt;
   PATH=&amp;quot;`pwd`/../`uname -m`-linux-gnu/bin:$PATH&amp;quot;&lt;br /&gt;
 cd ../..&lt;br /&gt;
&lt;br /&gt;
ARMv8&lt;br /&gt;
  cd deps&lt;br /&gt;
  rsync -a --exclude=.git --exclude=deps .. criu-aarch64&lt;br /&gt;
  cd criu-aarch64&lt;br /&gt;
  make \&lt;br /&gt;
   ARCH=aarch64 \&lt;br /&gt;
   CROSS_COMPILE=`pwd`/../`uname -m`-linux-gnu/bin/aarch64-linux-gnu- \&lt;br /&gt;
   USERCFLAGS=&amp;quot;-I`pwd`/../aarch64-linux-gnu/include -L`pwd`/../aarch64-linux-gnu/lib&amp;quot; \&lt;br /&gt;
   PATH=&amp;quot;`pwd`/../`uname -m`-linux-gnu/bin:$PATH&amp;quot;&lt;br /&gt;
  cd ../..&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&lt;br /&gt;
CRIU has functionality that is either optional or behaves differently depending on the kernel CRIU is running on. By default build process includes maximum of it, but this behavior can be changed.&lt;br /&gt;
&lt;br /&gt;
''Main article: [[Configuring]]''&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
CRIU works perfectly even when run from the sources directory (with the &amp;quot;./criu&amp;quot; command), but if you want to have in standard paths run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You may need to install the following packages to generate docs in Debian-based OS's to avoid errors from install-man:&lt;br /&gt;
* &amp;lt;code&amp;gt;asciidoc&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;xmlto&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Checking That It Works ==&lt;br /&gt;
&lt;br /&gt;
First thing to do is to run &amp;lt;code&amp;gt;criu check&amp;lt;/code&amp;gt;. At the end it should say &amp;quot;Looks OK&amp;quot;, if it doesn't the messages on the screen explain what functionality is missing. &lt;br /&gt;
&lt;br /&gt;
Some kernel functionality is required in rare cases and may not block the dump (but sometimes may). These features can be checked by adding the &amp;lt;code&amp;gt;--extra&amp;lt;/code&amp;gt; flag.&lt;br /&gt;
&lt;br /&gt;
If you're using our custom kernel, then the &amp;lt;code&amp;gt;--all&amp;lt;/code&amp;gt; option can be used, in this case CRIU would check for ''all'' the kernel features to work.&lt;br /&gt;
&lt;br /&gt;
You can then try running the [[ZDTM Test Suite]] which sits in the &amp;lt;code&amp;gt;tests/zdtm/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
&lt;br /&gt;
* [[Checking the kernel]]&lt;br /&gt;
* [[Usage]]&lt;br /&gt;
* [[Advanced usage]]&lt;br /&gt;
* [[:Category:HOWTO]]&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=3919</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=3919"/>
		<updated>2017-01-24T21:07:13Z</updated>

		<summary type="html">&lt;p&gt;Boucher: &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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker Experimental ==&lt;br /&gt;
&lt;br /&gt;
Checkpoint &amp;amp; Restore is now available in the _experimental_ runtime mode for Docker. Simply start your docker daemon with '''--experimental''' to enable the feature.&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to installing version 1.13 of Docker, you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
 $ ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
There's a top level &amp;lt;code&amp;gt;checkpoint&amp;lt;/code&amp;gt; sub-command in Docker, which lets you create a new checkpoint, and list or delete an existing checkpoint. These checkpoints are stored and managed by Docker, unless you specify a custom storage path.&lt;br /&gt;
&lt;br /&gt;
Here's an example of creating a checkpoint, from a container that simply logs an integer in a loop.&lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper --security-opt seccomp:unconfined busybox  \&lt;br /&gt;
          /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
 $ docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
 $ docker checkpoint create looper checkpoint1&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Unlike creating a checkpoint, restoring from a checkpoint is just a flag provided to the normal container '''start''' call. Here's an example:&lt;br /&gt;
&lt;br /&gt;
 $ docker start --checkpoint checkpoint1 looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. This is done by providing a custom storage path with the &amp;lt;code&amp;gt;--checkpoint-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox \&lt;br /&gt;
          /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint create --checkpoint-dir=/tmp looper2 checkpoint2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-clone --security-opt seccomp:unconfined busybox \&lt;br /&gt;
          /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker start --checkpoint-dir=/tmp --checkpoint=checkpoint2 looper-clone&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-clone&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
Checkpoint&lt;br /&gt;
&lt;br /&gt;
  # docker checkpoint create --help&lt;br /&gt;
  Usage:	docker checkpoint create [OPTIONS] CONTAINER CHECKPOINT&lt;br /&gt;
&lt;br /&gt;
  Create a checkpoint from a running container&lt;br /&gt;
&lt;br /&gt;
  Options:&lt;br /&gt;
      --checkpoint-dir string   Use a custom checkpoint storage directory&lt;br /&gt;
      --help                    Print usage&lt;br /&gt;
      --leave-running           Leave the container running after checkpoint&lt;br /&gt;
&lt;br /&gt;
Restore&lt;br /&gt;
&lt;br /&gt;
   # docker start --help&lt;br /&gt;
   Usage:	docker start [OPTIONS] CONTAINER [CONTAINER...]&lt;br /&gt;
&lt;br /&gt;
  Start one or more stopped containers&lt;br /&gt;
&lt;br /&gt;
  Options:&lt;br /&gt;
  -a, --attach                  Attach STDOUT/STDERR and forward signals&lt;br /&gt;
      --checkpoint string       Restore from this checkpoint&lt;br /&gt;
      --checkpoint-dir string   Use a custom checkpoint storage directory&lt;br /&gt;
      --detach-keys string      Override the key sequence for detaching a container&lt;br /&gt;
      --help                    Print usage&lt;br /&gt;
  -i, --interactive             Attach container's STDIN&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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 Checkpoint Restore ==&lt;br /&gt;
&lt;br /&gt;
{{Note| External C/R was done as proof-of-concept.  Its use is highly discouraged.}}&lt;br /&gt;
&lt;br /&gt;
Although it's not recommended, you can also learn more about using CRIU without integrating with docker: [[Docker_External]].&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=3004</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=3004"/>
		<updated>2016-08-02T12:42:17Z</updated>

		<summary type="html">&lt;p&gt;Boucher: &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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
 $ ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. From this point forward, commands are show using '''docker''' instead of '''docker-dev-1.10''', but if you have not installed this version globally you can use the latter.&lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper --security-opt seccomp:unconfined busybox  \&lt;br /&gt;
          /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
 $ docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
 $ docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
 $ docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox \&lt;br /&gt;
          /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-force --security-opt seccomp:unconfined busybox \&lt;br /&gt;
          /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
 # docker checkpoint --help&lt;br /&gt;
 Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
 &lt;br /&gt;
 Checkpoint one or more running containers&lt;br /&gt;
 &lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory for storing checkpoint image files&lt;br /&gt;
     --leave-running    leave the container running after checkpoint&lt;br /&gt;
     --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
 # docker restore --help&lt;br /&gt;
 Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
 &lt;br /&gt;
 Restore one or more checkpointed containers&lt;br /&gt;
 &lt;br /&gt;
     --force            bypass checks for current container state&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory to restore image files from&lt;br /&gt;
     --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&lt;br /&gt;
&lt;br /&gt;
{{Note| External C/R was done as proof-of-concept.  Its use is highly discouraged.}}&lt;br /&gt;
&lt;br /&gt;
Although it's not recommended, you can also learn more about using CRIU without integrating with docker: [[Docker_External]].&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker_External&amp;diff=3003</id>
		<title>Docker External</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker_External&amp;diff=3003"/>
		<updated>2016-08-02T12:40:29Z</updated>

		<summary type="html">&lt;p&gt;Boucher: Created page with &amp;quot;== External Checkpoint Restore ==  {{Note| External C/R was done as proof-of-concept.  Its use is discouraged and the helper script mentioned below may break in the near futur...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== External Checkpoint Restore ==&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 may break in the near future.}}&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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2997</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2997"/>
		<updated>2016-07-19T01:00:37Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* Restoring into a new container */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
 $ ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. From this point forward, commands are show using '''docker''' instead of '''docker-dev-1.10''', but if you have not installed this version globally you can use the latter.&lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper --security-opt seccomp:unconfined busybox  \&lt;br /&gt;
          /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
 $ docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
 $ docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
 $ docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox \&lt;br /&gt;
          /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-force --security-opt seccomp:unconfined busybox \&lt;br /&gt;
          /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
 # docker checkpoint --help&lt;br /&gt;
 Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
 &lt;br /&gt;
 Checkpoint one or more running containers&lt;br /&gt;
 &lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory for storing checkpoint image files&lt;br /&gt;
     --leave-running    leave the container running after checkpoint&lt;br /&gt;
     --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
 # docker restore --help&lt;br /&gt;
 Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
 &lt;br /&gt;
 Restore one or more checkpointed containers&lt;br /&gt;
 &lt;br /&gt;
     --force            bypass checks for current container state&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory to restore image files from&lt;br /&gt;
     --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2996</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2996"/>
		<updated>2016-07-19T00:54:43Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* checkpoint */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
 $ ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. From this point forward, commands are show using '''docker''' instead of '''docker-dev-1.10''', but if you have not installed this version globally you can use the latter.&lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper --security-opt seccomp:unconfined busybox  \&lt;br /&gt;
          /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
 $ docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
 $ docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
 $ docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
 # docker checkpoint --help&lt;br /&gt;
 Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
 &lt;br /&gt;
 Checkpoint one or more running containers&lt;br /&gt;
 &lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory for storing checkpoint image files&lt;br /&gt;
     --leave-running    leave the container running after checkpoint&lt;br /&gt;
     --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
 # docker restore --help&lt;br /&gt;
 Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
 &lt;br /&gt;
 Restore one or more checkpointed containers&lt;br /&gt;
 &lt;br /&gt;
     --force            bypass checks for current container state&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory to restore image files from&lt;br /&gt;
     --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2995</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2995"/>
		<updated>2016-07-19T00:52:51Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* checkpoint */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
 $ ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper --security-opt seccomp:unconfined busybox  \&lt;br /&gt;
                       /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
 $ docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
 $ docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
 $ docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
 # docker checkpoint --help&lt;br /&gt;
 Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
 &lt;br /&gt;
 Checkpoint one or more running containers&lt;br /&gt;
 &lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory for storing checkpoint image files&lt;br /&gt;
     --leave-running    leave the container running after checkpoint&lt;br /&gt;
     --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
 # docker restore --help&lt;br /&gt;
 Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
 &lt;br /&gt;
 Restore one or more checkpointed containers&lt;br /&gt;
 &lt;br /&gt;
     --force            bypass checks for current container state&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory to restore image files from&lt;br /&gt;
     --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2994</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2994"/>
		<updated>2016-07-18T18:56:04Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* usage */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
 $ ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
 $ docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
 $ docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
 $ docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
 # docker checkpoint --help&lt;br /&gt;
 Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
 &lt;br /&gt;
 Checkpoint one or more running containers&lt;br /&gt;
 &lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory for storing checkpoint image files&lt;br /&gt;
     --leave-running    leave the container running after checkpoint&lt;br /&gt;
     --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
 # docker restore --help&lt;br /&gt;
 Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
 &lt;br /&gt;
 Restore one or more checkpointed containers&lt;br /&gt;
 &lt;br /&gt;
     --force            bypass checks for current container state&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory to restore image files from&lt;br /&gt;
     --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2993</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2993"/>
		<updated>2016-07-18T18:55:29Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* Docker 1.10 */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
 $ docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
 $ ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
 $ docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
 $ docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
 $ docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
 # docker checkpoint --help&lt;br /&gt;
 Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
 Checkpoint one or more running containers&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory for storing checkpoint image files&lt;br /&gt;
     --leave-running    leave the container running after checkpoint&lt;br /&gt;
     --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
 # docker restore --help&lt;br /&gt;
 Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
 Restore one or more checkpointed containers&lt;br /&gt;
     --force            bypass checks for current container state&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory to restore image files from&lt;br /&gt;
     --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2992</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2992"/>
		<updated>2016-07-18T18:55:07Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* Docker 1.10 */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
 docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
 docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
 # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
 $ docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
 $ docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
 $ docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
 # docker checkpoint --help&lt;br /&gt;
 Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
 Checkpoint one or more running containers&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory for storing checkpoint image files&lt;br /&gt;
     --leave-running    leave the container running after checkpoint&lt;br /&gt;
     --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
 # docker restore --help&lt;br /&gt;
 Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
 Restore one or more checkpointed containers&lt;br /&gt;
     --force            bypass checks for current container state&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory to restore image files from&lt;br /&gt;
     --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2991</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2991"/>
		<updated>2016-07-18T18:54:26Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* usage */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
    # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
    docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
    docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
    docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
 # docker checkpoint --help&lt;br /&gt;
 Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
 Checkpoint one or more running containers&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory for storing checkpoint image files&lt;br /&gt;
     --leave-running    leave the container running after checkpoint&lt;br /&gt;
     --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
 # docker restore --help&lt;br /&gt;
 Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
 Restore one or more checkpointed containers&lt;br /&gt;
     --force            bypass checks for current container state&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory to restore image files from&lt;br /&gt;
     --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2990</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2990"/>
		<updated>2016-07-18T18:53:38Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* usage */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
    # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
    docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
    docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
    docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
 # docker checkpoint --help&lt;br /&gt;
 Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
 Checkpoint one or more running containers&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory for storing checkpoint image files&lt;br /&gt;
     --leave-running    leave the container running after checkpoint&lt;br /&gt;
     --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 # docker restore --help&lt;br /&gt;
 Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
 Restore one or more checkpointed containers&lt;br /&gt;
     --force            bypass checks for current container state&lt;br /&gt;
     --help             Print usage&lt;br /&gt;
     --image-dir        directory to restore image files from&lt;br /&gt;
     --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2989</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2989"/>
		<updated>2016-07-18T18:53:12Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* Restoring into a new container */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
    # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
    docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
    docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
    docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
 $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
 $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
 &lt;br /&gt;
 $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
 &lt;br /&gt;
 $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
    # docker checkpoint --help&lt;br /&gt;
    Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
    Checkpoint one or more running containers&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory for storing checkpoint image files&lt;br /&gt;
        --leave-running    leave the container running after checkpoint&lt;br /&gt;
        --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    # docker restore --help&lt;br /&gt;
    Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
    Restore one or more checkpointed containers&lt;br /&gt;
        --force            bypass checks for current container state&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory to restore image files from&lt;br /&gt;
        --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2988</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2988"/>
		<updated>2016-07-18T18:52:41Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* Restoring into a new container */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
    # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
    docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
    docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
    docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
  $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
  &lt;br /&gt;
  # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
  $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
  &lt;br /&gt;
  $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
  &lt;br /&gt;
  $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
    # docker checkpoint --help&lt;br /&gt;
    Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
    Checkpoint one or more running containers&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory for storing checkpoint image files&lt;br /&gt;
        --leave-running    leave the container running after checkpoint&lt;br /&gt;
        --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    # docker restore --help&lt;br /&gt;
    Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
    Restore one or more checkpointed containers&lt;br /&gt;
        --force            bypass checks for current container state&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory to restore image files from&lt;br /&gt;
        --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2987</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2987"/>
		<updated>2016-07-18T18:52:21Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* Restoring into a new container */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
    # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
    docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
    docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
    docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
    $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
    &lt;br /&gt;
    # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
    $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
    &lt;br /&gt;
    $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
    &lt;br /&gt;
    $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end.&lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
    # docker checkpoint --help&lt;br /&gt;
    Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
    Checkpoint one or more running containers&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory for storing checkpoint image files&lt;br /&gt;
        --leave-running    leave the container running after checkpoint&lt;br /&gt;
        --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    # docker restore --help&lt;br /&gt;
    Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
    Restore one or more checkpointed containers&lt;br /&gt;
        --force            bypass checks for current container state&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory to restore image files from&lt;br /&gt;
        --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the '''docker-checkpoint-restore''' branch of [[User:Boucher|Boucher]]'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely '''runc''' and '''containerd'''. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2984</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2984"/>
		<updated>2016-07-18T18:10:41Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* Docker 1.10 */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The '''graph''' and '''host''' options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need '''CRIU''' installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are '''libprotobuf-c''' and '''libnl-3'''. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
    # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
    docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
    docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like '''checkpoint''', '''restore''' is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
    docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a '''new''' container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
    $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
    # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
    $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
&lt;br /&gt;
    $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
    $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end. &lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
    # docker checkpoint --help&lt;br /&gt;
    Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
    Checkpoint one or more running containers&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory for storing checkpoint image files&lt;br /&gt;
        --leave-running    leave the container running after checkpoint&lt;br /&gt;
        --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    # docker restore --help&lt;br /&gt;
    Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
    Restore one or more checkpointed containers&lt;br /&gt;
        --force            bypass checks for current container state&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory to restore image files from&lt;br /&gt;
        --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the *docker-checkpoint-restore* branch of *@boucher*'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely *runc* and *containerd*. The final step in the process is to integrate with Docker itself. You can track the status of that process in [https://github.com/docker/docker/pull/22049 this pull request].&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2982</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2982"/>
		<updated>2016-07-18T18:07:49Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* usage */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The *graph* and *host* options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need *CRIU* installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are *libprotobuf-c* and *libnl-3*. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
    # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
    docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
    docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like *checkpoint*, *restore* is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
    docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a *new* container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
    $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
    # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
    $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
&lt;br /&gt;
    $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
    $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end. &lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
    # docker checkpoint --help&lt;br /&gt;
    Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
    Checkpoint one or more running containers&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory for storing checkpoint image files&lt;br /&gt;
        --leave-running    leave the container running after checkpoint&lt;br /&gt;
        --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    # docker restore --help&lt;br /&gt;
    Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
    Restore one or more checkpointed containers&lt;br /&gt;
        --force            bypass checks for current container state&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory to restore image files from&lt;br /&gt;
        --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the *docker-checkpoint-restore* branch of *@boucher*'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely *runc* and *containerd*. The final step in the process is to integrate with Docker itself. You can track the status of that process in [this pull request](https://github.com/docker/docker/pull/22049).&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2981</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2981"/>
		<updated>2016-07-18T18:07:17Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* Docker 1.10 */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental this pre-compiled version of Docker]. It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The *graph* and *host* options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need *CRIU* installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are *libprotobuf-c* and *libnl-3*. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
    # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
    docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
    docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like *checkpoint*, *restore* is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
    docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a *new* container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
    $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
    # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
    $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
&lt;br /&gt;
    $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
    $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end. &lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
    # docker checkpoint --help&lt;br /&gt;
&lt;br /&gt;
    Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
&lt;br /&gt;
    Checkpoint one or more running containers&lt;br /&gt;
&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory for storing checkpoint image files&lt;br /&gt;
        --leave-running    leave the container running after checkpoint&lt;br /&gt;
        --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    # docker restore --help&lt;br /&gt;
&lt;br /&gt;
    Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
&lt;br /&gt;
    Restore one or more checkpointed containers&lt;br /&gt;
&lt;br /&gt;
        --force            bypass checks for current container state&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory to restore image files from&lt;br /&gt;
        --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the *docker-checkpoint-restore* branch of *@boucher*'s fork of Docker, [https://github.com/boucher/docker/tree/docker-checkpoint-restore available here]. Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely *runc* and *containerd*. The final step in the process is to integrate with Docker itself. You can track the status of that process in [this pull request](https://github.com/docker/docker/pull/22049).&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2979</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2979"/>
		<updated>2016-07-18T18:05:27Z</updated>

		<summary type="html">&lt;p&gt;Boucher: /* Docker 1.10 */&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [this pre-compiled version of Docker](https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental). It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;/code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The *graph* and *host* options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need *CRIU* installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are *libprotobuf-c* and *libnl-3*. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
    # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
    docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
    docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like *checkpoint*, *restore* is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
    docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a *new* container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
    $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
    # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
    $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
&lt;br /&gt;
    $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
    $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end. &lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
    # docker checkpoint --help&lt;br /&gt;
&lt;br /&gt;
    Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
&lt;br /&gt;
    Checkpoint one or more running containers&lt;br /&gt;
&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory for storing checkpoint image files&lt;br /&gt;
        --leave-running    leave the container running after checkpoint&lt;br /&gt;
        --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    # docker restore --help&lt;br /&gt;
&lt;br /&gt;
    Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
&lt;br /&gt;
    Restore one or more checkpointed containers&lt;br /&gt;
&lt;br /&gt;
        --force            bypass checks for current container state&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory to restore image files from&lt;br /&gt;
        --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the *docker-checkpoint-restore* branch of *@boucher*'s fork of Docker, [available here](https://github.com/boucher/docker/tree/docker-checkpoint-restore). Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely *runc* and *containerd*. The final step in the process is to integrate with Docker itself. You can track the status of that process in [this pull request](https://github.com/docker/docker/pull/22049).&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2978</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2978"/>
		<updated>2016-07-18T18:05:12Z</updated>

		<summary type="html">&lt;p&gt;Boucher: Formatting issues&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [this pre-compiled version of Docker](https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental). It's based on Docker 1.10, and built with the &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL&amp;lt;/code&amp;gt; build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the &amp;lt;code&amp;gt;docker-1.10.0-dev&amp;lt;code&amp;gt; binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock&lt;br /&gt;
&lt;br /&gt;
The *graph* and *host* options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
    docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need *CRIU* installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are *libprotobuf-c* and *libnl-3*. Here's an output of &amp;lt;code&amp;gt;ldd&amp;lt;/code&amp;gt; on my system:&lt;br /&gt;
&lt;br /&gt;
    # ldd `which criu`&lt;br /&gt;
    	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
    	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
    	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
    	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
    	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
    	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
    	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
    	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
    docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
    docker logs looper&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint looper&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like *checkpoint*, *restore* is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
    docker restore looper&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a *new* container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the &amp;lt;code&amp;gt;--force&amp;lt;/code&amp;gt; option, in conjunction with the &amp;lt;code&amp;gt;--image-dir&amp;lt;/code&amp;gt; option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
    $ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
    # wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
    $ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
&lt;br /&gt;
    $ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
    $ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from &amp;lt;code&amp;gt;looper-force&amp;lt;/code&amp;gt; and see that they start from wherever the logs of &amp;lt;code&amp;gt;looper&amp;lt;/code&amp;gt; end. &lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
    # docker checkpoint --help&lt;br /&gt;
&lt;br /&gt;
    Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
&lt;br /&gt;
    Checkpoint one or more running containers&lt;br /&gt;
&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory for storing checkpoint image files&lt;br /&gt;
        --leave-running    leave the container running after checkpoint&lt;br /&gt;
        --work-dir         directory for storing log file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    # docker restore --help&lt;br /&gt;
&lt;br /&gt;
    Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
&lt;br /&gt;
    Restore one or more checkpointed containers&lt;br /&gt;
&lt;br /&gt;
        --force            bypass checks for current container state&lt;br /&gt;
        --help             Print usage&lt;br /&gt;
        --image-dir        directory to restore image files from&lt;br /&gt;
        --work-dir         directory for restore log&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the *docker-checkpoint-restore* branch of *@boucher*'s fork of Docker, [available here](https://github.com/boucher/docker/tree/docker-checkpoint-restore). Make sure to build with the env &amp;lt;code&amp;gt;DOCKER_EXPERIMENTAL=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. &amp;lt;code&amp;gt;docker checkpoint&amp;lt;/code&amp;gt; is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the &amp;lt;code&amp;gt;docker checkpoint create&amp;lt;/code&amp;gt; command, which takes &amp;lt;code&amp;gt;container_id&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;checkpoint_id&amp;lt;/code&amp;gt; as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
    docker checkpoint create my_container my_first_checkpoint&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. Although typically you may create and start a container in a single step using &amp;lt;code&amp;gt;docker run&amp;lt;/code&amp;gt;, under the hood this is actually two steps: &amp;lt;code&amp;gt;docker create&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;docker start&amp;lt;/code&amp;gt;. You can also call &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
    docker start --checkpoint my_first_checkpoint my_container&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely *runc* and *containerd*. The final step in the process is to integrate with Docker itself. You can track the status of that process in [this pull request](https://github.com/docker/docker/pull/22049).&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
	<entry>
		<id>https://criu.org/index.php?title=Docker&amp;diff=2977</id>
		<title>Docker</title>
		<link rel="alternate" type="text/html" href="https://criu.org/index.php?title=Docker&amp;diff=2977"/>
		<updated>2016-07-18T18:00:34Z</updated>

		<summary type="html">&lt;p&gt;Boucher: Update documentation on using CRIU with Docker&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;
Docker wants to manage the full lifecycle of processes running inside one if its containers, which makes it important for CRIU and Docker to work closely together when trying to checkpoint and restore a container. This is being achieved by adding the ability to checkpoint and restore directly into Docker itself, powered under the hood by CRIU. This integration is a work in progress, and its status will be outlined below. &lt;br /&gt;
&lt;br /&gt;
== Docker 1.10 ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to try CRIU and Docker together is to install [this pre-compiled version of Docker](https://github.com/boucher/docker/releases/tag/v1.10_2-16-16-experimental). It's based on Docker 1.10, and built with the `DOCKER_EXPERIMENTAL` build tag. &lt;br /&gt;
&lt;br /&gt;
To install, download the `docker-1.10.0-dev` binary to your system. You'll need to start a docker daemon from this binary, and then you can use the same binary to communicate with that daemon. To start a docker daemon, run a command something like this:&lt;br /&gt;
&lt;br /&gt;
`docker-1.10.0-dev daemon -D --graph=/var/lib/docker-dev --host unix:///var/run/docker-dev.sock`&lt;br /&gt;
&lt;br /&gt;
The *graph* and *host* options will prevent colliding with an existing installation of Docker, but you can replace your existing docker if desired. In another shell, you can then connect to that daemon:&lt;br /&gt;
&lt;br /&gt;
`docker-1.10.0-dev --host unix:///var/run/docker-dev.sock run -d busybox top`&lt;br /&gt;
&lt;br /&gt;
=== Dependencies ===&lt;br /&gt;
&lt;br /&gt;
In addition to downloading the binary above (or compiling one yourself), you need *CRIU* installed on your system, with at least version 2.0. You also need some shared libraries on your system. The most likely things you'll need to install are *libprotobuf-c* and *libnl-3*. Here's an output of `ldd` on my system:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
# ldd `which criu`&lt;br /&gt;
	linux-vdso.so.1 =&amp;gt;  (0x00007ffc09fda000)&lt;br /&gt;
	libpthread.so.0 =&amp;gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd28b2c7000)&lt;br /&gt;
	libprotobuf-c.so.0 =&amp;gt; /usr/lib/x86_64-linux-gnu/libprotobuf-c.so.0 (0x00007fd28b0b7000)&lt;br /&gt;
	libdl.so.2 =&amp;gt; /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd28aeb2000)&lt;br /&gt;
	libnl-3.so.200 =&amp;gt; /lib/x86_64-linux-gnu/libnl-3.so.200 (0x00007fd28ac98000)&lt;br /&gt;
	libc.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd28a8d3000)&lt;br /&gt;
	/lib64/ld-linux-x86-64.so.2 (0x000056386bb38000)&lt;br /&gt;
	libm.so.6 =&amp;gt; /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd28a5cc000)&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
=== checkpoint === &lt;br /&gt;
&lt;br /&gt;
Creating a checkpoint is a top level Docker command with this new version of Docker. Here's an example that simply logs an integer in a loop. &lt;br /&gt;
&lt;br /&gt;
First, we create container:&lt;br /&gt;
&lt;br /&gt;
`docker run -d --name looper --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'`&lt;br /&gt;
&lt;br /&gt;
You can verify the container is running by printings its logs:&lt;br /&gt;
&lt;br /&gt;
`docker logs looper`&lt;br /&gt;
&lt;br /&gt;
If you do this a few times you'll notice the integer increasing. Now, we checkpoint the container:&lt;br /&gt;
&lt;br /&gt;
`docker checkpoint looper`&lt;br /&gt;
&lt;br /&gt;
You should see that the process is no longer running, and if you print the logs a few times no new logs will be printed.&lt;br /&gt;
&lt;br /&gt;
=== restore ===&lt;br /&gt;
&lt;br /&gt;
Like `checkpoint`, `restore` is a top level command in this version of Docker. Continuing our example, let's restore the same container:&lt;br /&gt;
&lt;br /&gt;
`docker restore looper`&lt;br /&gt;
&lt;br /&gt;
If we then print the logs, you should see they start from where we left off and continue to increase. &lt;br /&gt;
&lt;br /&gt;
==== Restoring into a *new* container ====&lt;br /&gt;
&lt;br /&gt;
Beyond the straightforward case of checkpointing and restoring the same container, it's also possible to checkpoint one container, and then restore the checkpoint into a completely different container. Right now that is done with the `--force` option, in conjunction with the `--image-dir` option. Here's a slightly revised example from before:&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
$ docker run -d --name looper2 --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
# wait a few seconds to give the container an opportunity to print a few lines, then&lt;br /&gt;
$ docker checkpoint --image-dir=/tmp/checkpoint1 looper2&lt;br /&gt;
&lt;br /&gt;
$ docker create --name looper-force --security-opt seccomp:unconfined busybox /bin/sh -c 'i=0; while true; do echo $i; i=$(expr $i + 1); sleep 1; done'&lt;br /&gt;
&lt;br /&gt;
$ docker restore --force=true --image-dir=/tmp/checkpoint1 looper-force&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
You should be able to print the logs from `looper-force` and see that they start from wherever the logs of `looper` end. &lt;br /&gt;
&lt;br /&gt;
=== usage ===&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
# docker checkpoint --help&lt;br /&gt;
&lt;br /&gt;
Usage:	docker checkpoint [OPTIONS] CONTAINER&lt;br /&gt;
&lt;br /&gt;
Checkpoint one or more running containers&lt;br /&gt;
&lt;br /&gt;
  --help             Print usage&lt;br /&gt;
  --image-dir        directory for storing checkpoint image files&lt;br /&gt;
  --leave-running    leave the container running after checkpoint&lt;br /&gt;
  --work-dir         directory for storing log file&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
```&lt;br /&gt;
# docker restore --help&lt;br /&gt;
&lt;br /&gt;
Usage:	docker restore [OPTIONS] CONTAINER&lt;br /&gt;
&lt;br /&gt;
Restore one or more checkpointed containers&lt;br /&gt;
&lt;br /&gt;
  --force            bypass checks for current container state&lt;br /&gt;
  --help             Print usage&lt;br /&gt;
  --image-dir        directory to restore image files from&lt;br /&gt;
  --work-dir         directory for restore log&lt;br /&gt;
```&lt;br /&gt;
&lt;br /&gt;
== Docker 1.12 ==&lt;br /&gt;
&lt;br /&gt;
More detailed instructions on running checkpoint/restore with Docker in version 1.12 will be coming in the future, but in the meantime, you must build the version of Docker available in the `docker-checkpoint-restore` branch of `@boucher`'s fork of Docker, [available here](https://github.com/boucher/docker/tree/docker-checkpoint-restore). Make sure to build with the env `DOCKER_EXPERIMENTAL=1`.&lt;br /&gt;
&lt;br /&gt;
The command line interface has changed from the 1.10 version. `docker checkpoint` is now an umbrella command for a few checkpoint operations. To create a checkpoint, use the `docker checkpoint create` command, which takes `container_id` and `checkpoint_id` as non-optional arguments. Example:&lt;br /&gt;
&lt;br /&gt;
`docker checkpoint create my_container my_first_checkpoint`&lt;br /&gt;
&lt;br /&gt;
Restoring a container is now performed just as an option to `docker start`. Although typically you may create and start a container in a single step using `docker run`, under the hood this is actually two steps: `docker create` followed by `docker start`. You can also call `start` on a container that was previously running and has since been stopped or killed. That looks something like this:&lt;br /&gt;
&lt;br /&gt;
`docker start --checkpoint my_first_checkpoint my_container`&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Integration Status == &lt;br /&gt;
&lt;br /&gt;
CRIU has already been integrated into the lower level components that power Docker, namely *runc* and *containerd*. The final step in the process is to integrate with Docker itself. You can track the status of that process in [this pull request](https://github.com/docker/docker/pull/22049).&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
The latest versions of the Docker integration require at least version 2.0 of CRIU in order to work correctly. Additionally, depending on the storage driver being used by Docker, and other factors, there may be other compatibility issues that will attempt to be listed here.&lt;br /&gt;
&lt;br /&gt;
=== TTY ===&lt;br /&gt;
&lt;br /&gt;
Checkpointing an interactive container is currently not supported. &lt;br /&gt;
&lt;br /&gt;
=== Seccomp ===&lt;br /&gt;
&lt;br /&gt;
You'll notice that all of the above examples disable Docker's default seccomp support. In order to use seccomp, you'll need a newer version of the Kernel. **Update Needed with Exact Version**&lt;br /&gt;
&lt;br /&gt;
=== OverlayFS ===&lt;br /&gt;
&lt;br /&gt;
 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. The following small kernel patches fix the mount id and symlink target path issue:&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 ===&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;
&lt;br /&gt;
&lt;br /&gt;
== External Checkpoint Restore ==&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;
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;
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;
&lt;br /&gt;
[[Category:HOWTO]]&lt;/div&gt;</summary>
		<author><name>Boucher</name></author>
	</entry>
</feed>