Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Overview

conda-dist is a command-line tool that converts a Conda environment manifest into deliverables. It reads a single conda-dist.toml file, resolves the requested packages, and prepares the build artifacts.

Available output families include:

  • Native installers that unpack the environment into a user-specified prefix.
  • OCI container images that embed the environment on top of a minimal base.
  • Native packages (RPM/DEB) built for Linux targets.

The remaining chapters document the manifest format and describe how each backend consumes it.

Configuration Reference

conda-dist reads a single TOML manifest. Every command consumes the same configuration, so you describe the environment once and reuse it for installers, containers, or other outputs. A minimal manifest looks like:

name = "myapp"
version = "1.2.0"
author = "John Doe"
license = "Proprietary"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64"]

[dependencies]
python = "3.11.*"
pandas = "^2.2"

The remaining sections document each supported key, including optional tables for format-specific settings.

Common Settings

These keys apply to every build target and appear at the top level of the manifest.

Required fields

  • name — ASCII string composed of letters, digits, -, _, or .. Used when naming installers, archives, and tags.
  • version — ASCII string without whitespace. Appended to artifact names and container tags.
  • author — Free-form maintainer identifier bundled into metadata.
  • license — License identifier embedded in native package metadata. Defaults to Proprietary if omitted.
  • channels — Non-empty array of Conda channels evaluated in order of precedence.
  • platforms — Non-empty array of Conda platforms (for example linux-64, osx-arm64). Each platform yields a distinct installer executable.

Dependencies

Declare package requirements with a table of Conda match specs:

[dependencies]
python = "3.11.*"
pandas = "^2.2"

Metadata

Populate optional descriptive fields for installers and summary output:

[metadata]
summary = "MyApp command suite"
description = "Command-line utilities for data preparation."
release_notes = "- Initial publication."
featured_packages = ["python", "pandas"]

Virtual packages

conda-dist seeds each platform with sensible defaults for synthetic virtual packages instead of probing the build host. Override values only when you need to pin a specific runtime characteristic.

[virtual_packages.default]
linux = "5.15"
libc = { family = "glibc", version = "2.31" }

[virtual_packages.linux-64]
cuda = "12.2"

Use the default table for cross-platform values and add per-platform tables to override individual targets. Supported keys are linux, osx, win, libc, and cuda.

Package settings

Configure native RPM/DEB packaging:

[package]
split_deps = false
release = "1"

[package.images.rocky]
type = "rpm"
image = "rockylinux:9"

[package.images.ubuntu]
type = "deb"
image = "ubuntu:24.04"

When enabled, split_deps emits a metapackage plus individual native packages for each transitive dependency. The optional release field controls the RPM/DEB release suffix applied to the base package (defaults to 1). Each entry under package.images defines a container image keyed by name; the name is used as the output subdirectory.

Container Settings

[container] configures OCI image output.

[container]
base_image = "gcr.io/distroless/base-debian12"
prefix = "/opt/env"
tag_template = "registry.internal.example.com/analytics/{name}:{version}-py311"
  • base_image (optional) defaults to gcr.io/distroless/base-debian12.
  • prefix (optional) relocates the Conda environment inside the image. Supply an absolute path; the default is /opt/conda.
  • tag_template (optional) renders the final tag. Only {name} and {version} are recognised placeholders. The default template is {name}:{version}.

Container builds emit <name>-container.oci.tar alongside the manifest unless you override the output location on the command line.

Output Formats

Output formats consume the manifest and emit distributable artifacts. Each one reuses the same dependency resolution step, then applies backend-specific packaging.

  • Installers — produce native self-extracting executables per target platform.
  • Container images — stage the environment into a minimal base and output an OCI archive.
  • Native packages — produce RPM and DEB artifacts for Linux distributions.

Subsequent sections describe the behaviour and outputs of each format.

Installers

conda-dist installer <manifest> produces a native self-extracting installer for each target platform.

Usage Example

conda-dist installer app.toml
./app-linux-64 /opt/app
/opt/app/bin/python --version

The command caches downloads and writes one native installer executable per platform (defaulting to <name>-<platform> in the manifest directory). Each installer unpacks the bundled environment into the installation path you provide, with no external runtime requirements.

Characteristics

  • Output: Native executable archive, one per target platform.
  • Installation prefix: User-supplied path, installable anywhere.
  • Runtime dependencies: None required on the target host.
  • Reproducibility: Bundles the locked package set used at build time.
  • Transport: Compressed payload suitable for artifact stores or offline delivery.

