How to make your Docker Containers more Secure in 2024

Yves Soete
5 min readMar 4, 2024

04-MAR-2024- Written by Yves Soete —Blacksight LLC visit us to use our free website security scanner on scanner.blacksight.io

Get notified when new articles drop — visit blacksight.io/blog to subscribe

America runs on Dunkin, we all heard it, but in our universe, we can basically say:

The world runs on Docker, in large part.

Hardening your Docker builds is a line of defense many companies oversee and take other peoples’ practices for granted, with disastrous results in some cases. A container from the Docker Registry that has the label Official on, means it’s secure, right? Is it really, when you push it to production?

Many build on top of official containers, adding all kinds of insecure practices and assume their build is secure, which in many cases it isn’t.

Here’s a checklist that we at blacksight.io advise everybody who builds their containers and puts them in production to use and cross check:

1. Override the Dockerfiles port settings

A lot of times developers will locally work with containers and might be able to push them into the Container Registry to be used in deployments. Many times for debugging purposes the Developer will open certain ports by setting them into the Dockerfile. A way to prevent this is to define the ports that are allowed in normal situations with the -p parameter, any other port — even the ones defined in the Dockerfile — will be blocked.

2. Use minimal Docker Image sizes

Instead of using the default Ubuntu or other distro containers use the tiny Alpine or other slimmed down images.

For example: if you go for the official Node.js container, pick the alpine tag.

You reduce the attack vector by limiting the available programs in your container, and on top of that, your build time process might benefit too if you didn’t implement correct caching during container builds (mostly don’t, right?).

3. Prevent write access to your Containers

Most of us live in an immutable infrastructure world without data persistence within containers, there is little reason why containers should write anything to their container filesystem, and if you do, you should really look at why you’re doing it. We advise you to run your containers ( — read-only flag) in strictly read-only mode. An attacker who exploited your application will find it very difficult to do anything else this way.

If your application really can’t run without writing something you can use the — tmpfs flag and you can, add multiples of them, the benefit is that it doesn’t write back to a host volume. If you use docker-compose this is where to define it.

4. Have a correct .dockerignore file

Make sure certain local files don’t end up in containers, we have found secrets written into files in containers — by accident — that shouldn’t be there at all. Having a correct and updated .dockerignore file that excludes certain files and directories (where config files are stored) safeguards this.

5. Split up public facing applications and back end applications

Instead of having 1 network environment that contains both front end and back end containers, split them up in separate networks with a very restricted network access control, including database access.

6. Rebuild containers with an up to date Linux kernel and applications

Fine, you have your application running and it didn’t need any updates in the last 2 years. Honestly, I think it did, you probably need to rebuild it with the latest patches and an updated kernel, do this frequently, don’t deploy and forget containers. Please.

7. Do not expose your docker.sock

Double check that your docker.sock is not exposed, even if it’s blocked for write access.

docker inspect — format=’{{.HostConfig.Binds}}’ [container id]

8. Run Docker in rootless mode, prevent use of privileged

It’s not standard but possible to run the daemon as a non-root user called the Rootless-mode so you run them in a user namespace by default. We usually use the unprivileged user nobody (-u 1001 nobody)

see https://get.docker.com/rootless

Do not use the — privileged flag, redesign when people are using this flag and add the no-new-privileges option so processes cannot gain new privileges during execution. If you want to add an extra extra security layer add the — cap-drop flag and add only the requirement ones (optional).

docker inspect --format=’{{.HostConfig.Privileged}}’ [container_id]

9. Limit resources available to your Containers

This will limit DOS attacks, limit memory, number of restarts, amount of swap memory, maximum cpu resources, number of file descriptors and processes.

Remember: by default docker will take as much as it can without you setting specific limits.

10. Setup SELinux in your containers

Yup, it’s possible and advised. We literally get NSA level security if we add this to our Containers.

11. Remove build dependencies

Even in small alpine containers, in many cases, we have found project dependency files. Make sure you remove them like package.json and pom.xml they are not needed to run the application.

Same for JDK’s and Maven programs found in running containers, they aren’t needed and you reduce the attack vector by removing them.

We advise using a Build stage and a Runtime Stage aka Multi-Stage builds which removes build files in the runtime container.

12. Setup a container security scanner in your build pipeline

If you do GitOps implement a container security scanner in your build pipeline before it ends up in your Private Container Registry, but scan your registry too :-)

13. Setup correct logging level

As SIEM experts we couldn’t resist to keep this as last but not least, make sure you set your containers to the — log-level info and configure and setup correct logging and alerting for it.

We hope this list helps you to secure your Docker Container setup and keep you safe!

Bonus: Use our free website vulnerability scanner at scanner.blacksight.io

Liked this article? Get notified when new articles drop! visit blacksight.io/blog to subscribe

--

--

Yves Soete

Yves is the Principal DevSecOps Engineer at blacksight.io, a cyber security company with a strong focus on blackbox penetration testing