Building a Beautiful Docker Image for OpenShift

Bashayr Alabdullah
The Startup
Published in
4 min readJan 23, 2021

Small Tips!

There are some practices that OpenShift Container Platform recommends to follow them. Here, guidelines that apply when creating container images if you use OpenShift Container Platform.

First

What does mean by beautiful Docker image?

Minimal size, Security and Performance.

Dockerfile Instructions

  • RUN

The RUN instruction executes commands in a new layer on top of the current image and then commits the results to be used in the next step. In Dockerfile, each instruction is a new layer; that means if you have instructions like this:

RUN pip install virtualenv 
RUN virtualenv /venv
RUN . /venv/bin/activate
RUN pip install setuptools -U
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

Then, you will be have image with 6 layers resulting in images that are unnecessarily large. Therefore, it’s important that you minimized the number of layers in your images to ensure getting the best performance which are faster to deploy. For example, to have the minimal layers from the previous example use && command separator to execute multiple commands within a single RUN instruction:

RUN pip install virtualenv && virtualenv /venv && \
. /venv/bin/activate && \
pip install setuptools -U && \
pip install --upgrade pip && \
pip install -r requirements.txt

Now, it produces only one layer.

With Docker v1.10 and later, only the RUN, COPY, and ADD instructions create layers.

  • LABEL

The LABEL instruction is key-value pairs that contains the metadata of image such as versions, description, name, and any other details. In OpenShift, the label name prefix with io.openshift and for Kubernetes io.k8s . The below table is showing some of the most commonly used tags:

OpenShift some supported labels

It recommends to use only one instruction for all labels and separate each key-value pair with an equal sign (=) like this:

LABEL description="This is an example for label uses" \
version="1.0" \
creationDate="26-01-2021"
  • WORKDIR

The WORKDIR instruction is working directory path. It’s recommended to use it instead of multiple RUN instructions to help in maintaining, read and troubleshoot.

  • ENV

The ENV instruction is environment variables provided to the container. If you have for example web application that contains two docker images, one image is back-end and the other is front-end and you need to write IP back-end’s IP in front-end’s then using ENV is the best way to define the IP if the IP changes or you want to use the image in different place instead of hard-coding it. Similar to LABEL to specify multiple environment variables use layering concept, separate each key-value pair with an equal sign (=):

ENV MYSQL_DATABASE_USER="my_database_user" \
MYSQL_DATABASE="my_database"
  • USER

For security reason, run your image as a non-root user. By default OpenShift uses Security Context Constraints (SCCs) which allow administrators to control permissions for pods named restricted. Therefore, it makes OpenShift uses a random userid other than the root userid (0) to run containers. To enable use root user, you need to use the anyuid SCC. First, create a service account bound to a pod:

oc create serviceaccount sa-name

Then as cluster-admin, associate the service account with an SCC:

oc adm policy add-scc-to-user anyuid -z sa-name

Finaly, assign the service account to the deployment:

oc set serviceaccount deployment deployment-name sa-name

The folders and files in the container should be owned by the root group so, you have to add RUN instruction to change group ID and permissions to access them in the container:

RUN chgrp -R 0 /some-path && \
chmod -R g=u /some-path

Use the root group minimizes security risks since it does not have any special permissions. Moreover, use group execute permissions for files that shuld be executed. In addition, since the processes running in container as a privileged user; they must not listen on privileged ports (ports below 1024).

  • VOLUME

Use VOLUMEinstructions for persistent data to create a mount point inside the container.

  • ONBUILD

The ONBUILD instruction triggers only when building a child image. It executes before any command in a child Dockerfile. ONBUILDuseful to automate the build if you need to used as the base for another build.

😘

References:

--

--

Bashayr Alabdullah
The Startup

Salam, I'm Tech Engineer 🚀. I blend technology insights, inspiration, and fun in my feed. #innovation #discovery 🥑🎶🎯🌻 *my personal -own- thoughts*