Docker: Building Images
Continue sharing my journey in having all my virtualization needs in docker.
This time, I will talk about my method in building docker images from base images.
You will learn a way to build docker images for your needs.
This article will take about four minutes to read.
Introduction
After figuring out the commands I need in docker for all my virtualization needs, I want to start building out specific docker images so I can be productive with a consistent environment.
Goal
The goal is to create a docker image that does what you need when
running: docker run <image tag>
.
Building on Shoulders of Giants
If possible, use a pre-existing docker image. Docker hub hosts these here:
https://hub.docker.com/search?q=&type=image
The official ones by docker (for cross platform compatibility)
https://hub.docker.com/search?q=&type=image&image_filter=official
I’m not sure if it’s possible, but one can build their own docker image without an image. 🤔
Operating System Playground
A docker image can be as simple as an operating system image. If you just want to just play around with another operating system instead of tainting your host system, a base operating system would be perfect:
https://hub.docker.com/search?source=verified&type=image&category=os
The Dockerfile would be:
FROM ubuntu
Build it with:
docker build . -t <image tag>
Run it using:
docker run -it <image tag> /bin/sh
Language Playground
If you want to play with a different programming language in a clean environment,
https://hub.docker.com/search?source=verified&type=image&category=languages
The Dockerfile would be:
FROM ruby
Build it with:
docker build . -t <image tag>
Run it using:
docker run -it <image tag> /bin/sh
Docker Philosophy
When building out other systems when I install programming languages, I usually include version management like rvm/nvm
When building out an image in docker, you can install these. They will be harder to use later on as these version management system require user environment configurations.
The philosphy for a docker image is different than building out other systems, the intention for a docker image is a single use case, like an appliance. The system will be rebuilt consistently each time and not intended for multi-user/applications. To run an application with another version of a programming language, create a new image for it.
Frameworks Playground?
I would expect there would be docker images for web frameworks such as Express (node), Ruby on Rails (ruby), or even Django (python). Django and Ruby on Rails have depreciated their images for the base language versions instead.
When considering changes in the language and frameworks, this would
become an n x m
problem.
From the framework pages, each recommend their own method to create a docker image with the framework.
FROM ruby:2.3
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /usr/src/app
COPY Gemfile* ./
RUN bundle install
COPY . .
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
Docker Image
With a base image, I go into this cycle in creating a custom docker image that fit my needs:
- run image
- connect to container
- interactively execute configuration commands
- update Dockerfile
- build new image
- goto step 1
When using docker run -it <image tag>
, the cycle becomes:
- run & connect to container -
docker run -it <image tag>
- interactively execute configuration commands
- update Dockerfile
- build new image -
docker build . -t <image tag>
- goto step 1
Five simple steps to custom docker images with all your needs.
Updating Dockerfile
When updating the Dockerfile, use the RUN
directive to add new parts
to the image when running docker build
. Whatever the system requires
a command to build to your desire, add it in to the Dockerfile:
FROM <os>
RUN <command_1>
# ...
RUN <command_n>
For example: setting up a system to run Jekyll:
# originally: https://github.com/BretFisher/jekyll-serve/blob/main/Dockerfile
FROM ruby:3-alpine
RUN apk add --no-cache build-base gcc bash cmake git
RUN gem install bundler
Build the image:
docker build . -t <image name>
Now, when you run the image:
docker run -it <image name> /bin/bash
the environment is exactly how you want it to be. If something goes wrong when working with it:
docker image rm <image name>
Conclusion
Building a docker image to suit your needs can be tedious as there’s a “run, record, update” loop with the system and Dockerfile.
Before building, use a docker image from Docker Hub that most resembles your goal. Using public docker images lets you focus on parts of the system that is unique to your goal.