From docker run to docker compose
I want to share how to use docker compose to save yourself from going insane remember different docker run options for your images. (A clipboard manager can help only so far here.)
I will walk through having different functions for a docker image through docker run, then taking those commands into docker compose.
You will learn about docker compose saving docker run commands to a file and how YAML’s anchors and aliases feature can keep the file tidy.
This article will take you about four minutes to read.
Introduction
After building a docker image - you have a single appliance, software built to do one thing. What if you want to do other things with that image?
In real life, a refrigerator and freezer do similar things: keep things cold, they share the compressor, yet, what goes in each can be different or similar. Another appliance, the toaster - is different from the refrigerator that they don’t share any characteristics.
With docker images, you can create images that are similar, like a refrigerator and freezer, with overlapping characteristics. You can also create images that are so different so there’s no overlap, like a toaster and a refrigerator.
Today I will talk about reusing images for multiple tasks, like having a compressor that powers both the refrigerator and freezer.
Base Image
Last article I discussed the workflow for creating your own docker image. You can use that image or follow along with the ubuntu image
Functionality
First, let’s test the functionality of the base image and validate it can handle the tasks we want.
In my case, I will cover the following tasks:
- uptime - get system uptime
- tar gzip - combine files into single archive and compress them
- untar and unzip - take compressed archive and restore files
Testing
uptime
It’s a super simple utility that describes how long the system has been running:
tar gzip
This will take a bit more configuration as you need input files to make this function useful, namely:
-v
- use current directory as the/docker
volume in the containerw
- set the working directory in the container to/docker
/bin/bash -c "<command>"
- pass a command to bash to execute
unzip & untar
Let’s take the item created by tar gzip and restore it:
Overlap: Great; Tedious: Bleah!
Even just using a minimal ubuntu image, there can be a different
functionality created just with different options passed into run
command.
At the same time, remember each command and their options can become tedious.
Is there a better way?
Docker Compose
This is where docker compose comes in! It’s a way to manage this use case for docker (or at least how I am in this case)
Instead of remember all of those command options for docker run
, the
following docker-compose.yml
will do it:
To use this, run docker-compose run <service>
.
uptime
This is the same command as used in docker run format:
docker compose did more work, like the network and new container (for later exploration!)
targz
I named this service to targz
, as it’s doing that: “tarring then
gzipping”.
The service names in the docker-compose.yml
file can be anything you
want, so tarring_gzipping
would be fine too!
untargz
I will leave this command as an exercise for the reader. :-)
Can I do better?
Well, going from a bunch of docker run
commands to a neat
docker-compose.yml
file is a big step. Can things be better?
Yes, if we want to DRY-up the file so the overlapping settings for the
tar and untar commands are not repeated, use YAML anchors and
aliases. The docker-compose.yml
file can become:
In this case, reducing four lines is not a game changer. At the same time, knowing how to utilize YAML features for the future compose will be handy! 😉
Conclusion
Having a single docker image that can do couple of things because the base image functionality overlap is a win.
When docker run
command options start driving you nuts, write them
into a docker-compose.yml
file and run them with `docker-compose run