Learning Docker creating your own base image

Docker images are compiled in layers using a set of instructions contained in a text file called Dockerfile. Every container image starts with a base in many cases this base image is pulled from Dockerhub or your own repository. When creating your own base image you have two choices build one or use scratch.


Scratch is build into docker and is provided as a minimal linux environment that cannot do anything. If you have a compiled binary that will work in the container scratch may be a perfect minimal container. Do not expect scratch to have a package manager or even command line. For our example lets assume we have a basic c program called hello-world and is compiled:

FROM Scratch
ADD hello /
CMD ["/hello"]

This would start the container run the executable and end the container. My base container size with scratch alone is 1.84 kilobytes.

Building your own Image

Building your own image starts with install of the target operating system. Since Redhat and Ubuntu seem to be the most common operating systems available today I’ll provide instructions for both. In these instructions it’s possible to build minimal containers without package managers but these are multi-purpose base images. In both cases the process installs a minimal version of the operating system in a subdirectory then compiles the docker image from this directory.


Debian based systems make it really easy with the debootstrap command which is installed by default on Ubuntu. We will setup the image using Ubuntu 19.04 Disco Dingo.

sudo debootstrap disco disco > /dev/null
sudo tar -C disco -c . | docker import - disco

You now have a docker image called disco that is a minimal Ubuntu 19.04.

docker images

Redhat / Centos

I’ll use centos since I don’t personally own any Redhat licenses but the process is exactly the same. This will build the same version of OS you are currently running. You will need to change the RPM-GPG-KEY with your version of Centos. I read about the CentOS process in this article.

# Create a folder for our new root structure
export centos_root='/image/rootfs'

mkdir -p $centos_root

rpm --root $centos_root --initdb

yum reinstall --downloadonly --downloaddir . centos-release

rpm --root $centos_root -ivh --nodeps centos-release*.rpm

rpm --root $centos_root --import  $centos_root/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

yum -y --installroot=$centos_root --setopt=tsflags='nodocs' --setopt=override_install_langs=en_US.utf8 install yum  

sed -i "/distroverpkg=centos-release/a override_install_langs=en_US.utf8\ntsflags=nodocs" $centos_root/etc/yum.conf

cp /etc/resolv.conf $centos_root/etc

mount -o bind /dev $centos_root/dev

#Enter the file system for our image to do a yum clean (remove cached stuff) type exit to leave the chroot 
chroot $centos_root /bin/bash 

# Run this command then type exit to leave the chroot
yum clean all

rm -f $centos_root/etc/resolv.conf

umount $centos_root/dev

#Create the docker image
tar -C $centos_root -c . | docker import - centos

You now have a image called centos.

Put it together

Building your own images assures that no one can put something into your image that is unexpected. Scratch is a great way to run very minimal containers that are very small. If you need a fuller operating system you can use Ubuntu or CentOS.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.