Github url

docker-slim

by docker-slim

docker-slim /docker-slim

DockerSlim (docker-slim): Don't change anything in your Docker container image and minify it by up t...

8.8K Stars 306 Forks Last release: 4 months ago (1.29.0) Other 470 Commits 35 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

DSLIM1

FollowGitter chatDiscord chat

Minify and Secure Docker containers (free and open source!)

Don't change anything in your Docker container image and minify it by up to 30x making it secure too!

Keep doing what you are doing. No need to change anything. Use the base image you want. Use the package manager you want. Don't worry about hand optimizing your Dockerfile. You shouldn't have to throw away your tools and your workflow to have small container images.

Don't worry about manually creating Seccomp and AppArmor security profiles. You shouldn't have to become an expert in Linux syscalls, Seccomp and AppArmor to have secure containers. Even if you do know enough about it wasting time reverse engineering your application behavior can be time-consuming.

docker-slim

will optimize and secure your containers by understanding your application and what it needs using various analysis techniques. It will throw away what you don't need, reducing the attack surface of your container. What if you need some of those extra things to debug your container? You can use dedicated debugging side-car containers for that (more details below).

docker-slim

has been used with Node.js, Python, Ruby, Java, Golang, Rust, Elixir and PHP (some app types) running on Ubuntu, Debian, CentOS, Alpine and even Distroless.

Note that some application stacks do require advanced container probing to make sure that all dynamically loaded components are detected. See the

--http-probe\*

flags for more details to know how you can define custom probe commands. In some cases you might also need to use the

--include-path

flag to make sure everything your application needs is included (e.g.,

ubuntu.com

python SPA app container image example where the client side template files are explicitly included).

It's also a good idea to use your app/environment tests when you run

docker-slim

. See the

--continue-after

flag for more details about integrating your tests with the temporary container

docker-slim

creates when it's doing its dynamic analysis. Running tests in the target container is also an option, but it does require you to specify a custom ENTRYPOINT/CMD with a custom wrapper to start your app and to execute your tests.

Interactive CLI prompt screencast:

asciicast

Watch this screencast to see how an application image is minified by more than 30x.

asciicast

When

docker-slim

runs it gives you an opportunity to interact with the temporary container it creates. By default, it will pause and wait for your input before it continues its execution. You can change this behavior using the

--continue-after

flag.

If your application exposes any web interfaces (e.g., when you have a web server or an HTTP API), you'll see the port numbers on the host machine you will need to use to interact with your application (look for the

port.list

and

target.port.info

messages on the screen). For example, in the screencast above you'll see that the internal application port 8000 is mapped to port 32911 on your host.

Note that

docker-slim

will interact with your application for you if you enable HTTP probing with the

--http-probe

flag or other related HTTP probe flags. Some web applications built with scripting languages like Python or Ruby require service interactions to load everything in the application. Enable HTTP probing unless it gets in your way.

Minification Examples

Node.js application images:

  • from ubuntu:14.04 - 432MB => 14MB (minified by 30.85X)
  • from debian:jessie - 406MB => 25.1MB (minified by 16.21X)
  • from node:alpine - 66.7MB => 34.7MB (minified by 1.92X)
  • from node:distroless - 72.7MB => 39.7MB (minified by 1.83X)

Python application images:

  • from ubuntu:14.04 - 438MB => 16.8MB (minified by 25.99X)
  • from python:2.7-alpine - 84.3MB => 23.1MB (minified by 3.65X)
  • from python:2.7.15 - 916MB => 27.5MB (minified by 33.29X)
  • from centos:7 - 647MB => 23MB (minified by 28.57X)
  • from centos/python-27-centos7 - 700MB => 24MB (minified by 29.01X)
  • from python2.7:distroless - 60.7MB => 18.3MB (minified by 3.32X)

Ruby application images:

  • from ubuntu:14.04 - 433MB => 13.8MB (minified by 31.31X)
  • from ruby:2.2-alpine - 319MB => 27MB (minified by 11.88X)
  • from ruby:2.5.3 - 978MB => 30MB (minified by 32.74X)

Golang application images:

  • from golang:latest - 700MB => 1.56MB (minified by 448.76X)
  • from ubuntu:14.04 - 531MB => 1.87MB (minified by 284.10X)
  • from golang:alpine - 258MB => 1.56MB (minified by 165.61X)
  • from centos:7 - 615MB => 1.87MB (minified by 329.14X)

Rust application images:

  • from rust:1.31 - 2GB => 14MB (minified by 147.16X)

JAVA application images:

  • from ubuntu:14.04 - 743.6 MB => 100.3 MB

PHP application images:

  • from php:7.0-cli - 368MB => 26.6MB (minified by 13.85X)

Haskell application images:

  • (Scotty service) from haskell:8 - 2.09GB => 16.6MB (minified by 125.32X)
  • (Scotty service) from haskell:7 - 1.5GB => 21MB (minified by 71X)

Elixir application images:

  • (Phoenix service) from elixir:1.6 - 1.1 GB => 37 MB (minified by 29.25X)

Note: The examples are in a separate repository: https://github.com/docker-slim/examples


Latest version: 1.29.0 (3/18/2020)

This is a UX release that introduces an interactive mode to make it easier to run

