Published using Google Docs
Container updates without in-container DNF
Updated automatically every 5 minutes

Container updates without in-container DNF

Abstract

Sometimes you simply can't run/exec 'dnf update -y' in a container:

Before starting, it's important to note that updating running container like this has to be considered a corner case. Normally, new updated image should be pulled and container restarted from that image.

But we don't live in a perfect world, and more often than not pulling a new image might be a problem due to host <-> registry network disruption, Docker engine misbehaviour, or maybe just the container holds

more state than it should and the restart procedure would have devastating consequences on other parts of the infrastructure.

Locating the filesystem

The steps can be generalized as:

  1. Figure out the PID of the container process
  2. /proc/$PID/root/ then points to in-container root /

$ docker run -td fedora:22 bash  

3814dd3c128153b6c61242dca70c9970bb18bd2fe5a323ef93177ee0390a1bac  

 

$ docker top 3814dd3c128153b6c61242dca70c9970bb18bd2fe5a323ef93177ee0390a1bac  

UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD  

root                3206                1714                0                   14:49               pts/5               00:00:00            bash  

 

 

$ sudo ls -la /proc/3206/root/  

total  6  

drwxr-xr-x.  18 root root 4096 Oct 15 14:49 .  

drwxr-xr-x.  18 root root 4096 Oct 15 14:49 ..  

lrwxrwxrwx.   1 root root    7 Aug 16  2014 bin -> usr/bin  

dr-xr-xr-x.   2 root root 4096 Aug 16  2014 boot  

drwxr-xr-x.   5 root root  380 Oct 15 14:49 dev  

-rwxr-xr-x.   1 root root    0 Oct 15 14:49 .dockerenv  

-rwxr-xr-x.   1 root root    0 Oct 15 14:49 .dockerinit  

drwxr-xr-x.  45 root root 4096 Oct 15 14:49 etc  

drwxr-xr-x.   2 root root 4096 May 22 01:59 home  

lrwxrwxrwx.   1 root root    7 Aug 16  2014 lib -> usr/lib  

lrwxrwxrwx.   1 root root    9 Aug 16  2014 lib64 -> usr/lib64  

drwx------.   2 root root 4096 May 22 01:58 lost+found  

drwxr-xr-x.   2 root root 4096 Aug 16  2014 media  

drwxr-xr-x.   2 root root 4096 Aug 16  2014 mnt  

drwxr-xr-x.   2 root root 4096 Aug 16  2014 opt  

dr-xr-xr-x. 338 root root    0 Oct 15 14:49 proc  

dr-xr-x---.   2 root root 4096 May 22 01:59 root  

drwxr-xr-x.   3 root root 4096 Oct 15 14:49 run  

lrwxrwxrwx.   1 root root    8 Aug 16  2014 sbin -> usr/sbin  

drwxr-xr-x.   2 root root 4096 Aug 16  2014 srv  

dr-xr-xr-x.  13 root root    0 Oct 15 10:50 sys  

drwxrwxrwt.   7 root root 4096 May 22 01:59 tmp  

drwxr-xr-x.  12 root root 4096 May 22 01:58 usr  

drwxr-xr-x.  18 root root 4096 May 22 01:58 var  

Update container

Both DNF/YUM define an '--installroot' flag, which allows the caller to specify alternative root path from which RPMdb is read and where packages are updated/installed/removed. We also want to use in-container repository information

and plugins which can be done by specifying '--config' pointing to appropriate location within the $(installroot).

$ sudo dnf --setopt=tsflags=noscripts --installroot=/proc/3206/root/ --config=/proc/3206/root/etc/dnf/dnf.conf update  

Note that this still uses on-host repositories, we'd need '--repo-path' to allow for loading repository definitions from a different path.

Wrapping up

After DNF is complete we want to snapshot the container image so that another container started from the same image name will get the updated content:

$ docker commit 3814dd3c128153b6c61242dca70c9970bb18bd2fe5a323ef93177ee0390a1bac fedora:22  

Give me the code

The above workflow captured in a shell script can be found here:

shaded-enmity/dnf-container-update · GitHub

$ sudo ./dnf-container.update 3814dd3c128153b6c61242dca70c9970bb18bd2fe5a323ef93177ee0390a1bac