Dash Platform Docker Development tips
Introduction
This document describes some tips and optimizations needed to speed up build of Docker images. As Docker images are intensively used as part of the Dashmate workflow, these tips will be mainly useful to:
- developers, building Platform directly from git sources,
- Github Actions developers, trying to optimize caching of Docker caching.
When building Dash Platform's Docker images, you can encounter the following issues:
- Docker build without proper caching is relatively slow due to need to rebuild all sources from the scratch
- Building for other architectures using emulation (eg. running ARM64 VM on a x86-64 host) is very slow
- Cross-compiling Platform can be tricky due to some dependency issues (for example, cross-compilation of librocksdb-sys is hard)
- With intensive caching, cache can grow very fast and use more than 10 GB, which is above default cache size limit in Docker buildx and Github Actions.
Caches
We implement the following levels of caching:
- Docker caching: layers and cache mounts (
RUN --mount=type=cache,...
) sccache
Docker-level caching cache mounts
Cache mounts include some cachable elements of RUST_HOME (including downloaded dependencies), as well as Cargo target dir. As the target dir grows to multiple gigabytes, Docker cache garbage collector must be tuned accordingly.
For example, you can create the following Buildkit config file in $HOME/.config/buildkit/buildkitd.toml
:
[worker.oci]
gc = true
gckeepstorage = 40000 # 40 GB
[[worker.oci.gcpolicy]]
all = true
keepBytes = 30000000000 # 30 GB
keepDuration = 432000 # 5 days
and create buildx builder instance:
docker buildx create --config "$HOME/.config/buildkit/buildkitd.toml" --name local --use --bootstrap
Double-check that configured garbage collection policy was correctly applied:
docker exec -ti buildx_buildkit_local0 buildctl debug workers -v
GC Policy rule#0:
All: true
Keep Duration: 120h0m0s
Keep Bytes: 30GB
Sccache
Sccache is an additional layer of caching that can be used to improve build speed. Sccache can cache build artifacts using multiple storage systems, like local filesystem, Github Actions, S3 buckets, memcache, and others.
For local development in Docker, sccache uses Docker cache mounts. Alternative solution can be to use memcached daemon for caching.
Sccache is disabled by default.
Enabling sccache
To enable sccache, set RUSTC_WRAPPER=sccache
build argument when building the Docker image. For example:
docker buildx build --build-arg RUSTC_WRAPPER=sccache --target drive-abci .
Sccache and memcached
To use sccache with memcache, setup local memcached daemon with reasonable amount of RAM (4GB here):
docker run --name memcache -d -p 172.17.0.1:11211:11211 memcached memcached -m 4096 -l 0.0.0.0
docker update --restart unless-stopped memcache
Replace 172.17.0.1
with IP address of the host running memcached accessible from your Docker containers (and not accessible from external networks).
Using memcache with Dashmate
Before starting dashmate build, set SCCACHE_MEMCACHED
to address of your memcache server:
export RUSTC_WRAPPER=sccache
export SCCACHE_MEMCACHED=tcp://172.17.0.1:11211
Using memcache with buildx
Pass SCCACHE_MEMCACHED build argument to Docker Buildx
docker buildx build -f Dockerfile --build-arg SCCACHE_MEMCACHED=tcp://[your.ip.address.here]:11211 --progress=plain --target drive-abci .
Replace 172.17.0.1
with IP address of the host running memcached accessible from your Docker containers.
Using sccache in your IDE
You can also use the same cache for your local builds (eg. in your IDE). To do this, install sccache, and set RUSTC_WRAPPER
environment variable before starting your IDE (on Linux, you can put them into $HOME/.profile
):
export RUSTC_WRAPPER=/usr/local/bin/sccache
If you want your local system to use same cache as docker builds, set SCCACHE_MEMCACHED
:
export SCCACHE_MEMCACHED=tcp://172.17.0.1:11211
If you use Microsoft Visual Studio Code and rust-analyzer, you can add forementioned environment variables to "rust-analyzer.cargo.extraEnv
in your workspace config:
"settings": {
"rust-analyzer.rustfmt.extraArgs": [
"+nightly"
],
"rust-analyzer.cargo.buildScripts.useRustcWrapper": true,
"rust-analyzer.cargo.extraEnv": {
"SCCACHE_MEMCACHED": "tcp://192.168.1.91:11211",
"CARGO_TARGET_DIR": "/home/lklimek/tmp/rust/target"
}
}