docker-slim

when you don't know all available flags. Usage

<tab></tab>

and

<space></space>

buttons to navigate the interactive prompt and

<enter></enter>

to execute the selected command. The

--target

option for the

build

,

xray

and

profile

commands is now used to select the target container image you want to process. For more info about the latest release see the [

CHANGELOG

](https://github.com/docker-slim/docker-slim/blob/master/CHANGELOG.md). For more info about the interactive prompt see [

go-prompt

](https://github.com/c-bata/go-prompt).

INSTALLATION

  1. Download the zip package for your platform.
  1. Unzip the package.

  2. Add the location where you unzipped the package to your PATH environment variable (optional).

If the directory where you extracted the binaries is not in your PATH then you'll need to run your

docker-slim

commands from that directory.

To use the Docker image distribution just start using the

dslim/docker-slim

container image.

The OS-specific installers for

docker-slim

will be available soon (there's already a couple of community

Homebrew

formulas for Mac and Linux, but they need to be enhanced to work properly).

BASIC USAGE INFO

docker-slim [global flags] [lint|xray|build|profile|update|version|help] [command-specific flags] <image_id_or_name></image_id_or_name>

COMMANDS

  • lint
    • analyze container instructions in Dockerfiles (or Docker images)
  • xray
    • do static analysis for the target container image (including 'reverse engineering' the Dockerfile for the image)
  • profile
    • do
      xray
      plus dynamic container analysis
  • build
    • do
      profile
      plus an ability to create a new optimized image along with the security profiles
  • version
    • show the version information
  • update
    • update
      docker-slim
      to the latest version
  • help
    • show the available commands and global flags

Example:

docker-slim build my/sample-app

See the

USAGE DETAILS

section for more details. You can also get additional information about the parameters running

docker-slim

.

Run

docker-slim help

to get a high level overview of the available commands. Run a

docker-slim

command without any parameters and you'll get more information about that command (e.g.,

docker-slim build

).

If you run

docker-slim

without any parameters you'll get an interactive prompt that will provide suggestions about the available commands and flags.

Tabs

are used to show the available options, to autocomplete the parameters and to navigate the option menu (which you can also do with Up and Down arrows).

Spaces

are used to move to the next parameter and

Enter

