Dockerising my Workstation with Atomic: Part 1

Tom Apr 12, 2018
Dockerising my Workstation with Atomic: Part 1

Recently I've switched both my work and home computers to Fedora Atomic Workstation (hereafter referred to as Atomic), an operating system with the cloud and containerisation at the forefront of its architecture, so in this series of blog posts I’m going to be taking a look at Project Atomic [1], what an Atomic operating system is and how to get started with it.

What is Atomic?

Project Atomic is “an umbrella for many projects related to re-designing the operating system around principles of immutable infrastructure, using the LDK (Linux, Docker, Kubernetes) stack” [2]. Atomic itself is the name for a specific style of (provider agnostic) Linux distribution that is built around the design principles of distributed systems where configuration consistency and scalability are primary concerns. It has an immutable filesystem, is updated via a 'git like' ostree system and treats containers as first class citizens. We we will briefly look at each of these attributes below but for a more thorough explanation Project Atomic [3] is a good place to start and RedHat also provides an excellent comparison document [4].

Immutable filesystem

Unlike a normal Linux system the filesystem in an Atomic OS is read only. Prohibiting filesystem changes helps ensure that in scenarios such as deploying a large number of Atomic hosts in a cluster, (or dynamically adding and removing nodes from a cluster) machines all maintain exactly the same state. In fact /etc and /var are the only folders that it is possible to write to in Atomic! If you are imagining that this makes managing system updates very different to normal Linux systems you would be right. The idea of moving from one known state to another via transactional upgrades is central to the design of Atomic, rather than updating a package by writing to (or over) an existing filesystem you instead check out a new ostree which contains the updates. Ostrees are immutable bootable filesystem trees and have been called ‘git for binaries’ [5] or 'a more polished version of Linux VServer hardlinks' [6].

Atomic Updates

The atomic in Atomic comes from the fact that filesystem updates are 'atomic', or transactional, in nature. This goes hand in hand with the immutable filesystem and means that any new ostree that is checked out, or package that is layered on top of it, will only become available after the new ostree is live, which practically means after a reboot [7].

One of the great benefits of this system is that by default Atomic stores the previous version of the ostree, which means that if you make a breaking change you can simply select the previous configuration in the bootloader and roll back to it seamlessly.

Container Support

One of the most interesting aspects of Atomic is that as well as supporting Docker it allows you to build and run daemonless OCI containers (using for example runc [8]). Daemonless containers are interesting as they allow us to start container processes earlier in the boot sequence, use different orchestration systems, have better init system integration and more... [9]. There are already a wealth of tools emerging in this area to help you get building and running containers without Docker [10] so it’s a great time to start experimenting.

If you want to manage long running or orchestrated container processes you may find that systemd is not enough [11]. In these cases it would be sensible to run Kubernetes or OpenShift on your Atomic host as well. Luckily as OpenShift has the great oc tool running a local OpenShift instance can be as simple as a systemd unit running “oc cluster up” and linking some volumes for persistent configuration and storage. OpenShift in 3.9 is already using CRI-O [12] as the container runtime interface [13] so you can experiment with non Docker runtimes there as well.

Applications in Atomic

As we have established that installing packages and applications is pretty different in Atomic let’s quickly look at the various methods available.

Flatpak

Without a doubt the easiest way to run an application is as a Flatpak. Flatpak is a distribution agnostic sandboxed format which shares common runtimes and includes all required libraries in the package. The sandboxed nature of Flatpak emphasises security and as such access to other processes is deliberately not possible.

Flathub [14] serves as a central repository for flatpak applications, and these can be installed from the website, via the Software GUI or using the CLI. The main downside to flatpaks currently is simply that there are not enough of them available.

There are other packaged application formats that will run in Atomic, such as AppImages and I would encourage you to look at the following comparison chart [15] to learn more about each of them.

rpm-ostree

Instead of a package manager in Atomic you have the rpm-ostree command. This command allows you to overlay packages on the current filesystem, creating a new ostree. Packages overlaid in this manner are subject to the same atomic update rules as the system itself [16].

