Don't change anything in your Docker container image and minify it by up to 30x making it secure too! Optimizing images isn't the only thing it can do though. It can also help you understand and author better container images.
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).
Understand your container image before and after you optimize it using the xray
command in docker-slim
or the Slim SaaS where you can get even more powerful insights including how your container image changed.
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:
Watch this screencast to see how an application image is minified by more than 30x.
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 when HTTP probing is enabled (enabled by default; see the --http-probe*
flag docs for more details). 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.
You can also interact with the temporary container via a shell script or snippet using --exec-file
or --exec
. For example, you can create a container which is only capable of using curl.
>> docker pull archlinux:latest
...
>> docker-slim build --target archlinux:latest --tag archlinux:curl --http-probe=false --exec "curl checkip.amazonaws.com"
...
>> docker run archlinux:curl curl checkip.amazonaws.com
...
>> docker images
archlinux curl ... ... 17.4MB
archlinux latest ... ... 467MB
...
Feel free to join any of these channels or just open a new Github issue
if you want to chat or if you need help.
YouTube channel
Gitter channel
Discord server
Discussions
(new)Twitter
Slack
IRC channel
on freenode
(not used anymore, but we can start using it again :-): #dockerslim
Everyone's Docker/Kubernetes
(Japanese)Docker in Practice (2nd edition)
Docker/Kubernetes Security Practice Guide
(Japanese)You can find the examples in a separate repository: https://github.com/docker-slim/examples
Node.js application images:
Python application images:
Ruby application images:
Golang application images:
Rust application images:
JAVA application images:
PHP application images:
Haskell application images:
Elixir application images:
Latest version: 1.37.0 (9/23/2021)
The 1.37.0 releases adds experimental docker-compose support for the build command.
For more info about the latest release see the CHANGELOG
.
If you already have docker-slim
installed use the update
command to get the latest version:
docker-slim update
Download the zip package for your platform.
Latest Mac binaries (curl -L -o ds.zip https://downloads.dockerslim.com/releases/1.37.0/dist_mac.zip
)
Latest Mac M1 binaries (curl -L -o ds.zip https://downloads.dockerslim.com/releases/1.37.0/dist_mac_m1.zip
)
Latest Linux binaries (curl -L -o ds.tar.gz https://downloads.dockerslim.com/releases/1.37.0/dist_linux.tar.gz
)
Latest Linux ARM binaries (curl -L -o ds.tar.gz https://downloads.dockerslim.com/releases/1.37.0/dist_linux_arm.tar.gz
)
Latest Linux ARM64 binaries (curl -L -o ds.tar.gz https://downloads.dockerslim.com/releases/1.37.0/dist_linux_arm64.tar.gz
)
Unzip the package and optionally move it to your bin directory.
Linux (for non-intel replace dist_linux
with the platform-specific extracted path):
tar -xvf ds.tar.gz
mv dist_linux/docker-slim /usr/local/bin/
mv dist_linux/docker-slim-sensor /usr/local/bin/
Mac:
unzip ds.zip
mv dist_mac/docker-slim /usr/local/bin/
mv dist_mac/docker-slim-sensor /usr/local/bin/
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.
You can also use this script to install the current release of DockerSlim on Linux (x86 and ARM) and macOS (x86 and Apple Silicon)
curl -sL https://raw.githubusercontent.com/docker-slim/docker-slim/master/scripts/install-dockerslim.sh | sudo -E bash -
brew install docker-slim
The Homebrew installer: https://formulae.brew.sh/formula/docker-slim
docker pull dslim/docker-slim
See the RUNNING CONTAINERIZED section for more usage info.
Powered by DockerSlim. It will help you understand and troubleshoot your application containers and a lot more. If you use the xray
command you'll want to try the SaaS. Understanding image changes is easy with its container diff capabilities. Connect your own registry and you can do the same with your own containers. Try it here without installing anything locally.
docker-slim [global flags] [lint|xray|build|profile|update|version|help] [command-specific flags] <IMAGE_ID_OR_NAME>
If you don't specify any command docker-slim
will start in the interactive prompt mode.
build
- Analyzes, profiles and optimizes your container image generating the supported security profiles. This is the most popular command.xray
- Performs static analysis for the target container image (including 'reverse engineering' the Dockerfile for the image). Use this command if you want to know what's inside of your container image and what makes it fat.lint
- Analyzes container instructions in Dockerfiles (Docker image support is WIP)profile
- Performs basic container image analysis and dynamic container analysis, but it doesn't generate an optimized image.run
- Runs one or more containers (for now runs a single container similar to docker run
)version
- Shows the version information.update
- Updates docker-slim
to the latest version.help
- Show the available commands and global flagsExample: 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
.
docker-slim [global options] command [command options] <target image ID or name>
Commands:
lint
- Lint the target Dockerfile (or image, in the future)xray
- Show what's in the container image and reverse engineer its Dockerfilebuild
- Analyze the target container image along with its application and build an optimized image from itprofile
- Collect fat image information and generate a fat container reportversion
- Show docker-slim and docker version informationupdate
- Update docker-slimhelp
- Show help infoGlobal 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 outdated--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; if you don't use this flag you must specify the target as the argument to the command)--target-type
- explicitly specify the command target type (values: dockerfile, image)--skip-build-context
- don't try to analyze build contextbuild-context-dir
- explicitly specify the build context directoryskip-dockerignore
- don't try to analyze .dockerignoreinclude-check-label
- include checks with the selected label key:valueexclude-check-label
- exclude checks with the selected label key:valueinclude-check-id
- check ID to includeinclude-check-id-file
- file with check IDs to includeexclude-check-id
- check ID to excludeexclude-check-id-file
- file with check IDs to excludeshow-nohits
- show checks with no matchesshow-snippet
- show check match snippet (default value: true)list-checks
- list available checks (don't need to specify the target flag if you just want to list the available checks)XRAY
COMMAND OPTIONS--target
- Target container image (name or ID)--pull
- Try pulling target if it's not available locally (default: false).--show-plogs
- Show image pull logs (default: false).--changes value
- Show layer change details for the selected change type (values: none, all, delete, modify, add).--changes-output value
- Where to show the changes (values: all, report, console).--layer value
- Show details for the selected layer (using layer index or ID)--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--layer-changes-max
- Maximum number of changes to show for each layer--all-changes-max
- Maximum number of changes to show for all layers--add-changes-max
- Maximum number of add
changes to show for all layers--modify-changes-max
- Maximum number of modify
changes to show for all layers--delete-changes-max
- Maximum number of delete
changes to show for all layers--change-path value
- Include changes for the files that match the path pattern (Glob/Match in Go and **). Value formats: <path pattern>
| dump:<output type>:<path pattern>
| ::<path pattern>
where output type
is console
or a directory name. If value
starts with dump:
the match will be 'dumped' to the selected output type
. [can use this flag multiple times]--change-data value
- Include changes for the files that match the data pattern (regex). Value formats: <data regex>
| dump:<output type>:<path pattern>:<data regex>
| ::<path pattern>:<data regex>
| :::<data regex>
where output type
is console
or a directory name. If value
starts with dump:
the match will be 'dumped' to the selected output type
. [can use this flag multiple times]--change-data-hash value
- Include changes for the files that match the provided data hashes (sha1). Value formats: <sha1 hash>
| dump:<output type>:<sha1 hash>
| ::<sha1 hash>
where output type
is console
or a directory name. If value
starts with dump:
the match will be 'dumped' to the selected output type
. [can use this flag multiple times]--reuse-saved-image
- Reuse saved container image (default: true).--top-changes-max
- Maximum number of top changes to track (defalt: 20).--hash-data
- Generate file data hashes (default: false).--detect-duplicates
- Detect duplicate files based on their hashes (default: false).--show-duplicates
- Show all discovered duplicate file paths (default: true).--detect-utf8
- Detect utf8 files and optionally extract the discovered utf8 file content (possible values: "true" or "dump" or "dump:output_target.tgz" or "dump:output_target.tgz::max_size_bytes" or "dump:output_target.tgz:::max_size_bytes").--detect-all-certs
- Detect all certifcate files--detect-all-cert-pks
- Detect all certifcate private key files--change-match-layers-only
- Show only layers with change matches (default: false).--export-all-data-artifacts
- Archive path to export all data artifacts enabling the related flags if not set (if set to .
then path defaults to ./data-artifacts.tar
)--remove-file-artifacts
- Remove file artifacts when command is done (note: you'll loose the reverse engineered Dockerfile)Change Types:
none
- Don't show any file system change details in image layers (the top changes from the corresponding layer are still shown)all
- Show all file system change details in image layersdelete
- Show only delete
file system change details in image layersmodify
- Show only modify
file system change details in image layersadd
- Show only 'add' file system change details in image layersIn 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). It's an alternative way to provide the target information. The standard way to provide the target information is by putting as the last value in the build
command CLI call.--pull
- Try pulling target if it's not available locally (default: false).--show-plogs
- Show image pull logs (default: false).compose-file
- Load container info from selected compose filetarget-compose-svc
- Target service from compose filetarget-compose-svc-no-ports
- Do not publish ports for target service from compose filedep-exclude-compose-svc-all
- Do not start any compose services as target dependenciesdep-include-compose-svc
- Include specific compose service as a target dependency (only selected services will be started)dep-exclude-compose-svc
- Exclude specific service from the compose services that will be started as target dependenciesdep-include-compose-svc-deps
- Include all dependencies for the selected compose service (excluding the service itself) as target dependenciescompose-net
- Attach target to the selected compose network(s) otherwise all networks will be attached--http-probe
- Enables/disables 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=false
)--http-probe-off
- Alternative way to disable HTTP probing--http-probe-cmd
- Additional HTTP probe command [can use this flag multiple times]--http-probe-cmd-file
- File with user defined HTTP probe commands--http-probe-retry-count
- Number of retries for each HTTP probe (default value: 5)--http-probe-retry-wait
- Number of seconds to wait before retrying HTTP probe (doubles when target is not ready; default value: 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 value: false)--http-probe-exit-on-failure
- Exit when all HTTP probe commands fail (default value: true)--http-probe-crawl
- Enable crawling for the default HTTP probe command (default value: true)--http-crawl-max-depth
- Max depth to use for the HTTP probe crawler (default value: 3)--http-crawl-max-page-count
- Max number of pages to visit for the HTTP probe crawler (default value: 1000)--http-crawl-concurrency
- Number of concurrent workers when crawling an HTTP target (default value: 10)--http-max-concurrent-crawlers
- Number of concurrent crawlers in the HTTP probe (default value: 1)--http-probe-apispec
- Run HTTP probes for API spec where the value represents the target path where the spec is available (supports Swagger 2.x and OpenAPI 3.x) [can use this flag multiple times]--http-probe-apispec-file
- Run HTTP probes for API spec from file (supports Swagger 2.x and OpenAPI 3.x) [can use this flag multiple times]--http-probe-exec
- App to execute when running HTTP probes. [can use this flag multiple times]--http-probe-exec-file
- Apps to execute when running HTTP probes loaded from file.--publish-port
- Map container port to host port analyzing image at runtime to make it easier to integrate external tests (format => port | hostPort:containerPort | hostIP:hostPort:containerPort | hostIP::containerPort )[can use this flag multiple times]--publish-exposed-ports
- Map all exposed ports to the same host ports analyzing image at runtime (default value: 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 value: <original_image_name>.slim
) [can use this flag multiple times if you need to create additional tags for the optimized image]--entrypoint
- Override ENTRYPOINT analyzing image at runtime--cmd
- Override CMD analyzing image at runtime--mount
- Mount volume analyzing image (the mount parameter format is identical to the -v
mount command in Docker) [can use this flag multiple times]--include-path
- Include directory or file from image [can use this flag multiple times] (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-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 value: false)include-cert-all
- Keep all discovered cert filesinclude-cert-bundles-only
- Keep only cert bundlesinclude-cert-dirs
- Keep known cert directories and all files in theminclude-cert-pk-all
- Keep all discovered cert private keysinclude-cert-pk-dirs
- Keep known cert private key directories and all files in them--preserve-path
- Keep path from orignal image in its initial state. [can use this flag multiple times]--preserve-path-file
- File with paths to keep from original image in their original state.--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 and **
) from image--exclude-mounts
- Exclude mounted volumes from image (default value: true)--label
- Override or add LABEL analyzing image at runtime [can use this flag multiple times]--volume
- Add VOLUME analyzing image at runtime [can use this flag multiple times]--env
- Override ENV analyzing image at runtime [can use this flag multiple times]--workdir
- Override WORKDIR analyzing image at runtime--network
- Override default container network settings analyzing image at runtime--expose
- Use additional EXPOSE instructions analyzing image at runtime [can use this flag multiple times]--link
- Add link to another container analyzing image at runtime [can use this flag multiple times]--hostname
- Override default container hostname analyzing image at runtime--etc-hosts-map
- Add a host to IP mapping to /etc/hosts analyzing image at runtime [can use this flag multiple times]--container-dns
- Add a dns server analyzing image at runtime [can use this flag multiple times]--container-dns-search
- Add a dns search domain for unqualified hostnames analyzing image at runtime [can use this flag multiple times]--image-overrides
- Save runtime overrides in generated image (values is all
or a comma delimited list of override types: entrypoint
, cmd
, workdir
, env
, expose
, volume
, label
). Use this flag if you need to set a runtime value and you want to persist it in the optimized image. If you only want to add, edit or delete an image value in the optimized image use one of the --new-*
or --remove-*
flags (define below).--continue-after
- Select continue mode: enter
| signal
| probe
| exec
| timeout
or numberInSeconds (default value if http probes are disabled: enter
). You can also select probe
and exec
together: 'probe&exec'
(make sure to use quotes around the two modes or the &
will break the shell command).--dockerfile
- The source Dockerfile name to build the fat image before it's optimized.--tag-fat
- Custom tag for the fat image built from Dockerfile.--cbo-add-host
- Add an extra host-to-IP mapping in /etc/hosts to use when building an image (Container Build Option).--cbo-build-arg
- Add a build-time variable (Container Build Option).--cbo-label
- Add a label when building from Dockerfiles (Container Build Option).--cbo-target
- Target stage to build for multi-stage Dockerfiles (Container Build Option).--cbo-network
- Networking mode to use for the RUN instructions at build-time (Container Build Option).--cbo-cache-from
- Add an image to the build cache (Container Build Option).--cro-runtime
- Runtime to use with the created containers (Container Runtime Option).--cro-host-config-file
- File to load the Docker host configuration data (JSON format) to use when running the container. See the HostConfig struct definition from the go-dockerclient
package for configuration details. Note that docker-slim will automatically add SYS_ADMIN
to the list of capabilities and run the container in privileged mode, which are required to generate the seccomp profiles. The host config parameters specified using their standalone build or profile command flags overwrite the values in the host config file (volume binds are merged).--cro-sysctl
- Set namespaced kernel parameters in the created container (Container Runtime Option).--cro-shm-size
- Shared memory size for /dev/shm in the created container (Container Runtime Option).--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--new-label
- New LABEL instructions for the optimized image--new-volume
- New VOLUME instructions for the optimized image--remove-volume
- Remove VOLUME instructions for the optimized image--remove-env
- Remove ENV instructions for the optimized image--remove-label
- Remove LABEL instructions for the optimized image--remove-expose
- Remove EXPOSE instructions for the optimized image--exec
- A shell script snippet to run via Docker exec--exec-file
- A shell script file to run via Docker execIn 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. You can also use the --exclude-pattern
flag to control what shouldn't be included.
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 exec
options then docker-slim
will continue executing the build command after the container exec shell commands (specified using the --exec-file
or --exec
flags) are 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.
You can also combine multiple continue-after
modes. For now only combining probe
and exec
is supported (using either probe&exec
or exec&probe
as the --continue-after
flag value). Other combinations may work too. Combining probe
and signal
is not supported.
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>
. 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
). 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.
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
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 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 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 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.
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.
If you want to disable HTTP probing set the --http-probe
flag to false (e.g., --http-probe=false
). You can also use the --http-probe-off
flag to do the same (simply use the flag without any parameters).
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: crawling (defaults to false), 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.
Possible field combinations:
/path
- runs GET /path
crawl:/path
- runs GET /path
and then crawls the pages referenced by the target pagepost:/path
- runs POST /path
crawl:get:/path
- runs GET /path
and then crawls the pages referenced by the target pagehttps:get:/path
runs GET /path
only on httpscrawl:http:get:/path
- runs GET /path
and then crawls the pages referenced by the target pageHere 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.
Available HTTP command options:
method
- HTTP method to useresource
- target resource URLport
- port numberprotocol
- http
, https
, http2
, http2c
(cleartext version of http2), ws
, wss
(secure websocket)headers
- array of strings with column delimited key/value pairs (e.g., "Content-Type: application/json")body
- request body as a stringbody_file
- request body loaded from the provided fileusername
- username to use for basic authpassword
- password to use for basic authcrawl
- boolean to indicate if you want to crawl the target (to visit all referenced resources)Here's a probe command file 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"
},
{
"protocol": "http",
"method": "POST",
"resource": "/submit3",
"body_file": "mydata.json",
"headers": ["Content-Type: application/json"]
}
]
}
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>]
. 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
.
The current version also includes an experimental crawling
capability. To enable it for the default HTTP probe use the --http-probe-crawl
flag. You can also enable it for the HTTP probe commands in your command file using the crawl
boolean field.
When crawling
is enabled the HTTP probe will act like a web crawler following the links it finds in the target endpoint.
Probing based on the Swagger/OpenAPI spec is another experimental capability. This feature introduces two new flags:
http-probe-apispec
- value: <path_to_fetch_spec>:<api_endpoint_prefix>
http-probe-apispec-file
- value: <local_file_path_to_spec>
You can use the --http-probe-exec
and --http-probe-exec-file
options to run the user provided commands when the http probes are executed. This example shows how you can run curl
against the temporary docker-slim created container when the http probes are executed.
docker-slim build --http-probe-exec 'curl http://localhost:YOUR_CONTAINER_PORT_NUM/some/path' --publish-port YOUR_CONTAINER_PORT_NUM your-container-image-name
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
:
# 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
, ls -l /proc/<TARGET_PID>/cwd
, cat /proc/1/environ
, cat /proc/<TARGET_PID>/limits
, cat /proc/<TARGET_PID>/status
and ls -l /proc/<TARGET_PID>/fd
.
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
.
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
Feel free to copy the generated profile :-)
You can use the generated Seccomp profile with your original image or with the minified image.
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
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.
The extracted directory contains two binaries:
docker-slim
<- the main applicationdocker-slim-sensor
<- the sensor application used to collect information from running containersexamples
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
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 .
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>
.
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
).
curl http://<YOUR_DOCKER_HOST_IP>:<PORT>
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>
commands. The current version of DockerSlim doesn't allow you to map exposed network ports (it works like docker run … -P
).
docker-slim
says it's doneBy 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.
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.
docker run -it --rm --name="slim_node_app" -p 8000:8000 my/sample-node-app.slim
Yes! Either way, you should test your Docker images.
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!
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.
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
. 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:
Dockerfile.fat
)creport.json
)If you don't want to create a minified image and only want to "reverse engineer" the Dockerfile you can use the info
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
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.
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
.
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.
Pick one of the build options that works best for you.
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).
Note:
Use Go 1.13 or higher. 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.
If you have a web browser, you can get a fully pre-configured development environment in one click:
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:
golint
if you intend to run the src.inspect.sh
or mac.src.inspect.command
scripts.If the project sounds interesting or if you found a bug see CONTRIBUTING.md
and submit a PR!
The goal is to auto-generate Seccomp, AppArmor, (and potentially SELinux) profiles based on the collected information.
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.
The WISHLIST
doc includes even more potential improvements.
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 :-)
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 :-)
Apache License v2, see LICENSE for details.
docker-slim 的主要作用是对 docker 镜像进行瘦身的工具。经过瘦身处理的镜像会变小一些甚至变小数倍,且瘦身收仍然可以正常运行。 详情请见官方网站:https://dockersl.im/ 安装 在官网获取最新包的下载地址:https://dockersl.im/install.html,然后执行如下命令安装。 wget https://downloads.dockerslim.co
该帖子中的内容均是在windows环境下进行的操作 准备介质 app.jar springboot框架的一个打包后的应用程序 application.yml 应用程序外置的配置文件 Dockerfile 构建docker镜像的文件 docker-compose.yml 采用docker-compose编排容器服务的文件 在看该帖子的时候,默认我们电脑上是部署了docker环境的,不具备docker
说明 docker-slim 是应用瘦身的工具,官网说压缩可以达30倍,实测有些是可以达到,但是达到的基本不可以使用了(不是用官网提供的镜像另外压缩测试),很多命令工具之类的都删除完了,怎么形容呢,感觉就是为了压缩而压缩,但是好事情是,可以通过排除文件夹或者文件,使其不进行压缩来达到容器正常启动而使用的作用,所以还是有用的,按需而用即可。 docker-slim Jenkins配置示例 步骤
说明 当前为构建的脚本,部署脚本后面有时间再编写然后发出来,然后里面包含容器瘦身工具 docker-slim 的配置,具体的部署使用方式后面再单独写,话不多说,直接上代码(我的风格喜欢直接上代码) docker-slim 使用 代码 # 获取构建 tag version=`git log | head -1 | awk '{print substr($2,0,16)}'` # 瘦身之前构建的名称
docker-composer 一个用于自用的,搭建php运行环境的docker-compose文件及目录结构 关于基础镜像选择 基础镜像一般有两个选择 alpine:3 debain:buster-slim 镜像 大小(压缩过) 大小(未压缩) 描述 alpine:3 2-3M 5M左右 最小的基础镜像,对镜像大小有严格要求的,可以用这个 debain:buster-slim 20-27M 70
今天给大家介绍一下如何基于Docker的nacos/nacos-server:v2.1.2-slim镜像安装nacos 1、Data Source 我们需要从nacos的github官网下载nacos 2.12发布包 nacos-server-2.1.2.tar.gz nacos-server-2.1.2.zip 这里以nacos-server-2.1.2.tar.gz为例来介绍,解压后我们将得到
今天,我们来简要解析一下nacos的nacos/nacos-server:v2.1.2-slim镜像版本做了哪些事。 1、Dockerfile.Slim 我们在nacos官网的Quick Start for Nacos Docker页面可以找了解到github名称为nacos-group/nacos-docker的项目是nacos官方用于维护nacos docker镜像的地方,进入项目主页,我们找
通过如下的文件启动容器后 version: "3.8" services: test: image: python:3.10-slim container_name: test restart: always status一直处于Restarting >>> docker ps CONTAINER ID IMAGE
Dockerfile 中的 VOLUME 挂载与 docker -v 命令挂载,两者有明显区别: 1、VOLUME Dockerfile中 VOLUME 方式挂载到宿主机上的是匿名卷,在宿主机上是自动匿名挂载到 /var/lib/docker/volumes/ 目录下的,代码如下: FROM frolvlad/alpine-java:jre8-slim MAINTAINER oas.cloud C
一、解决的问题 二、与虚拟机的比较 三、优势 四、使用场景 五、镜像与容器 参考资料 一、解决的问题 由于不同的机器有不同的操作系统,以及不同的库和组件,在将一个应用部署到多台机器上需要进行大量的环境配置操作。 Docker 主要解决环境配置问题,它是一种虚拟化技术,对进程进行隔离,被隔离的进程独立于宿主操作系统和其它隔离的进程。使用 Docker 可以不修改应用程序代码,不需要开发人员学习特定环
我检查了垃圾箱,里面没有ping
第一章 Docker介绍1 1.1 docker简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的\[Linux\]机器上,也可以实现\[虚拟化\]。容器是完全使用\[沙箱\]机制,相互之间不会有任何接口。 1.2 Docker是什么? Docker是一个程序运行、测试、交付的开放平台,Docker被设计为能够使你快速地交
推荐使用 Swoole 官方 Docker:https://github.com/swoole/docker-swoole
Docker Commands Commands Notes docker ps -a Show all containers on the system docker ps Show only currently running containers docker run <NAME> Creates & runs a docker container via an image docker i
环境准备 1. 下载镜像及配置文件 链接: https://pan.baidu.com/s/1hw0h1KUlhSirFBId6kh8mw 提取码: 1wng $ ls backend-0.0.8.tar.gz env.list grpc-go-greeting-0.1.tar.gz nginx-lb.conf nginx-perf.conf nginxplus-23-r1.tar.