DEV Community

Cover image for The One Thing You Should Do After Building Best-Practice Docker Image (in 3 minutes)
Tomoya Amachi
Tomoya Amachi

Posted on • Originally published at Medium

The One Thing You Should Do After Building Best-Practice Docker Image (in 3 minutes)

Overview

Today, many companies tried to use Docker. This article is for wrote/writing best-practice Dockerfiles.

I created a tool analyzes your Dockerfile via the built image in 3 minutes.

Dockle - Container Image Linter for Security, Helping build the Best-Practice Docker Image, Easy to start

Dockle is able to check deeply. (file permissions, credential files...) So, Dockle the best tool to check important rules, especially for security.

(I'm also the main committer of Vuls and Trivy. These are famous vulnerability scanners.)

It's NOT a Dockerfile Linter (like a hadolint).

It's able to check security risks on a container base image too. Dockerfile Linter never does it.

I hope you star it!

How to use

Homebrew (Mac / Linux)

$ export DOCKER_CONTENT_TRUST=1
$ docker build -t test-image:v1 .
$ brew install goodwithtech/dockle/dockle
$ dockle test-image:v1

Linux

$ export DOCKER_CONTENT_TRUST=1
$ docker build -t test-image:v1 .
$ VERSION=$(
 curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \
 grep '"tag_name":' | \
 sed -E 's/.*"v([^"]+)".*/\1/' \
) && curl -L -o dockle.tar.gz https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.tar.gz
$ tar zxvf dockle.tar.gz
$ ./dockle test-image:v1

Windows

$ export DOCKER_CONTENT_TRUST=1
$ docker build -t test-image:v1 .
$ VERSION=$(
 curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \
 grep '"tag_name":' | \
 sed -E 's/.*"v([^"]+)".*/\1/' \
) && curl -L -o dockle.zip https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Windows-64bit.zip
$ unzip dockle.zip && rm dockle.zip
$ ./dockle.exe test-image:v1

via Docker

$ VERSION=$(
 curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \
 grep '"tag_name":' | \
 sed -E 's/.*"v([^"]+)".*/\1/' \
) && docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
 goodwithtech/dockle:v${VERSION} test-image:v1

You only need -v /var/run/docker.sock:/var/run/docker.sock when you'd like to scan the image on your host machine.

Results

PASS    - CIS-DI-0001: Create a user for the container
PASS    - CIS-DI-0005: Enable Content trust for Docker
PASS    - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
PASS    - CIS-DI-0007: Do not use update instructions alone in the Dockerfile
PASS    - CIS-DI-0008: Remove setuid and setgid permissions in the images
PASS    - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
PASS    - CIS-DI-0010: Do not store secrets in ENVIRONMENT variables
PASS    - CIS-DI-0010: Do not store secret files
PASS    - DKL-DI-0001: Avoid sudo command
PASS    - DKL-DI-0002: Avoid sensitive directory mounting
PASS    - DKL-DI-0003: Avoid apt-get/apk/dist-upgrade
PASS    - DKL-DI-0004: Use apk add with --no-cache
PASS    - DKL-DI-0005: Clear apt-get caches
PASS    - DKL-DI-0006: Avoid latest tag
PASS    - DKL-LI-0001: Avoid empty password
PASS    - DKL-LI-0002: Be unique UID
PASS    - DKL-LI-0002: Be unique GROUP

This tool checks CIS Benchmarks and Best practices for writing Dockerfiles
.

Dockle shows short messages suggestions for improvement when there are problems.

WARN    - CIS-DI-0001: Create a user for the container
        * Last user should not be root
PASS    - CIS-DI-0005: Enable Content trust for Docker
WARN    - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
        * not found HEALTHCHECK statement
PASS    - CIS-DI-0007: Do not use update instructions alone in the Dockerfile
INFO    - CIS-DI-0008: Remove setuid and setgid permissions in the images
        * Found setuid file: usr/lib/openssh/ssh-keysign urwxr-xr-x
FATAL   - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
        * Use COPY : /bin/sh -c #(nop) ADD file:81c0a803075715d1a6b4f75a29f8a01b21cc170cfc1bff6702317d1be2fe71a3 in /app/credentials.json
FATAL   - CIS-DI-0010: Do not store secrets in ENVIRONMENT variables
        * Suspicious ENV key found : MYSQL_PASSWD
FATAL   - CIS-DI-0010: Do not store secret files
        * Suspicious filename found : app/credentials.json
PASS    - DKL-DI-0001: Avoid sudo command
FATAL   - DKL-DI-0002: Avoid sensitive directory mounting
        * Avoid mounting sensitive dirs : /usr
PASS    - DKL-DI-0003: Avoid apt-get/apk/dist-upgrade
PASS    - DKL-DI-0004: Use apk add with --no-cache
FATAL   - DKL-DI-0005: Clear apt-get caches
        * Use 'rm -rf /var/lib/apt/lists' after 'apt-get install' : /bin/sh -c apt-get update && apt-get install -y git
PASS    - DKL-DI-0006: Avoid latest tag
FATAL   - DKL-LI-0001: Avoid empty password
        * No password user found! username : nopasswd
PASS    - DKL-LI-0002: Be unique UID
PASS    - DKL-LI-0002: Be unique GROUP

You can check details to searching analysys codes(CIS-DI-0001...) on README.

You don't mind if your image doesn't pass checkpoints.
It's one of an indicator.

Sometimes you have to run as root.

Sometimes CLI tool doesn't need HEALTHCHECK.

Sometimes use ADD statement when you'd like to add tar files.

I hope this is reminder that really you'd like to do so.

You can be specified to ignore rules to give --ignore, -i option or create .dockleignore.

$ dockle -i CIS-DI-0001 -i CIS-DI-0006 [IMAGE_NAME]
# run as root
CIS-DI-0001
# don't use HEALTHCHECK
CIS-DI-0006
# use latest tag
DKL-DI-0006

Let's do it again.

IGNORE  - CIS-DI-0001: Create a user for the container
INFO    - CIS-DI-0005: Enable Content trust for Docker
        * export DOCKER_CONTENT_TRUST=1 before docker pull/build
IGNORE  - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
PASS    - CIS-DI-0007: Do not use update instructions alone in the Dockerfile
INFO    - CIS-DI-0008: Remove setuid and setgid permissions in the images
        * Found setuid file: usr/lib/openssh/ssh-keysign urwxr-xr-x
IGNORE  - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
FATAL   - CIS-DI-0010: Do not store secrets in ENVIRONMENT variables
        * Suspicious ENV key found : MYSQL_PASSWD
FATAL   - CIS-DI-0010: Do not store secret files
        * Suspicious filename found : app/credentials.json
PASS    - DKL-DI-0001: Avoid sudo command
FATAL   - DKL-DI-0002: Avoid sensitive directory mounting
        * Avoid mounting sensitive dirs : /usr
PASS    - DKL-DI-0003: Avoid apt-get/apk/dist-upgrade
PASS    - DKL-DI-0004: Use apk add with --no-cache
FATAL   - DKL-DI-0005: Clear apt-get caches
        * Use 'rm -rf /var/lib/apt/lists' after 'apt-get install' : /bin/sh -c apt-get update && apt-get install -y git
PASS    - DKL-DI-0006: Avoid latest tag
FATAL   - DKL-LI-0001: Avoid empty password
        * No password user found! username : nopasswd
PASS    - DKL-LI-0002: Be unique UID
PASS    - DKL-LI-0002: Be unique GROUP

Closing

Dockle is NOT a Dockerfile Linter, but a Docker Image Linter.

Dockle can check deeply. (file permissions, credential files...) So, Dockle is able to check important rules than others, especially for security.

And Dockle is able to analyze an image created by stdin, too. You could use it in many places.

docker build -<<EOF
FROM busybox
RUN echo "hello world"
EOF

I hope you like it!

Thanks!!

Oldest comments (1)

Collapse
 
derek profile image
derek

πŸ‘πŸ½ very cool tool! Thank you for creating it!

I 😍the DX and the name dockle

🍻