Container-only builds
Dalec can create minimal container images with only specific packages installed, without building from source code. This is useful for creating minimal container images with just the runtime dependencies you need.
How it Works
When you specify only runtime dependencies in a Dalec spec (no sources or build steps), Dalec creates a Virtual Package and installs it in the target base image. The result is a minimal container with only your specified packages and their dependencies.
Example: Minimal Image with curl and bash
# syntax=ghcr.io/project-dalec/dalec/frontend:latest
name: my-minimal-image
version: 0.1.0
revision: 1
license: MIT
description: A minimal image with only curl and shell access
dependencies:
runtime:
curl:
bash:
image:
entrypoint: /bin/bash
Build the container:
docker build -f my-minimal-image.yml --target=azlinux3 -t my-minimal-image:0.1.0 .
This produces a minimal image built from scratch containing:
curlandbash- Essential packages like
prebuilt-ca-certificatesandtzdata - Dependencies of the specified packages
The --target=azlinux3 flag tells Dalec to use Azure Linux 3 repositories for package installation, even though the final image starts from scratch.
Alternatively, you can omit creating a Dalec spec file by passing the dependencies directly in the command line. This is useful for quick builds without needing a spec file.
docker build -t my-minimal-image:0.1.0 --build-arg BUILDKIT_SYNTAX=ghcr.io/project-dalec/dalec/frontend:latest --target=azlinux3/container/depsonly -<<<"$(jq -c '.dependencies.runtime = {"curl": {}, "bash": {}} | .image.entrypoint = "/bin/bash"' <<<"{}" )"
Cleanup policy for Debian/Ubuntu minimal images
Debian- and Ubuntu-based minimal container targets (for example trixie/container, bookworm/container, noble/container) run a post-install cleanup pass that strips the image down to just what the spec needs. The policy is intentionally aggressive and all-or-nothing per directory tree:
/usr/share/doc,/usr/share/man,/usr/share/info— preserved only when the spec declares at least onedocs,manpages, orlicensesartifact. If preserved, all dependency-owned content under those paths is also retained (the cleanup does not attempt to filter dependency files). If pruned, all content under those paths is removed, including any manpages orcopyrightfiles shipped by runtime dependencies./etc/systemd,/var/lib/systemd— preserved only when the final image actually has thesystemdpackage installed (orsystemctlonPATH)./var/log— the directory itself is always preserved, but its contents are emptied. Many runtime processes assume/var/logexists.- Package manager state and caches (
/etc/apt,/var/cache/apt,/var/lib/apt,/usr/lib/apt,/var/lib/pam,/var/cache/debconf,/usr/share/{bash-completion,bug,debconf,lintian,locale}) — always removed.
Implication for spec authors
If you want the final image to ship with manpages, the changelog, or copyright files for any package — your own or a dependency's — declare at least one docs, manpages, or licenses artifact in your spec. A single license file is enough to flip the toggle:
artifacts:
licenses:
LICENSE:
This preserves /usr/share/doc wholesale, so dependency-shipped copyright files (and any other dependency-owned content under the doc/man/info trees) will also remain in the image.
If you specifically want a leaner image with no dependency-owned docs but you need your own license files present, that is still the result of declaring licenses — the cleanup script does not currently support a more granular policy. If you need full control over which files are kept, use the non-minimal container target instead (for example trixie/testing/container), where this cleanup pass does not run.