« Previous 1 2 3 Next »
Best practices when working with Docker images
Shipshape
Security Scans Are Important
Your code has been scanned for security vulnerabilities, so you are confident your container is secure, right? Wrong! Scanning your code is not enough: You need to scan your image, too. Many services and applications help you with that, such as Docker Bench for Security [1] or Trivy [2] (see the article on Trivy in this issue). If you use Docker Desktop, the easiest option is to use the docker scan
command (Figure 2). (You need to be logged in to Docker Hub.) Also, many external services such as the Amazon Elastic Container Registry (ECR) offer vulnerability scanning. You need to make it a part of your automated testing.
Image vulnerability scans are so easy to set up it's hard to present any excuse for not using them. Just to give an example, configure a sample scanning setup with Anchore, an open source project comprising two parts. The first component is the Anchore engine responsible, among other things, for performing the scan. The other component is the Anchore CLI or the command used to interact with the Anchore engine.
Install the Anchore engine with the commands:
curl -O https://engine.anchore.io/docs/quickstart/docker-compose.yaml docker-compose up -d
The first line downloads a Docker Compose manifest, and the second line starts the engine with Docker Compose. Depending on your install, instead of docker-compose
, you might need to use docker compose
. If you don't have the Compose plugin installed, you need to install the docker-compose-plugin
package.
Next, install the Anchore CLI, which is a Python package that can be installed easily with PIP:
pip install anchorecli
Further interaction with the Anchore engine happens via Docker. For example, to add an image, use the command:
docker compose exec api anchore-cli image add docker.io/library/alpine:latest
Scanning the added image is as simple as:
docker compose exec api anchore-cli image vuln docker.io/library/alpine:latest all
Listing 4 shows the results.
Listing 4
Results of Image Scan
$ docker compose exec api anchore-cli image vuln docker.io/library/alpine:latest all Vulnerability ID Package Severity Fix CVE Refs Vulnerability URL Type Feed Group Package Path CVE-2022-28391 busybox-1.35.0-r29 High 1.35.0-r7 CVE-2022-28391 http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-28391 APKG alpine:3.17 pkgdb CVE-2022-28391 busybox-binsh-1.35.0-r29 High 1.35.0-r7 CVE-2022-28391 http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-28391 APKG alpine:3.17 pkgdb CVE-2022-28391 ssl_client-1.35.0-r29 High 1.35.0-r7 CVE-2022-28391 http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-28391 APKG alpine:3.17 pkgdb
Docker Cache
Because Docker places layers one on top of another, if one of the layers changes, all those on top of it change, too, so it makes sense to place the ones you plan to change frequently further down your Dockerfile. In this way Docker will cache the layers that don't need to be rebuilt, resulting in shorter build times. You can also use Docker's modern build engine BuildKit, which further improves build time with enhanced concurrency and better use of caching.
Decouple Apps from Their Configuration
No matter how you plan to run your images, it's important to separate the app from its configuration. How the configuration itself will be managed depends on the way you deploy your app. For example, if you decide to use Kubernetes, you will probably use ConfigMaps for the configuration and Secrets combined with external encryption services for sensitive data such as passwords and other credentials.
In this way, you use the same image in all phases, from testing to production. As a bonus, you don't need to rebuild the image when your configuration changes. However, a good practice requires that you don't update the config while your app is running: When you have a new configuration, you need to spin up a new container.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)