DEV Community

Cover image for Build Safer Docker Images
Adriano Galello
Adriano Galello

Posted on • Originally published at gdi3d.github.io

Build Safer Docker Images

When you're building your container image there are at least two effortless practices that you can follow:

  1. Prefer minimal base images
  2. Run process with Least privileged user

Prefer minimal base images

Base images not only help speed up your CI/CD pipelines, reduce storage space and network traffic. They also help you reduce the attack surface of your container.

Your container should only have the dependencies that it needs to run and nothing more.

I know, we all love to ssh into the container and use vim, ping, or some other tool to debug it. But being lazy can get us into trouble very quickly 😊.

Explore the following base image options:

  • Scratch If you are going to run a binary that doesn't need any other libs (GO programs for example).
  • Alpine The image is only 5 MB in size and has access to a package repository to install what you need.
  • If you want/need more, you can also try images with -slim version or even with -alpine.

Run process with Least Privileged User

Your process inside the container shouldn't run as root unless is mandatory.

Having a process running as root means that an attacker could gain root access and perform an attack on the host.

Imagine that someone mounts a volume to the container and an attacker was able to gain access to the container by the process running as root. They would be able to manipulate that external volume with no issues at all.

What if that container has been launched using --privileged flag?

The --privileged flag gives all capabilities to the container. When the operator executes docker run --privileged, Docker will enable access to all devices on the host as well as set some configuration in AppArmor or SELinux to allow the container nearly all the same access to the host as processes running outside containers on the host. Additional information about running with --privileged is available on the Docker Blog.
https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

As you can see, potential issues begin to emerge very quickly.

How do you run a process as non-root?

In your Dockerfile make sure you create a new regular user and then activate it.

Here's an example of how it can be done

...
# crate a non-root user
ENV NONROOT_USER myappser
ENV NONROOT_UID 1000
ENV HOME /app

RUN adduser --disabled-password \
    --gecos "Default user" \
    --uid ${NONROOT_UID} \
    ${NONROOT_USER}

USER root
# all files in the home folder will
# be owned by the non-root user
RUN chown -R ${NONROOT_USER}:${NONROOT_USER} ${HOME}
USER ${NONROOT_USER}

# You can add your CMD after this if you want to
...

Enter fullscreen mode Exit fullscreen mode

Photo credit: Francesco Ungaro

Top comments (3)

Collapse
 
phlash profile image
Phil Ashby

Good advice - thank you!

I would also like to mention keeping dependencies patched. Security vulnerabilities can leak into images (and thus get deployed by you!) through outdated dependencies, particularly base images It pays to automate dependency checking (use your source control / CI tooling solution - they often have this available).

Collapse
 
adriens profile image
adriens

Sure, the must-have indeed ;-p

Collapse
 
icolomina profile image
Nacho Colomina Torregrosa

Good advice, many thanks!