How To Build Your Own Docker Images
Thanks to Ugur Ceylan for the base image! CC BY 2.0
What’s with the Docker community’s love affair with Alpine Linux? Tiny containers mean more compute resources left over for actual… computing! Alpine Linux is particularly tiny. It says so, right on the tin: “Alpine Linux is a security-oriented, lightweight Linux distribution based.”
Do you like saving money? I like saving money. Better resource utilization means happy bank accounts.
Let’s take a closer look at Alpine Linux on Docker. Heck, while we’re at it let’s build our own image.
Table of Contents
Building Your Own Container
The first step to building an image is creating a new directory, and opening the Dockerfile. Follow along, but replace the “atom” line with your favorite text editor.
cd ~ mkdir buildingDockers cd buildingDockers atom Dockerfile
In atom, add the following line to the file and save:
FROM iron/base
This is Iron.io’s base image for containers, but you could actually name any image you want from the Docker repo.
I like the iron/base image, because (newsflash!) this is an Iron.io blog. But, also since it adds essential libraries that come in handy when we start adding and building other packages.
All we need for starters is the FROM
command. Let’s build the container! On the command line type:
docker build -t namehere .
Hero in a Half Shell
Great, we’ve got a container. Now what do we do with it?
Accessing the shell is a great way to admire our work. It’s also pretty handy for troubleshooting. To fire up the image and drop to the shell, try:
docker run --rm -it namehere /bin/sh
Note, this is NOT Bash.
There are a bunch of useful commands for building Docker images. To simplify, this guide is just going to cover FROM
(noted above) and RUN
commands. Once you build up some comfort, it’s definitely worth visiting the official docs to look at the whole list of options.
Born to RUN
RUN
is how to execute a command. For instance, Alpine Linux has a nice package repository, similar to apt-get (and the like). To see what’s installed already, try adding the following to your Dockerfile:
RUN apk info
Admiring our installed packages is only so useful. Let’s add something. To do so, pick a package from the Alpine Linux packages repo. Now, add it to the Dockerfile:
RUN apk add packageNameHere
IronWorker On-Demand Async Task Processing Tool
Speak to us to learn more about scheduling and message queues.
Best Practices and Caveats
Docker hosts a great best practices guide. In it, they note the importance of keeping images small in size. Avoiding bloat is simple and intuitive. No sweat, right? Just install the software that’s needed.
Wait, crap. Are you also limiting the number of RUN commands in your Dockerfile? Dockerfiles are built in layers. Each command adds a new layer. More layers mean more work has to be done to cleanly merge them all together.
Dress in Layers
To reduce layering, it’s recommended to group commands. This will add a single layer while performing as much work as we desire. Grouping commands looks something like this:
RUN command1 && command2
Make it more readable by using “” and carriage returns:
RUN command1 && command2 && command3
Grouping commands is great until it turns into mental gymnastics. When that happens, prioritize maintainability. Use an extra RUN
command if it reduces the cognitive load. As Kelsey Hightower notes in 12 Fractured Apps, twisting a RUN
command into a shell script is a less than great (read: terrible) way to keep an image maintainable.
Drop the Cache, and Nobody Gets Hurt
There’s no need to cache package installs in Docker-land. So, let’s drop the cache. To do so add the following near the end of your Dockerfile:
RUN rm -rf /var/cache/apk/*
Musl Milk
If you venture outside of the official Alpine Linux apk
ecosystem, there’s a good chance you’ve chosen to compile from source. Be aware that Alpine Linux relies on Musl rather than GCC.
Compile accordingly.
Busy Beat Boxin’
Alpine Linux made a few sacrifices at the shrine of distro size. Rather than install the standard suite of *Nix utilities, they opted for BusyBox. It’s a nice (tiny) compaction of some common utilities.
That means that some utilities might not accept the usual GNU flags. It also means some utilities are completely missing. Want curl
in your image? You’ll have to install it.
Keep Learning
Alpine Linux has a great wiki if you find yourself looking for more handy tips.
Lastly, it’s easy to inspect the Docker images that power our handy IronWorker guides. If you’d like to see how we write our Dockerfiles, visit github.com/iron-io/dockers.
Unlock the Cloud with Iron.io
Find out how IronWorker can help your application obtain the cloud with fanatical customer support, reliable performance, and competitive pricing.