Docker Hub is a blessing and a curse at times. It’s a great way to share Docker images to the public, but it can be used by hackers to sneak code into environments with malicious intent. Recently, a hacker uploaded images into Docker Hub that were downloaded over 5,000,000 times. The intent was to turn the victims Docker environment into a crypto-miner. He made off with over $90,ooo worth in cryptocurrency. This situation could have easily been avoid though by simply not using the images, rather using images from official repositories on Docker hub, which is one of the surest and simplest ways to improve security. There are also a number of simple practices Docker users can adopt that will help improve security in other ways. Here are a few.
Containers should only have the essentials needed to run the intended application. It’s tempting on the part of developers to want to install utilities and tools in the container such as editors, networking tools, and other such things. These create unnecessary security risks and can make a container image unnecessarily large.
There are many base images to choose from on Docker hub including many based on popular distros like Debian, CentOS, and Ubuntu. These base images, while they have a rich package management system, typically are much larger than more minimalist base images like Alpine. Many popular platforms like NodeJS and PHP will provide image that support a heftier base image as well as a minimalist image. If your app does not require something that the heavier images provide, prefer the more minimalist images. This will help keep the size of the images and containers to a minimum.
Use multi-stage builds if you compile code in a container
Often, the need to compile code into a binary is necessary for an application. For this, Docker created multi-stage builds. This typically requires many supporting libraries and code to be installed in the container prior to the build but isn’t necessary to run an app. The first stage of the build can be used to install all the build tools and compile the code, then the binaries and packages can be copied from the build image into an image intended to run the compiled binaries. This helps make the final image smaller and more secure.
The Single Responsibility Principle for software design also applies to Docker images as well. An image should only contain a single piece of functionality for an application. For instances, WordPress uses a MySQL database to store data. In this case, the WordPress application would use a separate image from MySQL.
Docker Hub contains many images that are maintained by the developers of platforms, such as NodeJS, Java, PHP, and .NET. These repositories are typically maintained by the software developers who created the platform (ie. Microsoft maintains the .NET Core images) While it is possible to build these for oneself, using the official images will save time and headaches downstream where software maintenance is concerned. It also improves the security by using a more trusted source for software.
Look at the Dockerfiles
If you need to use an image on Docker hub that isn’t in an official repository, look for the Dockerfile for the unofficial image. Having the Dockerfile is good for two reasons — one it lets you see what was put into the image and two it lets you build the image yourself instead of using the unofficial image.
Containers are inherently secure; however, this does not mean that one should be lacks about an application’s security best practices. For instance, an application should be run with a user with the fewest permissions possible to make the application function – this is true for containers. One should take time to consider both container security best practices and application security best practices when building container images.
Docker can run a container in a privileged mode either using the –privileged flag or using –cap-add . These modes however are intended only for special cases and should be avoided. It should never be used to solve permissions problems on an application.
Use image signing
Docker images can be signed using certificates in the way the code is signed. Signed images can thereby be verified against certificates to ensure that the contents of the image has not been modified between the publisher and the consumer of the image. This helps improve security by creating trusts between image consumers and publishers.
As with any application, it’s always best to place an application behind a security-hardened system that can scan traffic coming into an application for malicious content. Likewise, gateways and firewalls provide a plethora of other security functionality that is typically not baked into an application. Using these helps enhance the overall security of a container environment and containers running in that environment.
Data such as database files, static content, logs, and so on should not be stored in a container, rather should be stored outside of a container. Docker provides a special mechanism for doing just this with volumes. Volumes can be mounted inside of container so that data can be written to the volume instead of the container’s filesystem. This way, whenever the container is removed, the data is not lost.
Containers are supposed to be immutable, which means that once the container is running, it should not be modified. Instead of patching containers while they are running, patch the image that was used to create the container and redeploy it. This will better ensure that the image is getting the latest patches.
This list is by no means exhaustive, but adopting these practices can certainly help improve security in Docker images and containers out of the gate. Happy Dockering!