# Docker: Checkpoint and Restore
Before I do a deeper dive into Firecracker, I wanted to run a quick experiment and check whether it’s possible to take a snapshot of a Docker container and restore it at some point. I’m far from being the first to think about this, and
there’s a fantastic team working on CRIU: https://criu.org/. CRIU is a project that implements checkpoint/restore functionality for Linux. As the description says, it doesn’t work on Windows or Mac, so here I go again, dusting off my Thinkpad X220.
It’s been a while since I did something on Linux and Ubuntu, so I discovered there’s a new package manager called “Snap”. I tried it with Docker, and something messed up permissions on `docker.sock` file, i.e. whenever I start a Docker service, a sock file is always created under `root:root`. Perhaps, I’ll try snap next time, but for now I’m back to apt.
## Install Docker
Install Docker by following instructions from
https://docs.docker.com/engine/install/ubuntu/:
1. Add Docker’s GPG key:
```bash
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```
2. Verify that you now have the key with the fingerprint `9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88`, by searching for the last 8 characters of the fingerprint:
```bash
$ sudo apt-key fingerprint 0EBFCD88
pub rsa4096 2017-02-22 [SCEA]
9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
uid [ unknown] Docker Release (CEdeb) <
[email protected]>
sub rsa4096 2017-02-22 [S]
```
3. Setup the stable repository:
```bash
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
```
4. Install Docker:
```bash
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
```
5. Add your user to docker group:
```bash
sudo usermod -aG docker ${USER}
```
6. Logout/Login to your session.
7. Validate that Docker runs:
```bash
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
```
## Install CRIU
Follow instruction from https://criu.org/Docker:
1. Install CRIU:
```bash
$ sudo add-apt-repository ppa:criu/ppa
$ sudo apt install criu
```
2. Enable experimental features in Docker:
```bash
sudo echo "{\"experimental\": true}" >> /etc/docker/daemon.json
sudo systemctl restart docker
```
3. Run a test container that increments a timer every second:
```bash
$ 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'
```
4. Verify that logs are showing up:
```bash
$ docker logs looper
0
1
2
3
```
5. Create a checkpoint, which will stop the container:
```bash
$ docker checkpoint create looper checkpoint1
checkpoint1
```
6. Restore the container:
```bash
$ docker start --checkpoint checkpoint1 looper
```
7. Check logs one more time:
```bash
$ docker logs looper
0
1
2
3
0
1
2
```
8. Something didn’t work well on the last step, as you may notice. Test container is starting the counter from 0 rather than from the checkpoint. Not sure why this is happening. I’m running Docker 20.10.3 and CRIU 3.15 on Linux 5.8.15, which satisfies CRIU requirements.
At the same time, if I try something different like run alpine container, create a folder and snapshot, it works like expected:
```bash
$ # Terminal 1
$ docker run -it alpine sh
/ # mkdir ~/hello
```
```bash
$ # Terminal 2
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a82ccad8fdfa alpine "sh" 2 minutes ago Up 1 second clever_kapitsa
$ docker checkpoint create a82ccad8fdfa checkpoint1
checkpoint1
$ docker ps
$ docker start --checkpoint checkpoint1 a82ccad8fdfa
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a82ccad8fdfa alpine "sh" 2 minutes ago Up 1 second clever_kapitsa
$ docker exec -it a82ccad8fdfa sh
/ # cd
~ # ls
hello
```
I think CRIU will be useful at some point with Firecracker as well. Resource-wise in some cases it doesn’t make sense to run user containers at all times if no one is using them.