is used to run the command. For more info about the interactive prompt see [

go-prompt

](https://github.com/c-bata/go-prompt).

USAGE DETAILS

docker-slim [global options] command [command options] <target image id or name></target>

Commands:

  • lint
    • Lint the target Dockerfile (or image)
  • xray
    • Collects fat image information and reverse engineers its Dockerfile
  • build
    • Collect fat image information and build a slim image from it
  • profile
    • Collect fat image information and generate a fat container report
  • containerize
    • Containerize the target artifacts
  • version
    • Show docker-slim and docker version information
  • update
    • Update docker-slim
  • help
    • Show help info

Global options:

  • ```
  • -report
    - command report location (target location where to save the executed command results; 
    slim.report.json
    by default; set it to 
    off ``` to disable)
  • ```
  • -check-version ```
    • check if the current version is outdate
  • ```
  • -version ```
    • print the version
  • ```
  • -debug ```
    • enable debug logs
  • ```
  • -verbose ```
    • enable info logs
  • ```
  • -log-level ```
    • set the logging level ('debug', 'info', 'warn' (default), 'error', 'fatal', 'panic')
  • ```
  • -log-format ```
    • set the format used by logs ('text' (default), or 'json')
  • ```
  • -log ```
    • log file to store logs
  • ```
  • -host ```
    • Docker host address
  • ```
  • -tls ```
    • use TLS connecting to Docker
  • ```
  • -tls-verify ```
    • do TLS verification
  • ```
  • -tls-cert-path ```
    • path to TLS cert files
  • ```
  • -state-path value ```
    • DockerSlim state base path (must set it if the DockerSlim binaries are not in a writable directory!)
  • ```
  • -archive-state
    - Archives 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.
  • ```
  • -in-container
    - Set it to true to explicitly indicate that DockerSlim is running in a container (if it's not set DockerSlim will try to analyze the environment where it's running to determine if it's containerized)
    

To get more command line option information run

docker-slim

without any parameters or select one of the top level commands to get the command-specific information.

To disable the version checks set the global

--check-version

flag to

false

(e.g.,

--check-version=false

) or you can use the

DSLIM\_CHECK\_VERSION

environment variable.

LINT

COMMAND OPTIONS

  • ```
  • -target ```
    • target Dockerfile path (or Docker image, in the future)
  • ```
  • -target-type ```
    • explicitly specify the command target type (values: dockerfile, image)
  • ```
  • -skip-build-context ```
    • don't try to analyze build context
  • build-context-dir
    • explicitly specify the build context directory
  • skip-dockerignore
    • don't try to analyze .dockerignore
  • include-check-label
    • include checks with the selected label key:value
  • exclude-check-label
    • exclude checks with the selected label key:value
  • include-check-id
    • check ID to include
  • include-check-id-file
    • file with check IDs to include
  • exclude-check-id
    • check ID to exclude
  • exclude-check-id-file
    • file with check IDs to exclude

XRAY

COMMAND OPTIONS

  • ```
  • -target ```
    • target container image (name or ID)
  • ```
  • -changes value ```
    • show layer change details for the selected change type (values: none, all, delete, modify, add)
  • ```
  • -layer value ```
    • show details for the selected layer (using layer index or ID)
  • ```
  • -remove-file-artifacts ```
    • remove file artifacts when command is done (note: you'll loose the reverse engineered Dockerfile)
  • ```
  • -add-image-manifest ```
    • add raw image manifest to the command execution report file
  • ```
  • -add-image-config
    - add raw image config object to the command execution report file
    

In the interactive CLI prompt mode you must specify the target image using the

--target

flag while in the traditional CLI mode you can use the

--target

flag or you can specify the target image as the last value in the command.

BUILD

COMMAND OPTIONS

  • ```
  • -target ```
    • target container image (name or ID)
  • ```
  • -http-probe
    - enables HTTP probing (ENABLED by default; you have to disable the probe if you don't need it by setting the flag to 
    false ``` )
  • ```
  • -http-probe-cmd ```
    • additional HTTP probe command [zero or more]
  • ```
  • -http-probe-cmd-file ```
    • file with user defined HTTP probe commands
  • ```
  • -http-probe-retry-count ```
    • number of retries for each HTTP probe (default: 5)
  • ```
  • -http-probe-retry-wait ```
    • number of seconds to wait before retrying HTTP probe (doubles when target is not ready; default: 8)
  • ```
  • -http-probe-ports ```
    • explicit list of ports to probe (in the order you want them to be probed; excluded ports are not probed!)
  • ```
  • -http-probe-full ```
    • do full HTTP probe for all selected ports (if false, finish after first successful scan; default: false)
  • ```
  • -http-probe-exit-on-failure ```
    • exit when all HTTP probe commands fail (default: false)
  • ```
  • -show-clogs ```
    • show container logs (from the container used to perform dynamic inspection)
  • ```
  • -show-blogs ```
    • show build logs (when the minified container is built)
  • ```
  • -copy-meta-artifacts ```
    • copy meta artifacts to the provided location
  • ```
  • -remove-file-artifacts
    - remove file artifacts when command is done (note: you'll loose autogenerated Seccomp and Apparmor profiles unless you copy them with the 
    copy-meta-artifacts ``` flag or if you archive the state)
  • ```
  • -tag
    - use a custom tag for the generated image (instead of the default: 
    .slim ``` )
  • ```
  • -entrypoint ```
    • override ENTRYPOINT analyzing image
  • ```
  • -cmd ```
    • override CMD analyzing image
  • ```
  • -mount
    - mount volume analyzing image (the mount parameter format is identical to the 
  • v ``` mount command in Docker) [zero or more]
  • ```
  • -include-path ```
  • ```
  • -include-path-file
    - Load directory or file includes from a file (optionally overwriting the artifact's permissions, user and group information; format: 
    target:octalPermFlags#uid#gid ``` ; see the non-default USER FAQ section for more details)
  • ```
  • -include-bin value ```
    • Include binary from image (executable or shared object using its absolute path)
  • ```
  • -include-bin-file
    - Load shared binary file includes from a file (similar to 
  • -include-path-file ``` )
  • ```
  • -include-exe value ```
    • Include executable from image (by executable name)
  • ```
  • -include-exe-file
    - Load executable file includes from a file (similar to 
  • -include-path-file ``` )
  • ```
  • -include-shell ```
    • Include basic shell functionality (default: false)
  • ```
  • -path-perms
    - Set path permissions/user/group in optimized image (format: 
    target:octalPermFlags#uid#gid ``` ; see the non-default USER FAQ section for more details)
  • ```
  • -path-perms-file
    - File with path permissions to set (format: 
    target:octalPermFlags#uid#gid ``` ; see the non-default USER FAQ section for more details)
  • ```
  • -exclude-pattern
    - Exclude path pattern ([Glob/Match in Go](https://golang.org/pkg/path/filepath/#Match) and 
    ** ``` ) from image
  • ```
  • -exclude-mounts ```
    • Exclude mounted volumes from image (default: true)
  • ```
  • -env ```
    • override ENV analyzing image [zero or more]
  • ```
  • -workdir ```
    • override WORKDIR analyzing image
  • ```
  • -network ```
    • override default container network settings analyzing image
  • ```
  • -expose ```
    • use additional EXPOSE instructions analyzing image [zero or more]
  • ```
  • -link ```
    • add link to another container analyzing image [zero or more]
  • ```
  • -hostname ```
    • override default container hostname analyzing image
  • ```
  • -etc-hosts-map ```
    • add a host to IP mapping to /etc/hosts analyzing image [zero or more]
  • ```
  • -container-dns ```
    • add a dns server analyzing image [zero or more]
  • ```
  • -container-dns-search ```
    • add a dns search domain for unqualified hostnames analyzing image [zero or more]
  • ```
  • -continue-after ```
    • Select continue mode: enter | signal | probe | timeout or numberInSeconds (default: enter)
  • ```
  • -dockerfile ```
    • The source Dockerfile name to build the fat image before it's minified.
  • ```
  • -use-local-mounts ```
    • Mount local paths for target container artifact input and output (off, by default)
  • ```
  • -use-sensor-volume
    - Sensor volume name to use (set it to your Docker volume name if you manage your own 
    docker-slim ``` sensor volume).
  • ```
  • -keep-tmp-artifacts ```
    • Keep temporary artifacts when command is done (off, by default).
  • ```
  • -keep-perms ```
    • Keep artifact permissions as-is (true, by default)
  • ```
  • -run-target-as-user ```
    • Run target app (in the temporary container) as USER from Dockerfile (true, by default)
  • ```
  • -new-entrypoint ```
    • New ENTRYPOINT instruction for the optimized image
  • ```
  • -new-cmd ```
    • New CMD instruction for the optimized image
  • ```
  • -new-expose ```
    • New EXPOSE instructions for the optimized image
  • ```
  • -new-workdir ```
    • New WORKDIR instruction for the optimized image
  • ```
  • -new-env
    - New ENV instructions for the optimized image
    

In the interactive CLI prompt mode you must specify the target image using the

--target

flag while in the traditional CLI mode you can use the

--target

flag or you can specify the target image as the last value in the command.

The

--include-path

option is useful if you want to customize your minified image adding extra files and directories. The

--include-path-file

option allows you to load multiple includes from a newline delimited file. Use this option if you have a lot of includes. The includes from

--include-path

and

--include-path-file

are combined together. Future versions will also include the

--exclude-path

option to have even more control.

The

--continue-after

option is useful if you need to script

docker-slim

. If you pick the

probe

option then

docker-slim

will continue executing the build command after the HTTP probe is done executing. If you pick the

timeout

option

docker-slim

will allow the target container to run for 60 seconds before it will attempt to collect the artifacts. You can specify a custom timeout value by passing a number of seconds you need instead of the

timeout

string. If you pick the

signal

option you'll need to send a

USR1

signal to the

docker-slim

process. The

signal

option is useful when you want to run your own tests against the temporary container

docker-slim

creates. Your test automation / CI/CD pipeline will be able to notify

docker-slim

that it's done running its test by sending the

USR1

to it.

The

--include-shell

option provides a simple way to keep a basic shell in the minified container. Not all shell commands are included. To get additional shell commands or other command line utilities use the

--include-exe

and/or

--include-bin

options. Note that the extra apps and binaries might missed some of the non-binary dependencies (which don't get picked up during static analysis). For those additional dependencies use the

--include-path

and

--include-path-file

options.

The

--dockerfile

option makes it possible to build a new minified image directly from source Dockerfile. Pass the Dockerfile name as the value for this flag and pass the build context directory or URL instead of the docker image name as the last parameter for the

docker-slim

build command:

docker-slim build --dockerfile Dockerfile --tag my/custom\_minified\_image\_name .

If you want to see the console output from the build stages (when the fat and slim images are built) add the

--show-blogs

build flag. Note that the build console output is not interactive and it's printed only after the corresponding build step is done. The fat image created during the build process has the

.fat

suffix in its name. If you specify a custom image tag (with the

--tag

flag) the

.fat

suffix is added to the name part of the tag. If you don't provide a custom tag the generated fat image name will have the following format:

docker-slim-tmp-fat-image.<pid_of_docker-slim>.<current_timestamp></current_timestamp></pid_of_docker-slim>

. The minified image name will have the

.slim

suffix added to that auto-generated container image name (

docker-slim-tmp-fat-image.<pid_of_docker-slim>.<current_timestamp>.slim</current_timestamp></pid_of_docker-slim>

). Take a look at this python examples to see how it's using the

--dockerfile

flag.

The

--use-local-mounts

option is used to choose how the

docker-slim

sensor is added to the target container and how the sensor artifacts are delivered back to the master. If you enable this option you'll get the original

docker-slim

behavior where it uses local file system volume mounts to add the sensor executable and to extract the artifacts from the target container. This option doesn't always work as expected in the dockerized environment where

docker-slim

itself is running in a Docker container. When this option is disabled (default behavior) then a separate Docker volume is used to mount the sensor and the sensor artifacts are explicitly copied from the target container.

RUNNING CONTAINERIZED

The current version of

docker-slim

is able to run in containers. It will try to detect if it's running in a containerized environment, but you can also tell

docker-slim

explicitly using the

--in-container

global flag.

You can run

docker-slim

in your container directly or you can use the

docker-slim

container in your containerized environment. If you are using the

docker-slim

container make sure you run it configured with the Docker IPC information, so it can communicate with the Docker daemon. The most common way to do it is by mounting the Docker unix socket to the

docker-slim

container. Some containerized environments (like Gitlab and their

dind

service) might not expose the Docker unix socket to you, so you'll need to make sure the environment variables used to communicate with Docker (e.g.,

DOCKER\_HOST

) are passed to the

docker-slim

container. Note that if those environment variables reference any kind of local host names those names need to be replaced or you need to tell

docker-slim

about them using the

--etc-hosts-map

flag. If those environment variables reference local files those local files (e.g., files for TLS cert validation) will need to be copied to a temporary container, so that temporary container can be used as a data container to make those files accessible by the

docker-slim

container.

When

docker-slim

runs in a container it will attempt to save its execution state in a separate Docker volume. If the volume doesn't exist it will try to create it (

docker-slim-state

, by default). You can pick a different state volume or disable this behavior completely by using the global

--archive-state

flag. If you do want to persist the

docker-slim

execution state (which includes the

seccomp

and

AppArmor

profiles) without using the state archiving feature you can mount your own volume that maps to the

/bin/.docker-slim-state

directory in the

docker-slim

container.

By default,

docker-slim

will try to create a Docker volume for its sensor unless one already exists. If this behavior is not supported by your containerized environment you can create a volume separately and pass its name to

docker-slim

using the

--use-sensor-volume

flag.

Here's a basic example of how to use the containerized version of

docker-slim

:

docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock dslim/docker-slim build your-docker-image-name

Here's a GitLab example for their

dind
.gitlab-ci.yml

config file:

docker run -e DOCKER\_HOST=tcp://$(grep docker /etc/hosts | cut -f1):2375 dslim/docker-slim build your-docker-image-name

Here's a CircleCI example for their

remote docker
.circleci/config.yml

config file (used after the

setup\_remote\_docker

step):

docker create -v /dcert\_path --name dcert alpine:latest /bin/true docker cp $DOCKER\_CERT\_PATH/. dcert:/dcert\_path docker run --volumes-from dcert -e DOCKER\_HOST=$DOCKER\_HOST -e DOCKER\_TLS\_VERIFY=$DOCKER\_TLS\_VERIFY -e DOCKER\_CERT\_PATH=/dcert\_path dslim/docker-slim build your-docker-image-name

DOCKER CONNECT OPTIONS

If you don't specify any Docker connect options

docker-slim

expects to find the following environment variables:

DOCKER\_HOST

,

DOCKER\_TLS\_VERIFY

(optional),

DOCKER\_CERT\_PATH

(required if

DOCKER\_TLS\_VERIFY

is set to

"1"

)

On Mac OS X you get them when you run

eval "$(docker-machine env default)"

or when you use the Docker Quickstart Terminal.

If the Docker environment variables are configured to use TLS and to verify the Docker cert (default behavior), but you want to disable the TLS verification you can override the TLS verification behavior by setting the

--tls-verify

to false:

docker-slim --tls-verify=false build --http-probe=true my/sample-node-app-multi

You can override all Docker connection options using these flags:

--host

,

--tls

,

--tls-verify

,

--tls-cert-path

. These flags correspond to the standard Docker options (and the environment variables).

If you want to use TLS with verification:

docker-slim --host=tcp://192.168.99.100:2376 --tls-cert-path=/Users/youruser/.docker/machine/machines/default --tls=true --tls-verify=true build --http-probe=true my/sample-node-app-multi

If you want to use TLS without verification:

docker-slim --host=tcp://192.168.99.100:2376 --tls-cert-path=/Users/youruser/.docker/machine/machines/default --tls=true --tls-verify=false build --http-probe=true my/sample-node-app-multi

If the Docker environment variables are not set and if you don't specify any Docker connect options

docker-slim

will try to use the default unix socket.

HTTP PROBE COMMANDS

If the HTTP probe is enabled (note: it is enabled by default) it will default to running

GET /

with HTTP and then HTTPS on every exposed port. You can add additional commands using the

--http-probe-cmd

and

--http-probe-cmd-file

options.

The

--http-probe-cmd

option is good when you want to specify a small number of simple commands where you select some or all of these HTTP command options: protocol, method (defaults to GET), resource (path and query string).

If you only want to use custom HTTP probe command and you don't want the default

GET /

command added to the command list you explicitly provided you'll need to set

--http-probe

to false when you specify your custom HTTP probe command. Note that this inconsistency will be addressed in the future releases to make it less confusing.

Here are a couple of examples:

Adds two extra probe commands:

GET /api/info

and

POST /submit

(tries http first, then tries https):

docker-slim build --show-clogs --http-probe-cmd /api/info --http-probe-cmd POST:/submit my/sample-node-app-multi

Adds one extra probe command:

POST /submit

(using only http):

docker-slim build --show-clogs --http-probe-cmd http:POST:/submit my/sample-node-app-multi

The

--http-probe-cmd-file

option is good when you have a lot of commands and/or you want to select additional HTTP command options.

Here's an example:

docker-slim build --show-clogs --http-probe-cmd-file probeCmds.json my/sample-node-app-multi

Commands in

probeCmds.json

:

{ "commands": [{ "resource": "/api/info" }, { "method": "POST", "resource": "/submit" }, { "procotol": "http", "resource": "/api/call?arg=one" }, { "protocol": "http", "method": "POST", "resource": "/submit2", "body": "key=value" }] }

The HTTP probe command file path can be a relative path (relative to the current working directory) or it can be an absolute path.

For each HTTP probe call docker-slim will print the call status. Example:

info=http.probe.call status=200 method=GET target=http://127.0.0.1:32899/ attempt=1 error=none

.

You can execute your own external HTTP requests using the

target.port.list

field in the container info message docker-slim prints when it starts its test container:

docker-slim[build]: info=container name=<your_container_name> id=<your_container_id> target.port.list=[<comma_separated_list_of_port_numbers_to_use>] target.port.info=[<comma_separated_list_of_port_mapping_records>]</comma_separated_list_of_port_mapping_records></comma_separated_list_of_port_numbers_to_use></your_container_id></your_container_name>

. Example:

docker-slim[build]: info=container name=dockerslimk\_42861\_20190203084955 id=aa44c43bcf4dd0dae78e2a8b3ac011e7beb6f098a65b09c8bce4a91dc2ff8427 target.port.list=[32899] target.port.info=[9000/tcp =\> 0.0.0.0:32899]

. With this information you can run

curl

or other HTTP request generating tools:

curl http://localhost:32899

.

DEBUGGING MINIFIED CONTAINERS

You can create dedicated debugging side-car container images loaded with the tools you need for debugging target containers. This allows you to keep your production container images small. The debugging side-car containers attach to the running target containers.

Assuming you have a running container named

node\_app\_alpine

you can attach your debugging side-car with a command like this:

docker run --rm -it --pid=container:node\_app\_alpine --net=container:node\_app\_alpine --cap-add sys\_admin alpine sh

. In this example, the debugging side-car is a regular alphine image. This is exactly what happens with the

node\_alpine

app sample (located in the

node\_alpine

directory of the

examples

repo) and the

run\_debug\_sidecar.command

helper script.

If you run the

ps

command in the side-car you'll see the application from the target container:

# ps PID USER TIME COMMAND 1 root 0:00 node /opt/my/service/server.js 13 root 0:00 sh 38 root 0:00 ps

You can access the target container file system through

/proc/<target_pid>/root</target_pid>

:

# ls -lh /proc/1/root/opt/my/service total 8 drwxr-xr-x 3 root root 4.0K Sep 2 15:51 node\_modules -rwxr-xr-x 1 root root 415 Sep 8 00:52 server.js

Some of the useful debugging commands include

cat /proc/<target_pid>/cmdline</target_pid>

,

ls -l /proc/<target_pid>/cwd</target_pid>

,

cat /proc/1/environ

,

cat /proc/<target_pid>/limits</target_pid>

,

cat /proc/<target_pid>/status</target_pid>

and

ls -l /proc/<target_pid>/fd</target_pid>

.

MINIFYING COMMAND LINE TOOLS

Unless the default CMD instruction in your Dockerfile is sufficient you'll have to specify command line parameters when you execute the

build

command in DockerSlim. This can be done with the

--cmd

option.

Other useful command line parameters:

  • ```
  • -show-clogs ```
    • use it if you want to see the output of your container.
  • ```
  • -mount ```
    • use it to mount a volume when DockerSlim inspects your image.
  • ```
  • -entrypoint
    - use it if you want to override the ENTRYPOINT instruction when DockerSlim inspects your image.
    

Note that the

--entrypoint

and

--cmd

options don't override the

ENTRYPOINT

and

CMD

instructions in the final minified image.

Here's a sample

build

command:

docker-slim build --show-clogs=true --cmd docker-compose.yml --mount $(pwd)/data/:/data/ dslim/container-transform

It's used to minify the

container-transform

tool. You can get the minified image from [

Docker Hub

](https://hub.docker.com/r/dslim/container-transform.slim/).

QUICK SECCOMP EXAMPLE

If you want to auto-generate a Seccomp profile AND minify your image use the

build

command. If you only want to auto-generate a Seccomp profile (along with other interesting image metadata) use the

profile

command.

Step one: run DockerSlim

docker-slim build your-name/your-app

Step two: use the generated Seccomp profile

docker run --security-opt seccomp:<docker-slim directory>/.images/<your_app_image_id>/artifacts/your-name-your-app-seccomp.json <your other run params> your-name/your-app</your></your_app_image_id></docker-slim>

Feel free to copy the generated profile :-)

You can use the generated Seccomp profile with your original image or with the minified image.

USING AUTO-GENERATED SECCOMP PROFILES

You can use the generated profile with your original image or with the minified image DockerSlim created:

docker run -it --rm --security-opt seccomp:path\_to/my-sample-node-app-seccomp.json -p 8000:8000 my/sample-node-app.slim

ORIGINAL DEMO VIDEO

DockerSlim demo

Demo video on YouTube

DEMO STEPS

The demo runs on Mac OS X, but you can build a linux version. Note that these steps are different from the steps in the demo video.

  1. Get the docker-slim Mac, Linux or Linux ARM binaries. Unzip them and optionally add their directory to your PATH environment variable if you want to use the app from other locations.

The extracted directory contains two binaries:

  • docker-slim
    <- the main application
  • docker-slim-sensor
    <- the sensor application used to collect information from running containers
  1. Clone the
    examples
    repo to use the sample apps (note: the examples have been moved to a separate repo). You can skip this step if you have your own app.
git clone https://github.com/docker-slim/examples.git
  1. Create a Docker image for the sample node.js app in
    examples/node\_ubuntu
    . You can skip this step if you have your own app.
cd examples/node\_ubuntu
eval "$(docker-machine env default)"

<- optional (depends on how Docker is installed on your machine and what kind of Docker version you are using); if the Docker host is not running you'll need to start it first:

docker-machine start default

; see the

Docker connect options

section for more details.

docker build -t my/sample-node-app .
  1. Run
    docker-slim
    :
./docker-slim build my/sample-node-app

<- run it from the location where you extraced the docker-slim binaries (or update your PATH env var to include the

docker-slim

bin directory)

DockerSlim creates a special container based on the target image you provided. It also creates a resource directory where it stores the information it discovers about your image:

<docker-slim directory>/.images/<target_image_id></target_image_id></docker-slim>

.

By default,

docker-slim

will run its http probe against the temporary container. If you are minifying a command line tool that doesn't expose any web service interface you'll need to explicitly disable http probing (by setting

--http-probe=false

).

  1. Use curl (or other tools) to call the sample app (optional)
curl http://<your_docker_host_ip>:<port></port></your_docker_host_ip>

This is an optional step to make sure the target app container is doing something. Depending on the application it's an optional step. For some applications it's required if it loads new application resources dynamically based on the requests it's processing (e.g., Ruby or Python).

You'll see the mapped ports printed to the console when

docker-slim

starts the target container. You can also get the port number either from the

docker ps

or

docker port <container_id></container_id>

commands. The current version of DockerSlim doesn't allow you to map exposed network ports (it works like

docker run … -P

).

  1. Press and wait until
    docker-slim
    says it's done

