Running container applications between bootable images
In this chapter, we want to test a docker application and make sure that all the settings and downloads done in one bootable filetree are going to be saved into writable folders and be available in the other image, in other words after reboot from the other image, everything is available exactly the same way.
We are going to do this twice: first, to verify an existing bootable image installed in parallel and then create a new one.
11.1 Downloading a docker container appliance
Photon OS comes with docker package installed and configured, but we expect that the docker daemon is inactive (not started). Configuration file /usr/lib/systemd/system/docker.service is read-only (remember /usr is bound as read-only).
root@sample-host-def [ ~ ]# systemctl status docker
* docker.service - Docker Daemon
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled)
Active: inactive (dead)
root@sample-host-def [ ~ ]# cat /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Daemon
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/bin/docker -d -s overlay
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=always
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
[Install]
WantedBy=multi-user.target
Now let's enable docker daemon to start at boot time - this will create a symbolic link into writable folder /etc/systemd/system/multi-user.target.wants to its systemd configuration, as with all other systemd controlled services.
root@sample-host-def [ ~ ]# systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
root@sample-host-def [ ~ ]# ls -l /etc/systemd/system/multi-user.target.wants
total 0
lrwxrwxrwx 1 root root 38 Sep 6 08:38 docker.service -> /usr/lib/systemd/system/docker.service
lrwxrwxrwx 1 root root 47 Aug 28 20:21 iptables.service -> ../../../../lib/systemd/system/iptables.service
lrwxrwxrwx 1 root root 47 Aug 28 20:21 remote-fs.target -> ../../../../lib/systemd/system/remote-fs.target
lrwxrwxrwx 1 root root 50 Aug 28 20:21 sshd-keygen.service -> ../../../../lib/systemd/system/sshd-keygen.service
lrwxrwxrwx 1 root root 43 Aug 28 20:21 sshd.service -> ../../../../lib/systemd/system/sshd.service
lrwxrwxrwx 1 root root 55 Aug 28 20:21 systemd-networkd.service -> ../../../../lib/systemd/system/systemd-networkd.service
lrwxrwxrwx 1 root root 55 Aug 28 20:21 systemd-resolved.service -> ../../../../lib/systemd/system/systemd-resolved.service
To verify that the symbolic link points to a file in a read-only directory, try to make a change in this file using vim and save. you'll get an error: "/usr/lib/systemd/system/docker.service" E166: Can't open linked file for writing".
Finally, let's start the daemon, check again that is active.
root@sample-host-def [ ~ ]# systemctl start docker
root@sample-host-def [ ~ ]# systemctl status -l docker
* docker.service - Docker Daemon
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
Active: active (running) since Sun 2015-09-06 08:56:30 UTC; 42s ago
Main PID: 349 (docker)
CGroup: /system.slice/docker.service
`-349 /bin/docker -d -s overlay
Sep 06 08:56:30 sample-host-def docker[349]: Warning: '-d' is deprecated, it will be removed soon. See usage.
Sep 06 08:56:30 sample-host-def docker[349]: time="2015-09-06T08:56:30Z" level=warning msg="please use 'docker daemon' instead."
Sep 06 08:56:30 sample-host-def docker[349]: time="2015-09-06T08:56:30.617969465Z" level=info msg="Option DefaultDriver: bridge"
Sep 06 08:56:30 sample-host-def docker[349]: time="2015-09-06T08:56:30.618264109Z" level=info msg="Option DefaultNetwork: bridge"
Sep 06 08:56:30 sample-host-def docker[349]: time="2015-09-06T08:56:30.632397533Z" level=info msg="Listening for HTTP on unix (/var/run/docker.sock)"
Sep 06 08:56:30 sample-host-def docker[349]: time="2015-09-06T08:56:30.637516253Z" level=info msg="Firewalld running: false"
Sep 06 08:56:30 sample-host-def docker[349]: time="2015-09-06T08:56:30.786748372Z" level=info msg="Loading containers: start."
Sep 06 08:56:30 sample-host-def docker[349]: time="2015-09-06T08:56:30.787252697Z" level=info msg="Loading containers: done."
Sep 06 08:56:30 sample-host-def docker[349]: time="2015-09-06T08:56:30.787410576Z" level=info msg="Daemon has completed initialization"
Sep 06 08:56:30 sample-host-def docker[349]: time="2015-09-06T08:56:30.787610148Z" level=info msg="Docker daemon" commit=d12ea79 execdriver=native-0.2 graphdriver=overlay version=1.8.1
We'll ask docker to run Ubuntu Linux in a container. Since it's not present locally, it's going to be downloaded first from the official docker repository https://hub.docker.com/_/ubuntu/.
root@sample-host-def [ ~ ]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
root@sample-host-def [ ~ ]# docker run -it ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
d3a1f33e8a5a: Downloading [=========================================> ] 54.55 MB/65.79 MB
c22013c84729: Download complete
d74508fb6632: Download complete
91e54dfb1179: Download complete
When downloading is complete, it comes to Ubuntu root prompt with assigned host name d07ebca78051, that is actually the Container ID. Let's verify it's indeed the expected OS.
root@sample-host-def [ ~ ]# docker run -it ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
d3a1f33e8a5a: Pull complete
c22013c84729: Pull complete
d74508fb6632: Pull complete
91e54dfb1179: Already exists
library/ubuntu:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:fde8a8814702c18bb1f39b3bd91a2f82a8e428b1b4e39d1963c5d14418da8fba
Status: Downloaded newer image for ubuntu:latest
root@d07ebca78051:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="14.04.3 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.3 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
root@d07ebca78051:/#
Now let's write a file into Ubuntu home directory
echo "Ubuntu file" > /home/myfile
root@d07ebca78051:/home# cat /home/myfile
Ubuntu file
We'll exit back to the Photon prompt and if it's stopped, we will re-start it.
root@d07ebca78051:/# exit
exit
root@sample-host-def [ ~ ]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d07ebca78051 ubuntu "/bin/bash" 3 minutes ago Exited (0) 13 seconds ago kickass_hodgkin
root@photon-host-cus1 [ ~ ]# docker start d07ebca78051
d07ebca78051
root@photon-host-cus1 [ ~ ]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d07ebca78051 ubuntu "/bin/bash" 16 minutes ago Up 5 seconds kickass_hodgkin
11.2 Rebooting into an existing image
Now let's reboot the machine and select the other image. First, we'll verify that the docker daemon is automaically started.
root@photon-host-cus1 [ ~ ]# systemctl status docker
* docker.service - Docker Daemon
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
Active: active (running) since Sun 2015-09-06 11:19:05 UTC; 2min 9s ago
Main PID: 292 (docker)
CGroup: /system.slice/docker.service
`-292 /bin/docker -d -s overlay
...
Next, is the Ubuntu OS container still there?
root@photon-host-cus1 [ ~ ]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57dcac5d0490 ubuntu "/bin/bash" 25 minutes ago Exited (137) 5 minutes ago sad_banach
It is, so let's start it, attach and verify that our file is persisted, then add another line to it and save, exit.
root@photon-host-cus1 [ ~ ]# docker start -i 57dcac5d0490
root@57dcac5d0490:/# cat /home/myfile
Ubuntu file
root@57dcac5d0490:/# echo "booted into existing image" >> /home/myfile
root@57dcac5d0490:/# exit
11.3 Reboot into a newly created image
Let's upgrade and replace the .0 image by a .3 build that contains git and also perl_YAML (because it is a dependency of git).
root@photon-host-cus1 [ ~ ]# rpm-ostree status
TIMESTAMP (UTC) VERSION ID OSNAME REFSPEC
* 2015-09-04 00:36:37 1.0_tp2_minimal.2 092e21d292 photon photon:photon/tp2/x86_64/minimal
2015-08-20 22:27:43 1.0_tp2_minimal 2940e10c4d photon photon:photon/tp2/x86_64/minimal
root@photon-host-cus1 [ ~ ]# rpm-ostree upgrade
Updating from: photon:photon/tp2/x86_64/minimal
43 metadata, 209 content objects fetched; 19992 KiB transferred in 0 seconds
Copying /etc changes: 5 modified, 0 removed, 19 added
Transaction complete; bootconfig swap: yes deployment count change: 0
Freed objects: 16.2 MB
Added:
git-2.1.2-1.ph1tp2.x86_64
perl-YAML-1.14-1.ph1tp2.noarch
Upgrade prepared for next boot; run "systemctl reboot" to start a reboot
root@photon-host-cus1 [ ~ ]# rpm-ostree status
TIMESTAMP (UTC) VERSION ID OSNAME REFSPEC
2015-09-06 18:12:08 1.0_tp2_minimal.3 d16aebd803 photon photon:photon/tp2/x86_64/minimal
* 2015-09-04 00:36:37 1.0_tp2_minimal.2 092e21d292 photon photon:photon/tp2/x86_64/minimal
After reboot from 1.0_tp2_minimal.3 build, let's check that the 3-way /etc merge succeeded as expected. The docker.service slink is still there, and docker demon restarted at boot.
root@photon-host-cus1 [ ~ ]# ls -l /etc/systemd/system/multi-user.target.wants/docker.service
lrwxrwxrwx 1 root root 38 Sep 6 12:50 /etc/systemd/system/multi-user.target.wants/docker.service -> /usr/lib/systemd/system/docker.service
root@photon-host-cus1 [ ~ ]# systemctl status docker
* docker.service - Docker Daemon
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
Active: active (running) since Sun 2015-09-06 12:56:33 UTC; 1min 27s ago
Main PID: 292 (docker)
CGroup: /system.slice/docker.service
`-292 /bin/docker -d -s overlay
...
Let's revisit the Ubuntu container. Is the container still there? is myfile persisted?
root@photon-host-cus1 [ ~ ]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
57dcac5d0490 ubuntu "/bin/bash" 2 hours ago Exited (0) About an hour ago sad_banach
root@photon-host-cus1 [ ~ ]# docker start 57dcac5d0490
root@57dcac5d0490:/# cat /home/myfile
Ubuntu file
booted into existing image
root@57dcac5d0490:/# echo "booted into new image" >> /home/myfile