Automatically reduce Docker container size using DockerSlim
Jan 12, 2022
Prerequisites to complete this example
- Basic knowledge of Linux commands and a terminal
- Docker Desktop is installed on your host machine.
- A text editor or browser to view JSON files
For video instructions click here: Automatically minify container images using DockerSlim
Many tech stacks struggle with large Docker container sizes, and common web frameworks are no exception. Python’s Flask microframework is one of the world’s most popular open source set-ups for RESTful web services and APIs. However, common Python-Flask Docker images can weigh in at close to 1 GB in size.
Slimming an application built with Python-Flask using DockerSlim is easy, automatic, and quick. Here’s a step-by-step tutorial using DockerSlim’s build functionality.
1. Download and test DockerSlim
Download DockerSlim from here: https://dockersl.im/
We developed this example on macOS.
Create a folder and copy the files from the DockerSlim download into the folder. We’ll create one called
. ├── DockerSlim | ├── docker-slim | ├── docker-slim-sensor
If you plan to use DockerSlim frequently, we recommend you add your folder path to the /etc/paths file or otherwise add it to your PATH so you can run the
docker-slim command from anywhere.
# /etc/paths ## some paths /<pathtomydockerslimfolder>/DockerSlim
Restart terminal for the changes to be active.
Otherwise, you’ll need to run your docker-slim commands from the directory where you extracted them. You can type ./docker-slim help to run DockerSlim in this case. We’ll generally assume that you’ve added the the docker-slim binaries to your path.
Run DockerSlim to check if it’s working by typing
docker-slim help (or
./docker-slim help if you did not add it to your PATH above).
$ docker-slim help
NAME: docker-slim - optimize and secure your Docker containers! USAGE: docker-slim [global options] command [command options] [arguments...] VERSION: darwin|Transformer|1.35.0|6eca3ad331720c31a7e398ffaf002a896dc9a70a|2021-04-15_02:48:03AM COMMANDS: build, b Analyzes, profiles and optimizes your container image auto-generating Seccomp and AppArmor security profiles containerize, c Containerize the target artifacts convert, k Convert container image edit, e Edit container image help, h Show help info lint, l Analyzes container instructions in Dockerfiles probe, prb Probe target profile, p Collects fat image information and generates a fat container report run, r Run one or more containers server, s Run as an HTTP server update, u Updates docker-slim version, v Shows docker-slim and docker version information xray, x Shows what's inside of your container image and reverse engineers its Dockerfile GLOBAL OPTIONS: --report value command report location (enabled by default; set it to "off" to disable it) (default: "slim.report.json") --check-version check if the current version is outdated [$DSLIM_CHECK_VERSION] --debug enable debug logs --verbose enable info logs --log-level value set the logging level ('debug', 'info', 'warn' (default), 'error', 'fatal', 'panic') (default: "warn") --log value log file to store logs --log-format value set the format used by logs ('text' (default), or 'json') (default: "text") --tls use TLS --tls-verify verify TLS --tls-cert-path value path to TLS cert files --host value Docker host address --state-path value DockerSlim state base path --in-container DockerSlim is running in a container --archive-state value archive DockerSlim state to the selected Docker volume (default volume - docker-slim-state). By default, enabled when DockerSlim is running in a container (disabled otherwise). Set it to "off" to disable explicitly. --no-color disable color output --version, -v print the version
DockerSlim has an excellent menu-driven command line. To try that, simply run docker-slim with no additional arguments. You can get to the help menu by typing
help in the command line at the interactive prompt.
2. Prepping a Container to Slim
We’ll use the DockerSlim
build command for this exercise and pull one of the DockerSlim example containers. The container houses a simple Python/Flask service. You can pull the container from the dslimexamples repo on DockerHub.
$ docker pull dslimexamples/server-python2-flask-standard
After the pull command completes, check to see that the image is loaded using the
docker images command.
Using default tag: latest latest: Pulling from dslimexamples/server-python2-flask-standard 741437d97401: Pull complete 34d8874714d7: Pull complete 0a108aa26679: Pull complete 7f0334c36886: Pull complete 49ea0d2b5c48: Pull complete 2f697d8eb8c9: Pull complete 19e57c082018: Pull complete 62a638f5d7ed: Pull complete 5bceaf33fb03: Pull complete 72d2aabda994: Pull complete 9bb059401bdd: Pull complete d3940358526e: Pull complete Digest: sha256:0b1ba4d668a86479b927ff522bab220a27ece1c40a1d1dc89bc15b81a44b7f8b Status: Downloaded newer image for dslimexamples/server-python2-flask-standard:latest docker.io/dslimexamples/server-python2-flask-standard:latest
3. Verifying the output container
A vital step when minifying a container is verifying that the output container from DockerSlim functions correctly. We will use curl to perform a simple before and after functional verification on the example container.
To perform the simple validation test, we first need to run the example container. Run the following command in the terminal window.
$ docker run -it --rm -p 1300:1300 --name dslimflask dslimexamples/server-python2-flask-standard
* Serving Flask app "server" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: on * Running on http://0.0.0.0:1300/ (Press CTRL+C to quit)
This command starts the Python/Flask container interactively (see the
-it flags) and attaches the container's open port to
Open a second terminal window and use CURL to send a request to the running container. (Note: You will need CURL installed on your local machine and available via your PATH.)
$ curl http://127.0.0.1:1300
This curl command performs an HTTP GET on the root method of the Python/Flask REST service running in the container we just started. The Python/Flask service will respond by returning a JSON object with a “success” status. The service also logs an access record (see the terminal window in the background of the following image) to the terminal with IP Address, Date, Time, method (GET /HTTP 1.1), and 200 success status code.
This sequence (successfully) performs a basic web service test to verify that the example container functions as expected.
Press CTRL+C in the window where the Python/Flask server container runs to exit the service to stop the container.
4. Building the container from DockerSlim
Next, we will minify the container using the DockerSlim build command. The DockerSlim build command takes a container image reference as input. The input container image must be available on the local Docker Desktop in order for DockerSlim to be able to access it.
In the terminal window where you previously started the Python/Flask container, enter the following.
$ docker-slim build --copy-meta-artifacts . dslimexamples/server-python2-flask-standard
--copy-meta-artifacts . argument will copy several files produced by DockerSlim into the current working directory. You can change
. to any path you choose.
a. DockerSlim Build Steps and Output
As you can see here, the output from the DockerSlim build command is fairly robust.
But what’s actually happening?
The minification process includes performing a combination of static and dynamic analysis of the input container image to determine which files, libraries, executables, etc., are required for the regular operation of the container.
DockerSlim runs the input container using the Docker engine. While the container is running, DockerSlim attempts to understand how the application(s) present in the container function by using a set of built-in probes to inspect various facets of the container.
Here are some of the more pertinent stages of the minification process:
DockerSlim detects the open ports available for the input container and attempts to execute a sequence of web requests and web crawler actions intended to exercise the underlying web service running in the container. It then observes the application dependencies, files, and executables necessary for the application to function in response to probes, recording these dependencies and using this knowledge to compose the output container.
DockerSlim does not modify the original input container. The output of the build command is a new container image produced by DockerSlim (renamed by adding ‘.slim’ to the original container image name) constructed to include only the files necessary for the container's functional operation. This new container contains a subset of the input container’s files. DockerSlim does not inject any new files into the output container. However, DockerSlim flattens the output container layer structure.
Note: DockerSlim has several other built-in methods to test and stimulate a containerized application. DockerSlim also includes several advanced commands and options to perform minification for a wide variety of Linux-based containerized applications.
You can find details about DockerSlim advanced build commands here:
b. Verifying our results from the slimmed container
When DockerSlim finishes, use
docker images to see the new slim container produced by DockerSlim. It can be found with the
.slim extension to the original container name.
Note: The .slim image is 28MB vs 932MB (33X smaller)!
We will verify the ‘.slim’ version of the container using the same curl command we used previously. Run the .slim container by executing the following command in the terminal.
docker run -it --rm -p 1300:1300 --name dslimflask dslimexamples/server-python2-flask-standard.slim
The Python/Flask service starts normally and produces outputs identical to that of the input container when we ran it previously.
Just like before, we can open a second terminal window to do our CURL test on the running, and now slimmed, container.
The web service returns a success response and logs the access in the terminal as before.
In this case, DockerSlim has produced a much smaller, minified output container that functions equivalently to the original input container.
And just like that, you have a 28 MB container that does all the same things as your previous image.
Looking for similar examples to play around with? Check out a wide variety of different containerized applications in the DockerSlim examples Github, and follow our Twitch Live Stream, where we review a new container type each week.