By default or when http probing is enabled explicitly

docker-slim

will continue its execution once the http probe is done running. If you explicitly picked a different

continue-after

option follow the expected steps. For example, for the

enter
continue-after

option you must press the

enter

button on your keyboard.

If http probing is enabled (when

http-probe

is set) and if

continue-after

is set to

enter

and you press the

enter

key before the built-in HTTP probe is done the probe might produce an EOF error because

docker-slim

will shut down the target container before all probe commands are done executing. It's ok to ignore it unless you really need the probe to finish.

  1. Once DockerSlim is done check that the new minified image is there
docker images

You should see

my/sample-node-app.slim

in the list of images. Right now all generated images have

.slim

at the end of its name.

  1. Use the minified image
docker run -it --rm --name="slim\_node\_app" -p 8000:8000 my/sample-node-app.slim

FAQ

Is it safe for production use?

Yes! Either way, you should test your Docker images.

How can I contribute if I don't know Go?

You don't need to read the language spec and lots of books :-) Go through the Tour of Go and optionally read 50 Shades of Go and you'll be ready to contribute!

What's the best application for DockerSlim?

DockerSlim will work for any dockerized application; however, DockerSlim automates app interactions for applications with an HTTP API. You can use DockerSlim even if your app doesn't have an HTTP API. You'll need to interact with your application manually to make sure DockerSlim can observe your application behavior.

