Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ All notable changes to pythainer will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- `apt_mirror` parameter on `get_user_builder()` and `get_min_user_builder()`
(and reusable `switch_apt_mirror()` helper) to swap the default Ubuntu APT
mirror before the first `apt-get update`, which is useful when
`archive.ubuntu.com` is slow or under incident. A common choice is
`mirror://mirrors.ubuntu.com/mirrors.txt` for automatic geographic
mirror selection. `security.ubuntu.com` is left untouched.

## [0.0.7] - 2026-03-28

### Added
Expand Down
64 changes: 64 additions & 0 deletions src/pythainer/examples/builders/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,52 @@
from pythainer.examples.installs import clspv_build_install


def switch_apt_mirror(
builder: UbuntuDockerBuilder,
apt_mirror: str,
) -> None:
"""
Replace the default ``archive.ubuntu.com/ubuntu/`` URL in the APT sources
of the base image with ``apt_mirror``.

Call this **before** the first ``apt-get update`` so that subsequent
installs use the new mirror. Both source formats are handled:

* the DEB822 file ``/etc/apt/sources.list.d/ubuntu.sources`` used by
Ubuntu 24.04 (noble) and later,
* the classic ``/etc/apt/sources.list`` used by earlier releases.

``security.ubuntu.com/ubuntu/`` is left untouched so security updates
continue to come from Canonical directly.

A common choice is Ubuntu's geographic mirror auto-selector,
``mirror://mirrors.ubuntu.com/mirrors.txt``, which returns a
proximity-sorted list of mirrors at install time.

Parameters:
builder (UbuntuDockerBuilder):
An initialized Docker builder targeting an Ubuntu-based image.
The builder is mutated in-place.
apt_mirror (str):
Base URL substituted for ``http://archive.ubuntu.com/ubuntu/``
in the APT sources (e.g.
``mirror://mirrors.ubuntu.com/mirrors.txt``,
``http://be.archive.ubuntu.com/ubuntu/``).
"""
archive = "http://archive.ubuntu.com/ubuntu/"
builder.desc(f"Switch APT mirror to {apt_mirror}")
builder.run(
command=(
"for f in /etc/apt/sources.list.d/ubuntu.sources "
"/etc/apt/sources.list; do "
'[ -f "$f" ] && '
f"sed -i 's|{archive}|{apt_mirror}|g' \"$f\"; "
"done"
),
)
builder.space()


def configure_ubuntu_user(
builder: UbuntuDockerBuilder,
user_name: str,
Expand Down Expand Up @@ -111,6 +157,7 @@ def get_user_builder(
lib_dir: str = "/home/${USER_NAME}/workspace/libraries",
cmake_version: str = "3.27.9",
packages: List[str] = (),
apt_mirror: str | None = None,
) -> UbuntuDockerBuilder:
"""
Creates a customized Docker builder with a non-root user and general
Expand All @@ -124,6 +171,11 @@ def get_user_builder(
lib_dir (str): Directory for libraries and tools.
cmake_version (str): Version of CMake to install.
packages (List[str]): Additional packages to install in the Docker image.
apt_mirror (str | None):
Optional URL substituted for ``http://archive.ubuntu.com/ubuntu/``
in the APT sources before the first ``apt-get update`` (e.g.
``mirror://mirrors.ubuntu.com/mirrors.txt``). If ``None``, the
base image's default mirror is used.

Returns:
UbuntuDockerBuilder: A configured Docker builder instance with a non-root user.
Expand All @@ -138,6 +190,9 @@ def get_user_builder(
docker_builder.env(name="DEBIAN_FRONTEND", value="noninteractive")
docker_builder.space()

if apt_mirror is not None:
switch_apt_mirror(builder=docker_builder, apt_mirror=apt_mirror)

docker_builder.add_packages(
packages=[
"apt-utils",
Expand Down Expand Up @@ -272,6 +327,7 @@ def get_min_user_builder(
user_name: str = "user",
lib_dir: str = "/home/${USER_NAME}/workspace/libraries",
packages: list[str] = (),
apt_mirror: str | None = None,
) -> UbuntuDockerBuilder:
"""
Create a minimal Ubuntu-based Docker builder with a non-root user.
Expand Down Expand Up @@ -300,6 +356,11 @@ def get_min_user_builder(
packages (list[str]):
Optional additional Ubuntu packages to install on top of the minimal
default package set.
apt_mirror (str | None):
Optional URL substituted for ``http://archive.ubuntu.com/ubuntu/``
in the APT sources before the first ``apt-get update`` (e.g.
``mirror://mirrors.ubuntu.com/mirrors.txt``). If ``None``, the
base image's default mirror is used.

Returns:
UbuntuDockerBuilder:
Expand All @@ -316,6 +377,9 @@ def get_min_user_builder(
docker_builder.env(name="DEBIAN_FRONTEND", value="noninteractive")
docker_builder.space()

if apt_mirror is not None:
switch_apt_mirror(builder=docker_builder, apt_mirror=apt_mirror)

docker_builder.add_packages(
packages=[
"apt-utils",
Expand Down
Loading