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.2
represents the development machine with docker installed1192.168.0.3
represents 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 not
The 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 --build
Once 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.2
1 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:2375
While 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 swarm
Normally, 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 swarm
Once 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 ps
Both of those commands will run on the flatcar instance4. However, adding--context=flatcar
to 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--context
parameter ever again:
1docker context use flatcar
Conclusion
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.2
is the representation of your machine running docker ↩︎ ↩︎ ↩︎ -
192.168.0.3
is 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 build
does not build the docker image on the remote host for whatever reason. A workaround is to prepend the command withCOMPOSE_DOCKER_CLI_BUILD=0
to set an environment variable that forcesdocker-compose
to run the builds on the remote host. ↩︎