Docker Best Practices

Techie     April 2022


1 . Do not run SSH inside of a container.


2 . Use Minimal base images: A Minimal base image has the minimum essential resources required to run an application. The most common minimal base image is Alpine Linux which is around 2MB compared to Ubuntu which is around 60MB. Minimal base images translate to faster deploys and smaller attack surface.


3 . Verify the authenticity of any software you install in your images. You may use official apt-get softwares. If you are downloading from unofficial third party repositories, always verify they are signed or have valid checksums. For example:


4 . Never run your applications as root. Always use the user directive inside of the Dockerfile to make sure that you drop privileges of your user.

...

# create group and user

RUN groupadd -r your_user && useradd -g your_user your_user

# some images like nodejs already have a generic user node, so you may skip creating a user


# set ownership and permissions

RUN chown -R your_user:your_user /app


# switch to user

USER your_user


CMD node index.js

If your application has to start as root because it runs on a privileged support, you can map arbitrary ports on your host inside of the container so you that it doesn’t need to run with the same port inside of the container as it does outside.

In the case you need to run as root not because of the port, ensure you draw privileges preferably using gosu and not sudo.


5 . Identify cacheable units: Order Dockerfile commands from the least to the most frequently changing to take advantage of docker caching for faster builds.


6 . Exclude unnecessary files and directories when building to reduce the image size: You should remove unnecessary items like auto-generated directories(e.g target, build) and README files. Simply add them in the .dockerignore file in the root of the project.


7 . Use multi-stage builds to remove build dependencies such as package.json, pom.xml: The multi-stage build feature allows the use of multiple temporary images during the build process but only keeps the latest image as the final artifact.

# Build stage

From maven AS build

WORKDIR /app

COPY myapp /app

RUN mvn package


# Run stage

FROM tomcat

COPY --from=build /app/target/file.war /usr/local/tomcat/webapps/

...

Notice the use of directive - -from=build, to get the files generated from the build stage and copy them to the final image. The final application image is only created in the last stage.


8 . Scan the image for security vulnerabilities:

# Login to docker hub

$ docker login


# scan app

$ docker scan myapp:1.0


Thanks for reading, see you in the next one!