Container Images

conda-dist container <manifest> builds an OCI image from the manifest.

Usage Example

conda-dist container app.toml
skopeo copy oci-archive:app-container.oci.tar docker-daemon://app:1.0.0
docker run app:1.0.0 env/bin/python --version

conda-dist container stages the resolved environment on the configured base image and writes an OCI archive (default <name>-container.oci.tar alongside the manifest). The example uses skopeo to load the archive into a Docker daemon; any OCI-aware transport can be substituted.

Characteristics

  • Output: OCI archive suitable for use with Docker, Kubernetes, etc.
  • Base image: Configurable (defaults to gcr.io/distroless/base-debian12).
  • Footprint: Distroless base plus the packaged environment keeps layers minimal.
  • Multi-architecture: Multiple platforms yield a single tag backed by per-platform images.

Native Packages

conda-dist package <manifest> builds RPM and DEB archives for Linux targets.

Usage Example

[package.images.rocky]
type = "rpm"
image = "rockylinux:9"

[package.images.ubuntu]
type = "deb"
image = "ubuntu:24.04"
conda-dist package app.toml

Packages are written beneath <output-dir>/<image-name>/, grouped by the image name from the manifest. The output directory defaults to the manifest directory, and each image directory contains the generated RPM/DEB artifacts.

Use --image <name> to select a subset of images from the manifest.

Characteristics

  • Output: RPM/DEB archives organized per container image.
  • Platforms: Supports all Linux targets listed in the manifest.
  • Images: Works with docker/podman-compatible distribution images.
  • Runtime dependencies: None required on the target host.

CLI Reference

conda-dist

NAME

conda-dist - Build distributable artifacts from Conda environments

SYNOPSIS

conda-dist [–work-dir] [–locked] [–unlock] [–engine] [–engine-flag] [-h|–help] [-V|–version] <subcommands>

DESCRIPTION

Build distributable artifacts from Conda environments

OPTIONS

–work-dir <PATH>
Workspace directory used for cached artifacts (defaults to <manifest>/.conda-dist)

–locked
Require the existing lockfile and skip solving; fails if the lockfile is stale or missing

–unlock
Regenerate the lockfile even if one already exists

–engine <PATH>
Path to the container engine binary (defaults to docker, then podman)

–engine-flag <FLAG>
Extra flags passed directly to the container engine (repeatable)

-h, –help
Print help

-V, –version
Print version

SUBCOMMANDS

conda-dist-lock(1)
Update or validate the lockfile without producing artifacts

conda-dist-installer(1)
Build self-extracting installers

conda-dist-container(1)
Build container images embedding the environment

conda-dist-package(1)
Build native system packages (rpm/deb) using containerized installers

conda-dist-help(1)
Print this message or the help of the given subcommand(s)

VERSION

v0.3.0

conda-dist container

NAME

container - Build container images embedding the environment

SYNOPSIS

conda-dist container [–platform] [–oci-output] [-h|–help] [MANIFEST]

DESCRIPTION

Build container images embedding the environment

OPTIONS

–platform <PLATFORM>
Restrict the build to a single target platform

–oci-output <PATH>
Path to write the resulting OCI archive (defaults to <manifest-dir>/<name>-container.oci.tar)

-h, –help
Print help

[MANIFEST] [default: conda-dist.toml]
Path to the conda-dist manifest (conda-dist.toml)

conda-dist installer

NAME

installer - Build self-extracting installers

SYNOPSIS

conda-dist installer [–output-dir] [–installer-platform] [-h|–help] [MANIFEST]

DESCRIPTION

Build self-extracting installers

OPTIONS

–output-dir <PATH>
Optional directory to write the installer binary

–installer-platform <PLATFORM> [default: all]
Select which installer platform(s) to build

-h, –help
Print help

[MANIFEST] [default: conda-dist.toml]
Path to the conda-dist manifest (conda-dist.toml)

conda-dist lock

NAME

lock - Update or validate the lockfile without producing artifacts

SYNOPSIS

conda-dist lock [-h|–help] [MANIFEST]

DESCRIPTION

Update or validate the lockfile without producing artifacts

OPTIONS

-h, –help
Print help

[MANIFEST] [default: conda-dist.toml]
Path to the conda-dist manifest (conda-dist.toml)

conda-dist package

