Smart apt

Install apt packages without writing apt-get update by hand. The run builder inserts an update before the first install and again whenever you add a source that changes the package lists.

Install packages, a PPA, and a third-party repo

from __future__ import annotations

from docker_dsl import Stage
from docker_dsl import context as ctx

ctx.register("with_intel", bool)

with Stage("ubuntu:24.04") as s:
    s.workdir("/root")

    with s.cache("/var/cache/apt", lock=True), s.cache("/var/lib/apt", lock=True), s.run() as r:
        r.apt_install("software-properties-common")
        r.add_apt_ppa("ppa:apt-fast/stable")
        r.apt_install("apt-fast", "curl", "wget", "git", fast=True)

        if ctx.with_intel:
            r.add_apt_repo(
                "https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB",
                "https://apt.repos.intel.com/oneapi all main",
                name="oneapi-archive-keyring",
            )
            r.apt_install("intel-oneapi-mkl-devel", fast=True)

        r("rm -rf /tmp/*")

    s.cmd("bash")

Render it with --with_intel=true:

# syntax=docker/dockerfile:1
FROM ubuntu:24.04 AS base
WORKDIR /root
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked --mount=type=cache,target=/var/lib/apt,sharing=locked \
  apt-get update -y \
  && apt-get install -y --no-install-recommends software-properties-common \
  && add-apt-repository ppa:apt-fast/stable -y \
  && apt-get update -y \
  && apt-fast install -y --no-install-recommends apt-fast curl wget git \
  && wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | gpg --dearmor | tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null \
  && echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | tee /etc/apt/sources.list.d/oneapi-archive-keyring.list \
  && apt-get update -y \
  && apt-fast install -y --no-install-recommends intel-oneapi-mkl-devel \
  && rm -rf /tmp/*

When the update runs

An apt-get update -y appears before the first apt_install. add_apt_ppa and add_apt_repo mark the package lists stale, so the next apt_install runs another update. The output above has two updates, one before the first install and one after the PPA. You never write the update yourself, and it never repeats needlessly.

The apt helpers

  • r.apt_install(*packages, fast=False) installs packages. Pass fast=True to use apt-fast once it is installed.
  • r.add_apt_ppa(ppa) adds a PPA.
  • r.add_apt_repo(key_url, repo_url, name=...) adds a third-party repo, fetches its GPG key, and writes a signed-by source list.

Cache the apt directories with lock=True (as above) so package downloads persist between builds without two builds corrupting the same cache.