Can I use DockerSlim with dockerized command line tools?

Yes. The

--cmd

,

--entrypoint

, and

--mount

options will help you minify your image. The

container-transform

tool is a good example.

Notes:

You can explore the artifacts DockerSlim generates when it's creating a slim image. You'll find those in

<docker-slim directory>/.images/<target_image_id>/artifacts</target_image_id></docker-slim>

. One of the artifacts is a "reverse engineered" Dockerfile for the original image. It'll be called

Dockerfile.fat

.

If you'd like to see the artifacts without running

docker-slim

you can take a look at the

examples/artifacts

directory in this repo. It doesn't include any image files, but you'll find:

  • a reverse engineered Dockerfile (
    Dockerfile.fat
    )
  • a container report file (
    creport.json
    )
  • a sample AppArmor profile (which will be named based on your original image name)
  • and a sample Seccomp profile

If you don't want to create a minified image and only want to "reverse engineer" the Dockerfile you can use the

info

command.

What if my Docker images uses the USER command?

The current version of DockerSlim does include support for non-default users (take a look at the non-default user examples (including the ElasticSearch example located in the

3rdparty

directory) in the [

examples

](https://github.com/docker-slim/examples) repo. Please open tickets if something doesn't work for you.

Everything should work as-is, but for the special cases where the current behavior don't work as expected you can adjust what DockerSlim does using various

build

command parameters:

--run-target-as-user

,

--keep-perms

,

--path-perms

,

--path-perms-file

(along with the

--include-\*

parameters).

The

--run-target-as-user

parameter is enabled by default and it controls if the application in the temporary container is started using the identity from the USER instruction in the container's Dockerfile.

The

--keep-perms

parameter is also enabled by default. It tells DockerSlim to retain the permissions and the ownership information for the files and directories copied to the optimized container image.

The

--path-perms

and

--path-perms-file

parameters are similar to the

--include-path

and

--include-path-file

parameters. They are used to overwrite the permission and the user/group information for the target files and directories. Note that the target files/directories are expected to be in the optimized container image. If you don't know if the target files/directories will be in the optimized container you'll need to use one of the

--include-\*

parameters (e.g.,

--include-path-file

) to explicitly require those artifacts to be included. You can specify the permissions and the ownership information in the

--include-\*

parameters too (so you don't need to have the

--path-\*

parameters just to set the permissions).

The

--path-\*

and

--include-\*

params use the same format to communicate the permission/owernship info:

TARGET\_PATH\_OR\_NAME:PERMS\_IN\_OCTAL\_FORMAT#USER\_ID#GROUP\_ID

.

You don't have to specify the user and group IDs if you don't want to change them.

Here's an example using these parameters to minify the standard

nginx

image adding extra artifacts and changing their permissions:

docker-slim build --include-path='/opt:770#104#107' --include-path='/bin/uname:710' --path-perms='/tmp:700' nginx

.

This is what you'll see in the optimized container image:

drwx------ 0 0 0 0 Feb 28 22:15 tmp/ -rwx--x--- 0 0 0 31240 Mar 14 2015 bin/uname drwxrwx--- 0 104 107 0 Feb 28 22:13 opt/

The

uname

binary isn't used by nginx, so the

--include-path

parameter is used to keep it in the optimized image changing its permissions to

710

.

The

/tmp

directory will be included in the optimized image on its own, so the

--path-perms

parameter is used to change its permissions to

700

.

When you set permissions/user/group on a directory the settings are only applied to that directory and not to the artifacts inside. The future versions will allow you to apply the same settings to everything inside the target directory too.

Also note that for now you have to use numeric user and group IDs. The future versions will allow you to use user and group names too.

Nginx fails in my minified image

If you see

nginx: [emerg] mkdir() "/var/lib/nginx/body" failed

it means your nginx setup uses a non-standard temporary directory. Nginx will fail if the base directory for its temporary folders doesn't exist (they won't create the missing intermediate directories). Normally it's

/var/lib/nginx

, but if you have a custom config that points to something else you'll need to add an

--include-path

flag as an extra flag when you run

docker-slim

.

DockerSlim fails with a 'no permission to read from' error

You can get around this problem by running DockerSlim from a root shell. That way it will have access to all exported files.

DockerSlim copies the relevant image artifacts trying to preserve their permissions. If the permissions are too restrictive the master app might not have sufficient priviledge to access these files when it's building the new minified image.

BUILD PROCESS

Use Go 1.13 or higher to build

docker-slim

. You can use earlier version of Go, but it can't be lower than Go 1.5.1. Versions prior to 1.5.1 have a Docker/ptrace related bug (Go kills processes if your app is PID 1). When the 'monitor' is separate from the 'launcher' process it will be possible to user older Go versions again.

Tools:

  • license-bill-of-materials
    • Optional tool to track dependencies and their licenses.
  • golint
    • Optional tool for code analysis. See
      https://github.com/golang/lint
      for more details.

You can install these tools using the

tools.get.sh

shell script in the

scripts

directory.

Notes:

  • Make sure you have
    golint
    if you intend to run the
    src.inspect.sh
    or
    mac.src.inspect.command
    scripts.

Build Steps

You have multiple options to build

docker-slim

:

  • Run
    make
    (or
    ./scripts/docker-builder.run.sh
    or click on
    ./scripts/mac/docker-builder.run.command
    on Macs) from the project directory (builds
    docker-slim
    in a Docker container; great if you don't want to install Go on your local machine and if you already have Docker)
  • Run
    make build
    (or
    ./scripts/src.build.sh
    or click on
    ./scripts/mac/src.build.command
    on Macs) to build
    docker-slim
    natively (requires Go installed locally)

DESIGN

CORE CONCEPTS

  1. Inspect container metadata (static analysis)
  2. Inspect container data (static analysis)
  3. Inspect running application (dynamic analysis)
  4. Build an application artifact graph
  5. Use the collected application data to build small images
  6. Use the collected application data to auto-generate various security framework configurations.

DYNAMIC ANALYSIS OPTIONS

  1. Instrument the container image (and replace the entrypoint/cmd) to collect application activity data
  2. Use kernel-level tools that provide visibility into running containers (without instrumenting the containers)
  3. Disable relevant namespaces in the target container to gain container visibility (can be done with runC)

SECURITY

The goal is to auto-generate Seccomp, AppArmor, (and potentially SELinux) profiles based on the collected information.

  • AppArmor profiles
  • Seccomp profiles

CHALLENGES

Some of the advanced analysis options require a number of Linux kernel features that are not always included. The kernel you get with Docker Machine / Boot2docker is a great example of that.

DEVELOPMENT PROGRESS

TODO

  • AppArmor profile improvements
  • Better support for command line applications (e.g., ability to specify multiple executions)
  • Discover HTTP endpoints to make the HTTP probe more intelligent.
  • Scripting language dependency discovery in the "scanner" app.
  • Explore additional dependency discovery methods.
  • Build/use a custom Boot2docker kernel with every required feature turned on.
  • "Live" image create mode - to create new images from containers where users install their applications interactively.

ORIGINS

DockerSlim was a

Docker Global Hack Day

#

dockerhackday

project. It barely worked at the time, but it did get a win in Seattle and it took the second place in the

Plumbing

category overall :-)

DHD3

Since then it's been improved and it works pretty well for its core use cases. It can be better though. That's why the project needs your help! You don't need to know much about Docker and you don't need to know anything about Go. You can contribute in many different ways. For example, use DockerSlim on your images and open a Github issue documenting your experience even if it worked just fine :-)

ONLINE

IRC (freenode): #dockerslim

Docker Hub: dslim (dockerslim is already taken :-()

MINIFIED DOCKER HUB IMAGES

CONTRIBUTING

If the project sounds interesting or if you found a bug see [

CONTRIBUTING.md

](https://github.com/docker-slim/docker-slim/blob/master/CONTRIBUTING.md) and submit a PR!

LICENSE

Apache License v2, see LICENSE for details.


Go Report CardCodacy Badge

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.