Docker on the CLI
It is always useful to be able to do your work from the command line.
For some time now, Docker Desktop have been dulling the collective common knowledge about how to use docker
on the command line.
Let us address this knowledge gap - while avoiding the basics - with a Housekeeping section before we dive into Tools.
Housekeeping
For general housekeeping we need to check which images and containers exist, monitor their resource usage, and clean up any unnecessary or unused items.
A Good Tip
As quick aside I need to mention that a lot of housekeeping can be avoided with the option --rm
for instance when running an image:
% docker run --rm hello-world
The option --rm
effectively cleans up after itself.
Automatically remove the container and its associated anonymous volumes when it exits
Listing
% docker ps # alias for `docker container ls`
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
90217dfd7c27 hugomods/hugo:git "docker-entrypoint.s…" 7 days ago Up 7 days 127.0.0.1:1313->1313/tcp codereapergithubio-render-run-d1f5fc2bea43
% docker images # alias for `docker image ls`
REPOSITORY TAG IMAGE ID CREATED SIZE
hugomods/hugo git cd0d7c15f208 3 weeks ago 99.2MB
hello-world latest f1f77a0f96b7 5 weeks ago 5.2kB
Resource Usage
% docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
90217dfd7c27 codereapergithubio-render-run-d1f5fc2bea43 1.33% 47.91MiB / 1.914GiB 2.45% 2.05MB / 26.2MB 0B / 0B 40
% docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 4 1 192.9MB 101.9MB (52%)
Containers 1 1 0B 0B
Local Volumes 0 0 0B 0B
Build Cache 5 0 199B 199B
The option --no-stream
can be omitted to use the stats
subcommand as a top
command.
Disable streaming stats and only pull the first result
Cleaning Up
Note that following command will remove everything not currently in use without confirmation.
% docker system prune -af --volumes
Deleted Containers:
... skipped ...
Deleted Images:
... skipped ...
Deleted build cache objects:
... skipped ...
Total reclaimed space: 93.68MB
Tools
We will not be installing any tools, but instead we are going to run the tools using docker run
commands. That way we only need to maintain an alias
file or some similar.
CVE Scanning
It can be good to have options for scanning your images, so let us take a look at two scanning tool options.
Grype
% grype python:alpine
NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY
python 3.13.2 3.14.0 binary CVE-2024-3220 Unknown
Show alias
alias grype='
mkdir -p /tmp/grype && \
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /tmp/grype:/tmp \
-e GRYPE_DB_CACHE_DIR=/tmp/grype \
anchore/grype $@'
Trivy
% trivy python:alpine
2025-03-30T15:50:42Z INFO [vuln] Vulnerability scanning is enabled
2025-03-30T15:50:42Z INFO [secret] Secret scanning is enabled
2025-03-30T15:50:42Z INFO [secret] If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2025-03-30T15:50:42Z INFO [secret] Please see also https://trivy.dev/v0.61/docs/scanner/secret#recommendation for faster secret detection
2025-03-30T15:50:42Z INFO Detected OS family="alpine" version="3.21.3"
2025-03-30T15:50:42Z INFO [alpine] Detecting vulnerabilities... os_version="3.21" repository="3.21" pkg_num=28
2025-03-30T15:50:42Z INFO Number of language-specific files num=1
2025-03-30T15:50:42Z INFO [python-pkg] Detecting vulnerabilities...
Report Summary
┌──────────────────────────────────────────────────────────────────────┬────────────┬─────────────────┬─────────┐
│ Target │ Type │ Vulnerabilities │ Secrets │
├──────────────────────────────────────────────────────────────────────┼────────────┼─────────────────┼─────────┤
│ python:alpine (alpine 3.21.3) │ alpine │ 0 │ - │
├──────────────────────────────────────────────────────────────────────┼────────────┼─────────────────┼─────────┤
│ usr/local/lib/python3.13/site-packages/pip-24.3.1.dist-info/METADATA │ python-pkg │ 0 │ - │
└──────────────────────────────────────────────────────────────────────┴────────────┴─────────────────┴─────────┘
Legend:
- '-': Not scanned
- '0': Clean (no security findings detected)
Show alias
alias trivy='
mkdir -p /tmp/trivy && \
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /tmp/trivy:/root/.cache/ \
aquasec/trivy image $@'
Explore Image Contents
Dive
Allows you to view each layers command, directories and files which can be very helpful in a debugging situation. This is an interactive tool, so it is hard to show the output from dive
therefore I am borrowing their own introduction gif:
Show alias
alias dive='
docker run --rm -it \
-v /var/run/docker.sock:/var/run/docker.sock \
ghcr.io/wagoodman/dive $@'
Note you cannot view the contents of a file (yet - see #336).
SBOMs with Syft
Syft is an easy-to-use tool for generating Software Bill of Materials for container images (and filesystems).
% syft alpine
NAME VERSION TYPE
alpine-baselayout 3.6.8-r1 apk
alpine-baselayout-data 3.6.8-r1 apk
alpine-keys 2.5-r0 apk
alpine-release 3.21.3-r0 apk
apk-tools 2.14.6-r3 apk
busybox 1.37.0-r12 apk
busybox-binsh 1.37.0-r12 apk
ca-certificates-bundle 20241121-r1 apk
libcrypto3 3.3.3-r0 apk
libssl3 3.3.3-r0 apk
musl 1.2.5-r9 apk
musl-utils 1.2.5-r9 apk
scanelf 1.3.8-r1 apk
ssl_client 1.37.0-r12 apk
zlib 1.3.1-r2
Show alias
alias syft='docker run --rm ghcr.io/anchore/syft $@'
Reverse-engineer a Dockerfile with dfimage
Take a peak at how others have made their Dockerfile.
% dfimage aquasec/trivy
FROM alpine:latest
RUN /bin/sh -c apk --no-cache add ca-certificates git # buildkit
COPY trivy /usr/local/bin/trivy # buildkit
COPY contrib/*.tpl contrib/ # buildkit
ENTRYPOINT ["trivy"]
Show alias
alias dfimage='
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
ghcr.io/laniksj/dfimage $@'
Missing Out
You might be wondering, what are we missing out on by not using Docker Desktop and you are missing three things:
- Docker Scout
- Docker Cloud
- Docker Debug
Docker Scout
Scout can present you with an assessment score of an images vulnerabilities. This score is meaningless if you ignoring the “high number, bad” and “low number, good” arguments. You still need evaluate the risks of your application, its use-cases and risk profile.
You have tools above to generate a list of software and versions used in an image or a list of vulnerabilities to evaluate.
Docker Cloud
Docker Build Cloud and Testcontainers Cloud are both … ridiculous. They are marketed as time-saving tools and they are both the ability to do docker build
and docker run
, but in the cloud.
Your builds and tests should not take long, and the solution is not to send your code to a third-party and have them run it.
If - and there should not be a need for it - you really need to offload building and testing from the developers machine, use your own build server, or a free one from GitHub.
Docker Debug
This is the ability to have a shell on a distroless image. This could be really useful.
The dive
tool mentioned above should be enough, especially once we have the ability to view the contents of a file.