Monday, March 16, 2015

Creating Base Images

In First Steps with Docker, we have used a fairly crude way to create initial base images. A minimalistic approach to come to a base image environment is to have only the necessary rpms installed through on-board tools. This assumes the system is enabled for accessing all packages online.

Inspired from, this script works both for SLES 12 and RHEL 7:

Update 3/26: added "--releasever=/" to the yum statement, per Neale's comment and the discussion on the LINUX390 mailing list at Marist. Also added copying of /etc/rhsm and /etc/pki (works the same for me, works better for Neale). Thanks for pointing this out, Neale.
Update 5/07: added "/etc/products.d" to the cp statement, to avoid warnings in some cases when using zypper.
Update 10/12: removing yum cache contents (via that "yum clean all" takes another 34MB away, so down to ~110 MB now
Update 1/29: hint on an issue. It seems the LinuxONE cloud also requires the comment to be uncommented...
Update 5/17: set CMD to /bin/bash for convenience
Update 6/21: use yum-plugin-ovl to avoid issues between yum and overlayfs-backend (also Thanks again for pointing to this package, Neale!
mkdir img || exit
mkdir -m 755 img/dev
mknod -m 600 img/dev/console c 5 1
mknod -m 600 img/dev/initctl p
mknod -m 666 img/dev/full c 1 7
mknod -m 666 img/dev/null c 1 3
mknod -m 666 img/dev/ptmx c 5 2
mknod -m 666 img/dev/random c 1 8
mknod -m 666 img/dev/tty c 5 0
mknod -m 666 img/dev/tty0 c 4 0
mknod -m 666 img/dev/urandom c 1 9
mknod -m 666 img/dev/zero c 1 5

test -d /etc/yum && yum --installroot=$PWD/img --releasever=/ --setopt=tsflags=nodocs \
--setopt=group_package_types=mandatory -y install bash yum vim-minimal yum-plugin-ovl
test -d /etc/yum && cp -a /etc/yum* /etc/rhsm/* /etc/pki/* img/etc/
test -d /etc/yum && yum --installroot=$PWD/img clean all

# in some cases the following line is needed. I still have not understood, why...
# test -d /etc/zypp && mkdir img/etc && cp -a /etc/zypp* /etc/products.d img/etc/

test -d /etc/zypp && zypper --root $PWD/img  -D /etc/zypp/repos.d/ \

--no-gpg-checks -n install -l bash zypper vim
test -d /etc/zypp && cp -a /etc/zypp* /etc/products.d img/etc/

rm -fr img/usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
rm -fr img/usr/share/{man,doc,info,gnome/help}
rm -fr img/usr/share/cracklib
rm -fr img/usr/share/i18n
rm -fr img/etc/
rm -fr img/var/cache/ldconfig/*

Please pay attention to line feeds due to the rendering in your browser (particularly watch the yum and zypper commands and the first line with rm). This script produces a directory img containing a lean environment just capable of running a shell, editing files and comfortably install further packages (via zypper/yum). You can import it into an image using
cd img
tar cf - . | docker import --change "CMD /bin/bash" - your-image-name

The results is a comfortably small image:
r1745044:~ # docker images
REPOSITORY            TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
sles12-mini           latest              d67d54066582        19 seconds ago      249.7 MB
[root@r1745042 ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
rhel7-mini          latest              ea7c03641155        23 seconds ago      138.1 MB
You can add any packages to the package installer line (zypper/yum) in the script, e.g. should you prefer another editor. Of course, true fans of emacs probably can remove all other packages except emacs (but then they still need a good editor :-).


  1. For yum, I learned that I needed to add --repository=7Server as the $releasever variable wasn't being expanded and the yum install would fail.

  2. Hi Neale, thanks a lot! I updated the script in the article.

  3. Image is created, but "There are no enabled repos"
    Could you please tell me if there is any way to enable repos to install few packages using this base image ?

    1. Hi there, this script should pick up all the repo settings from your host environment. If that has got repos enabled, they should be in /etc/yum resp. /etc/zypp.
      So the question would be: are you able to install additional packages in the host with yum/zypper, but not in a container based on that image? If that is the case, the script does seem to work, and comparing the contents of /etc/yum or /etc/zypp would be the next step. What step are you stuck at?
      Just FYI: there are two other options to get started in a different, if that is what you are after:
      * if using SUSE, the Containers Module comes with sle2docker and sles*-docker-image RPMs that create a SLES base image for you
      * use opensuse:tumbleweed as an image (it's an official image with openSUSE)
      * use clefos as an image (it's an official image with a CentOS equivalent)
      * or if you are not after an image that is related to SLES or RHEL, any of the images "ubuntu", "debian", "alpine" or even "busybox" works.
      Obviously any but the first of these options requires Internet access, or at least a machine which can "docker pull" and "docker save" the image to move it to your Z environment.