Strengthening your Docker Container Security with 10 best practices

PRATHEESH PC
7 min readApr 10, 2023

--

Ensuring a Safe and Secure Environment for Your Containers with this 10 best practices.

Docker is a popular tool used for containerization of applications. While Docker has many advantages, security remains a concern for many organizations.

In this article, we will discuss Docker security best practices to help you ensure the security of your Docker containers and the applications running inside them.

Use the latest version of Docker

It is critical to use the most recent version of Docker to ensure the security, stability, and features of your Docker environment. There are often security updates, bug fixes, and performance enhancements with each new version of Docker that help keep your containers and host system secure and reliable.

Furthermore, new Docker versions may contain new features and capabilities that might improve the functioning of your Docker system. You can assure that your environment is up to date and that you can obtain help from Docker if you use the most recent version of Docker.

Overall, it is advised that you upgrade to the most recent version of Docker on a frequent basis to guarantee that your Docker environment is performing optimally.

Limit container privileges

For security reasons, container rights must be restricted. When you start a Docker container, it runs as a process on the host system and has access to all of the host system’s resources. Limiting the container’s permissions reduces the risk of attackers gaining access to the host system or other containers.

You can, for example, use the user argument to provide a non-root user to run the container, or the cap-drop flag to remove particular Linux privileges that the container does not require.

# generate clean, final image for end users
FROM alpine:3.11.3

# Create a non-root user with a home directory
RUN adduser -D non_root_user

# Set the working directory to the home directory of the non-root user
WORKDIR /home/non_root_user

# Copy everything into non_root_user
COPY --from=builder /app/cmd .

# Set the ownership and permissions of the echo binary
RUN chown non_root_user:non_root_user /home/non_root_user/cmd && \
chmod 500 /home/non_root_user/cmd

# Switch to the non-root user
USER non_root_user

Explanation : The docker file creates a non-root user called non_root_user, sets the working directory to the home directory of the non_root_user user, copies the cmd binary into the container, and sets the ownership and permissions of the cmd binary.

See sample code : https://github.com/pcpratheesh/docker-with-non-root-user-sample

Use a secure base image

Using a secure base image is essential because it instills trust and dependability in your Docker environment. A secure base image is one that has been tested for vulnerabilities and built with security in mind.

You may limit the risk of security vulnerabilities and guarantee that your containers are built on a stable and trustworthy foundation by choosing a secure base image. A secure base image may include security patches, hardened settings, and security and compliance best practices.

Also can save time and effort in building and maintaining a secure Docker environment, as many security considerations are already taken care of by the base image.

FROM golang:1.17-alpine AS builder

# Set the working directory
WORKDIR /app

# Copy go mod and sum files
COPY go.mod go.sum ./

# Install dependencies
RUN go mod download

# Copy the application code
COPY . .

# Build the application
RUN go build -o app

# Use a secure base image for the runtime environment
FROM scratch

# Copy the application binary from the builder image
COPY --from=builder /app/app .

# Run the application
CMD ["./app"]

Explanation : After building the application, we are using a minimal and secure scratch base image for the runtime environment. This image does not include any OS or package manager, which helps minimize the attack surface of the container.

Remove unnecessary packages

Every package deployed in a Docker image enhances the container’s attack surface. If a package contains known security flaws, it might be exploited to obtain access to the underlying host system. We may lower the chance of security breaches by eliminating unneeded packages from the container’s attack surface.

It can also be reduce the size of image and it would include shorter deployment time, reduced storage costs, and better network transfer rates.

Here is a sample

# Use an official Golang runtime as a parent image at stage 1
FROM golang:1.17-alpine AS build

# Set the working directory to /app
WORKDIR /app

# Copying current directory contents into the container at /app
COPY . .

# Install any necessary dependencies
RUN apk add --no-cache git

# download the golang dependancies
RUN go mod download

# Build the app
RUN go build -o app .

# Use a minimal Alpine-based image as a parent image
FROM alpine:3.14

# Copy the binary from the previous stage
COPY --from=build /app/app /app/app

