Moving Docker to it's own Server
Introduction
Difficulty: Intermediate
What you should know:
- How to edit YAML
- How to create and setup VMs
What you will need:
- A VM Hypervisor of your choice
- docker
- docker-compose
What you will learn: How to install and setup Flatcar Linux as a remote docker installation
In this guide, the following representations are made:
192.168.0.2represents the development machine with docker installed1192.168.0.3represents the VM that will be setup2
Situation
One of the most prolific problems that I’ve run into while developing with
docker is running out of disk space. This can become quite the problem if you
are working on things that are not related to docker. Suddenly finding out that
you can’t run a git commit, update the system, or save a file because you ran
out of disk space is a pain in the neck.Using tools such as ncdu to locate
where all my space has gone, nearly every time I find that the cause is due to
docker containers, images, and volumes. It’s no surprise that docker takes up a
lot of space during development. Hundreds of “dangling” docker images are left
over with the constant docker-compose up --build and docker-compose down.
You might say that I’m running out of space because I’m not regularly cleaning out my docker images, that I didn’t partition my system correctly, or that I’m not effectively using docker volumes to simplify my work. You might be right about that, but I much prefer using a remote host to develop on using Flatcar Linux. I now let a VM running Flatcar handle all the data issues and if it needs to be re-installed, that’s not a problem and can be easily done.
A Potential Solution
Years ago, I had heard about an operating system called CoreOS whose update process was based upon the work done for Chrome OS. The idea was that you could have many machines (based upon the “Machines are cattle, not pets” principle) running docker in a clustered environment and updates were performed by merely rebooting the host machines. All applications would run inside of Docker and no real user accounts would exist on the machine.
However, CoreOS is no longer available. The wonderful thing about Open Source is the fact that, if something is useful, people will keep it available in some way. Enter, Flatcar Linux.
What is Flatcar Linux
Flatcar Linux is a fork of Container Linux (formerly CoreOS) and works off the principle that the only thing it runs is docker. This means that all applications, whether they are production or used for development, are run within docker containers. A setup like this allows users to build images and run containers with more flexibility than running docker on your main machine. If you run out of disk space on your Flatcar instance, you still have space on your development machine to save your work. Or maybe you’d like to reboot your dev machine for system updates? That can be done as well without shutting down your containers. Unless, of course, Flatcar is running as a VM on the same machine that you’re rebooting. In which case, the VM can be paused and resumed after you’ve updated. If starting fresh is necessary, everything is a simple reinstall away from being in a fresh, clean, state. Or maybe testing in a kubernetes cluster is needed, that can be done too.
Suffice it to say, you’ve got options and it’s awesome! You’re no longer limited to your local box.
Downloading Flatcar Linux
There are a few different ways to download and install Flatcar Linux. For the sake of this tutorial, I will be going over the installation process for installing Flatcar Linux on a Bare Metal Server. While it’s not the easiest, it is the most portable setup and can work with any operating system. These steps can even be followed on that old laptop that’s been collecting dust for the past few years!
So first, go to the docs that detail installing from an ISO and download the Stable ISO. Once it’s downloaded, insert it into the virtual CD drive of your preferred virtual machine software and boot from it.
Next, we’ll need a machine capable of running docker containers to setup the installation config.
Flatcar Pre-Requisites
Aside from having a VM that can support Flatcar and all the containers that you
plan to run, Flatcar also requires an installation file called ignition.json.
Throughout the following steps, it is expected that you will end up with a
directory structure similar to the following:
flatcar-project
├ data - used for mounting into the docker container
│ ├ flatcar.yml - easy to read config file
│ └ ignition.json - generated config file from flatcar.yml
├ create-ignition-file.sh - executable used to easily regenerate ignition.json
├ Dockerfile - docker build file for a simple web host
├ docker-compose.yml - composition config for a simple web host
└ index.html - default index file used to indicate if things are
setup correctly or notThe next steps should serve as a guide for creating the ignition.json and
serving it via a simple web server so that we can download it onto our Flatcar
installation live CD.
Create ignition.json
The data/ignition.json file is Flatcar’s installation config. However, most
of the configuration is actually done via yaml, rather than json. I’ve got an
example yaml file here that you are free to use, however. A username, password
hash, and SSH key will need to be provided. If you want to disable password
login, line 9 containing password_hash: "PASSWORD_HASH" will need to be
deleted.
If you would like to skip to where the ignition.json file is generated,
please click here
flatcar.yml
Generating the JSON Ignition File
Once the YAML config has been created, it is time to convert it into a json
file. By following the Flatcar Documentation, they recommend
using an application called ct. Luckily, ct can be run from a docker container
and is still in a docker registry under the CoreOS project. The script below
expects the flatcar.yml file to be in a subdirectory called data. It then
reads it’s contents and sends them to the standard input of the ct command (by
running docker). Then, the resulting ignition.json will be written to the
same data directory that flatcar.yml resides in (the data dir will be used
later).
Assuming that the above flatcar.yml is in the data directory, the below
commands within create-ignition-file.sh should create an ignition.json in
the same folder.
Docker Webhost Configuration
The docker configuration consists 3 files.
- Dockerfile - used for creating a lighttpd web host container
- index.html - a dummy file to determing if the docker volume was mounted correctly
- docker-compose.yml - used for quick orchestration
The contents of these files should be the same as the ones in the following Github gists:
Setup lighttpd to serve ignition file
With everything in place, we can now bring up our webserver and verify that we
can access the ignition.json file. Within the project directory, the
webserver can be brought up by running
docker-compose up --buildOnce the container has fully started up, visiting http://127.0.0.1:8080/ in a
web browser should bring up a file list and ignition.json should be visible.
Make sure that you know your computer’s IP1, as it will be needed for the
next section.
Install Flatcar Linux
You can find the official Install Guide for Flatcar on their
docs, but for a bare-metal install (which has been used throughout this guide),
the installation commands boil down to 2 commands. The first to pull down out
config and the second to install it to disk. Make sure that you replace
192.168.0.21 in the highlighted line with the IP address of your machine
running the simple webhost that was setup earlier.
|
|
At this point, flatcar should be installing itself into the VM that was setup earlier. Once it has been completed, you are free to remove the ISO file from the VM and reboot it. Before rebooting the machine, make sure that you have it’s IP address in hand2.
Point docker commands to remote docker instance
Most guides out there (including the one from the Flatcar docs)
suggest setting the environment variable DOCKER_HOST to the IP of the remote
docker server2.
1export DOCKER_HOST=tcp://192.168.0.3:2375While there is nothing wrong with doing it that way, I prefer to use the newer
docker context commands3 that allow the registration of 1 (or more) docker
servers. The docker context ls command shows what will be setup by the end of
this section.
1$ docker context ls
2NAME DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
3default Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
4flatcar * tcp://192.168.0.3:2375 swarmNormally, the only context that exists is the default context which connects
to the local docker daemon via unix file sockets. The flatcar context shown
above can be created with the following command (replace the VM IP with the IP
of your own Flatcar installation2):
1docker context create flatcar \
2 --docker "host=tcp://192.168.0.3:2375" \
3 --default-stack-orchestrator swarmOnce the flatcar context command has been created, it can now be used in any docker or docker-compose commands. Like so:
docker --context=flatcar images -a
docker-compose --context=flatcar psBoth of those commands will run on the flatcar instance4. However, adding--context=flatcarto all docker and docker-compose commands can become quite tedious. Luckily, docker allows the selection of the default context. Running the following command should allow the use of the flatcar context, without ever needing to type the--contextparameter ever again:
1docker context use flatcarConclusion
After following this guide, all docker containers and commands should now run
on a VM (or bare-metal machine) running Flatcar Linux. The final step (though
completely optional) in preventing usage of the docker daemon on the dev
machine is by disabling docker with systemctl disable docker --now. That
should stop docker and make sure it doesn’t start when rebooting. This setup
can be used amongst multiple machines and it will provide flexibility as the
software industry continues to evolve.
-
192.168.0.2is the representation of your machine running docker ↩︎ ↩︎ ↩︎ -
192.168.0.3is the representation of your flatcar VM ↩︎ ↩︎ ↩︎ ↩︎ -
Docker contexts appear to be more flexible and don’t feel like a “hacked together solution” in my eyes. ↩︎
-
Caveat: I have found that running
docker-compose --context=flatcar builddoes not build the docker image on the remote host for whatever reason. A workaround is to prepend the command withCOMPOSE_DOCKER_CLI_BUILD=0to set an environment variable that forcesdocker-composeto run the builds on the remote host. ↩︎