cclyzer++ ships with two dockerfiles in docker/:

  • dev.dockerfile has all the tools needed to develop cclyzer++

  • dist.dockerfile contains cclyzer++ and its runtime dependencies

Obtaining Images

Pulling from GHCR

You can pull pre-built images from GHCR like so:

docker pull

The main tag refers to the most recent release. You can also specify a tag or commit SHA of a previous release, e.g.,

# The following are equivalent:
docker pull
docker pull

Building Locally

cd docker
DOCKER_BUILDKIT=1 docker build --tag=cclyzerpp-dev --file=dev.dockerfile ..

To build the dist image, first build cclyzer++ as described in Building. For example, to do so inside the dev image, run this from the source root:

docker run \
  --rm \
  --mount type=bind,src=$PWD,target=/work \
  --workdir /work \
  "" \
  bash -c "cmake -G Ninja -B build -S . && cmake --build build -j $(nproc)"

You should see files in build/. Now, build the dist image:

cd docker
DOCKER_BUILDKIT=1 docker build --tag=cclyzerpp-dist --file=dist.dockerfile ..



This section is mainly of interest to developers of cclyzer++.

This section discusses the trade-offs of different choices made concerning the Docker images.

Multiple Dockerfiles

Using multiple Dockerfiles rather than a multi-stage build with different dev and dist stages enables the use of multiple dockerignores. In a multi-stage build, the dockerignore would have to allow any file used by any stage, whereas with the current setup, each image has its own dockerignore.

Granular dockerignores cause faster builds, as evidenced by lines like the following in the docker build output:

=> transferring context: 2B                   0.0s

This shows that Docker didn’t have to copy any files (the “build context”) to the Docker daemon, making the build that much faster. Furthermore, granular dependencies cause more cache hits.