# Remove unwanted packages
RUN apk del git

# Set the working directory to /app
WORKDIR /app

# Run the binary
CMD ["./app"]

Explanation : The Dockerfile sets the parent image to the official Golang runtime image and installs any necessary dependencies. It then builds the application and stores it in a binary file called app. In the second stage it only copies what we want to run the application(the binary).

The benefit of multi-stage builds is that they can help reduce the size of your Docker images. By using multiple stages, you can eliminate any unnecessary files and packages that were required for building your application but are not needed at runtime. This can result in smaller images that are faster to download and deploy.

Use Docker Secrets

It allows us to store sensitive information securely and give it to your containers as environment variables or files. You may keep critical information distinct from your application code and configuration files with Docker Secrets, lowering the risk of exposure. The confidential data is encrypted in transit and at rest, and access is restricted to those who require it.

create secret in docker

docker secret create my_first_secret my_first_secret.txt

And then you can use os package to read the secrets

my_first_secret = os.GetEnv("MY_FIRST_SECRET")

or we could define the secrets section of the docker-compose.yml file.

version: '3.7'

services:
app:
build: .
secrets:
- db_user
- db_password
- db_host
ports:
- "8080:8080"

volumes:
mysecrets:
external: true

secrets:
db_user:
file: secrets/db_user.txt
db_password:
file: secrets/db_password.txt
db_host:
file: secrets/db_host.txt

There are several methods in which we can implement the secrets depending on the specific use case and requirements of the application.

With Docker-compose , Docker Swarm, External Key-Value store and Config management tools such as Ansible, Puppet.

See sample code : https://github.com/pcpratheesh/docker-with-secret-sample

Read more: https://docs.docker.com/engine/swarm/secrets/

Use container orchestration tools

The use of container orchestration tools may significantly improve the security of Docker deployments. These solutions simplify managing the operation of containerized applications over several hosts, resulting in increased security via features such as container isolation, load balancing, and automatic scaling.

Container orchestration tools like Kubernetes, Docker Swarm provide a centralized control plane for managing containers, which allows for easy implementation of security policies and best practices.

Here are some popular container orchestration tools

Keeping container Up to date

Keeping your container up to date is critical to its security. Security flaws in new versions of container images and applications can be found and patched. If you are running an out-of-date container, you are vulnerable to attackers who can exploit known flaws in your software.

To keep your container up to date, regularly check for and apply updates to your container images and the software running inside them. Use automated tools to monitor for new vulnerabilities and apply patches as needed.

Monitor the Containers

Monitoring your containers is an essential aspect of maintaining the security. Docker provides a built-in container monitoring tool called Docker Stats, which allows you to view various statistics.

Monitoring your containers regularly using various monitoring tools can help you detect potential security risks, vulnerabilities, or performance issues, and take appropriate action to mitigate them before they cause any harm.

Here are some popular container monitoring tools

Use container registries

Docker images should be stored in secure container registries like Docker Hub, Google Container Registry, or Amazon Elastic Container Registry (ECR).

When you use a registry, you can manage and control the images you use for your containers, making sure they are up-to-date, secure, and coming from a trusted source

Use container hardening techniques

Techniques like image signing, container immutability, and runtime protection can be used to harden containers against attacks.

One of the container hardening is to limit the number of network ports that are exposed to the container. By limiting the exposed ports to only those that are required for the container’s functionality, you can reduce the attack surface of your environment. You should also avoid running containers as the root user and to use container firewall to containers network traffic.

In conclusion, leveraging Docker security best practices is essential for maintaining a secure container environment. This includes utilizing encryption and authentication measures to protect data in transit as well as minimizing user access privileges to only those necessary for their roles within the organization.

Additionally, it is important to perform regular backups of container images along with their associated configurations so changes can quickly be reverted if necessary without losing vital information during an incident response scenario.

I hope this article helps. Thank you so much for reading. :)

Learn more :

--

--

PRATHEESH PC

Hey there! I'm a software developer and I'm absolutely in love with building things with technology.