There is quite a bit of magic in the rpm-ostree command (such as bubblewrapping RPM %post scripts to ensure OSTree integrity) and because only a subset of the packages in the mainline repo are currently available in this format [17] you should think about using this command only when you can’t avoid it. My current ostree status looks as follows:

ostree://pirate:fedora/27/x86_64/workstation
Version: 27.98 (2018-03-25 21:40:41)

BaseCommit: 837c870919d5182948ae9041e6404c5e306bae6c4db1ba3e07b2c323af8b7556

GPGSignature:
Valid signature by 860E19B0AFA800A1751881A6F55E7430F5282EE4

LayeredPackages:
libselinux-python python util-linux-user zsh

Breaking this down we can see that I am using the most current ostree (at the time of writing), I’m pulling it from the unofficial European 'pirate mirror' [18] and I have only four layered packages,

util-linux-user is there so I can chsh to my shell of choice, zsh, and the python packages are installed so that I can configure my system using Ansible, that's it! Instead most of my applications are provided using the final method we will look at, containerisation.

Containers

If you have used containers before it is most likely to be in the context of back end or web applications rather than the desktop, but the good news is that it’s not difficult to containerise a desktop application either and a small amount of work here can give us a really great portable system. There are people doing really exciting work in this area and I can’t recommend Jess Frazelle’s github [19] enough if you want to get some ideas about tools you can successfully dockerise [20].

Atomic also comes with it’s own command to manage containers, adding INSTALL, RUN and UNINSTALL labels to our images allows the atomic command to create containers which manage their own lifecycles, install themselves by, for example, mounting parts of the host filesystem and installing and enabling systemd units. The atomic command can even be used to upgrade your containers by pulling the latest version of the image from a repository and recreating your container with it.

But Why?

Now you may be saying to yourself “this sounds pretty cool for a cloud server or my Kubernetes cluster by why you would choose this for your desktop?” And that is a fair question, if you go down this road you better like working with containers and be prepared to troubleshoot. However I believe this a price worth paying as not only do you get to work with and explore some of the most exciting tools in containerisation technology but you will get experience in, and I believe see the advantages of, creating portable containerised environments. For example containerising your workstation can make it extremely easy to reproduce your entire system anywhere and be running in minutes, something we’ll explore in a later article. Apart from those reason I would also add that is just extremely nice to work in this way and the community around Atomic really friendly, open and accessible. If you use containers for development or deployment it’s really not that much of a leap to start using them for your desktop.

So that wraps up our quick overview of what Atomic is. Next time we will be looking at putting a desktop application into a container and running it without a daemon so you can begin to recreate your environment in the Atomic world.

>>> Click here for the second part of the series.



    [1] https://www.projectatomic.io/
    [2] http://www.projectatomic.io/docs/introduction/
    [3] https://www.projectatomic.io/docs/
    [4] https://access.redhat.com/articles/2772861
    [5] https://ostree.readthedocs.io/en/latest/manual/introduction/
    [6] https://ostree.readthedocs.io/en/latest/
    [7] There is currently work underway to allow in place changes https://github.com/projectatomic/rpm-ostree/issues/639
    [8] https://github.com/opencontainers/runc
    [9] For a great overview of Docker architecture and how the runtimes work I would recommend these articles .
 [10] http://www.projectatomic.io/blog/2018/03/the-many-ways-to-build-oci-images/
 [11] For a lightweight cron-like replacement I can suggest Crontainer by fellow niner Phil Hässig
 [12] https://github.com/kubernetes-incubator/cri-o
 [13] https://www.redhat.com/en/blog/introducing-cri-o-10
 [14] https://flathub.org/
 [15] https://askubuntu.com/a/1009061
 [16] The system update command “atomic host upgrade” is actually an alias to “rpm-ostree upgrade”
 [17] Adding additional remotes like epel also does not work for obvious reasons
 [18] https://faw.piratemirror.party/README.txt
 [19] https://github.com/jessfraz
 [20] Also check out her blog! https://blog.jessfraz.com