NAME

package - Build native system packages (rpm/deb) using containerized installers

SYNOPSIS

conda-dist package [–image] [–platform] [–output-dir] [-h|–help] [MANIFEST]

DESCRIPTION

Build native system packages (rpm/deb) using containerized installers

OPTIONS

–image <NAME>
Restrict native packaging to specific image name(s) from the manifest

–platform <PLATFORM>
Restrict native packaging to specific target platform(s) (defaults to host platform)

–output-dir <PATH>
Output directory for generated packages (defaults to <manifest-dir>)

-h, –help
Print help

[MANIFEST] [default: conda-dist.toml]
Path to the conda-dist manifest (conda-dist.toml)

Developer Notes

This section covers conda-dist internals and development notes.

Packaging Implementation

This section documents how conda-dist produces the three output types:

Self-Extracting Installer

Inputs

The installer output combines two inputs:

  • A platform-specific installer binary embedded in the conda-dist build (conda-dist/installers/* compiled into the binary via build.rs).
  • A tar.gz payload containing the staged channel.

Payload Layout

The payload is a gzipped tar archive with a single root directory named after the environment. The archive includes:

  • conda-lock.yml (the lockfile copied into the channel directory).
  • The channel subdirectories: noarch/ and the target platform subdir (for example linux-64/).
  • repodata.json and any other channel index artifacts in the root of each subdir.

Self-Extracting Binary Layout

The final installer file is created by appending metadata and payload data to the installer stub. The layout is:

[installer bytes]
[bundle metadata JSON]
[u64 metadata length, little-endian]
[tar.gz payload bytes]
[u64 payload length, little-endian]
"CONDADIST!"

The embedded metadata JSON matches the bundle metadata from the manifest. The trailing length fields and magic marker allow the installer to find the payload and metadata by reading backward from the end of the executable.

Runtime Behavior

At install time the installer:

  • Reads the embedded metadata and payload length footer from its own executable.
  • Extracts the tar.gz payload to a temporary directory.
  • Loads the lockfile from the extracted channel directory.
  • Uses the extracted channel (a file:// URL) to install the locked environment into the requested prefix.

OCI/Docker Images

Container images are built by running the self-extracting installer during the image build.

Build Behavior

  • Installers are prepared for the requested Linux platforms and staged in the build context.
  • A multi-stage Dockerfile is generated. The first stage holds the installers; the final stage runs the matching installer to materialize the environment at the configured prefix.
  • The image build is multi-platform; each platform run uses its corresponding installer.
  • The resulting image sets CONDA_PREFIX and PATH to the configured prefix.
  • The build output is exported as a multi-architecture OCI archive.

Native Packages (RPM/DEB)

Native packages are built in containers. The build uses a self-extracting installer to materialize the environment inside the container before packaging it.

Build Behavior

  • Installers are prepared for the requested platforms.
  • A per-platform package_plan.tsv describes which native packages to build and where their payloads and metadata live in the packaging workspace.
  • The packaging container receives the installer, the package plan, and an output directory via bind mounts.
  • Inside the container, the packaging script installs the environment via the installer.
  • Inside the container, the script runs rpmbuild or dpkg-deb and writes artifacts to the output directory.

split_deps = false (Single Package)

When split_deps is disabled:

  • The base package contains the full environment payload.
  • No per-dependency subpackages are generated.
  • The resulting RPM/DEB is self-contained.

split_deps = true (One Package per Conda Package)

When split_deps is enabled:

  • The base package is a metapackage with no payload.
  • One dependency package is created per conda package, containing only that package’s files.
  • For Python noarch packages, the native package release is suffixed with the Python major/minor version (for example py311) so builds against different interpreters remain distinct.

To ensure dependency packages are only installed alongside the base metapackage, conda-dist encodes a dependency cycle:

  • The base package depends on each dependency package with exact version+build pins and provides lock-<package> for each dependency.
  • Each dependency package depends on its corresponding lock-<package> virtual provide.

This makes the base package act as the lockfile while still allowing the environment to be split into native packages.

Example dependency cycle (environment name: my-app):

my-app (metapackage)
  Depends: my-app-numpy (= 1.26.4-0), my-app-python (= 3.12.1-0), ...
  Provides: lock-my-app-numpy, lock-my-app-python, ...

my-app-numpy
  Depends: lock-my-app-numpy

my-app-python
  Depends: lock-my-app-python