From 6347d5e065813e372cf389c6efa92bf0783d538a Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Wed, 19 Nov 2025 15:26:48 +0100 Subject: [PATCH 01/14] feat(justfile): pick latest git release via version="latest-git-tag" --- justfile | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/justfile b/justfile index da01125..a0b65b5 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,14 @@ version := '' image := 'ghcr.io/linkerd/dev' -_tag := if version != '' { "--tag=" + image + ':' + version } else { "" } + +# Auto-detect latest git version if version is 'latest-git-tag' +_version := if version == 'latest-git-tag' { + shell('which git > /dev/null || (echo >&2 "$1error$2: git not available" && exit 1) && git --git-dir="$3/.git" --work-tree="$3" tag -l --sort=-version:refname "v*" | head -n 1', style('error'), NORMAL, justfile_directory()) +} else { + version +} + +_tag := if _version != '' { "--tag=" + image + ':' + _version } else { "" } k3s-image := 'docker.io/rancher/k3s' @@ -26,7 +34,7 @@ build: && _list-if-load for tgt in {{ targets }} ; do just output='{{ output }}' \ image='{{ image }}' \ - version='{{ version }}' \ + version='{{ _version }}' \ _target "$tgt" done @@ -36,22 +44,22 @@ _list-if-load: if [ '{{ load }}' = 'true' ] ; then just image='{{ image }}' \ targets='{{ targets }}' \ - version='{{ version }}' \ + version='{{ _version }}' \ list fi list: #!/usr/bin/env bash set -euo pipefail - if [ -z '{{ version }}' ]; then + if [ -z '{{ _version }}' ]; then echo "Usage: just version= list" >&2 exit 64 fi for tgt in {{ targets }} ; do if [ "$tgt" == "devcontainer" ]; then - docker image ls {{ image }}:{{ version }} | sed 1d + docker image ls {{ image }}:{{ _version }} | sed 1d else - docker image ls {{ image }}:{{ version }}-$tgt | sed 1d + docker image ls {{ image }}:{{ _version }}-$tgt | sed 1d fi done @@ -100,8 +108,9 @@ _target target='': @just \ output='{{ output }}' \ image='{{ image }}' \ + version='{{ _version }}' \ _build --target='{{ target }}' \ - {{ if version == '' { '' } else { '--tag=' + image + ':' + version + if target == 'devcontainer' { '' } else { '-' + target } } }} + {{ if _version == '' { '' } else { '--tag=' + image + ':' + _version + if target == 'devcontainer' { '' } else { '-' + target } } }} # Build the devcontainer image _build *args='': From 0214db78b266a4640317c29624489d0b98674573 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Wed, 19 Nov 2025 18:55:25 +0100 Subject: [PATCH 02/14] feat(justfile): allow passing in additional docker args to build --- justfile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/justfile b/justfile index a0b65b5..7c0b39e 100644 --- a/justfile +++ b/justfile @@ -28,14 +28,15 @@ export DOCKER_PROGRESS := env_var_or_default('DOCKER_PROGRESS', 'auto') all: sync-k3s-images build -build: && _list-if-load +build *args='': && _list-if-load #!/usr/bin/env bash set -euo pipefail for tgt in {{ targets }} ; do just output='{{ output }}' \ image='{{ image }}' \ version='{{ _version }}' \ - _target "$tgt" + _target "$tgt" \ + {{ args }} done _list-if-load: @@ -104,13 +105,14 @@ _k3s-channels: | {key:.id, value:$tag} ] | from_entries' -_target target='': +_target target='' *args='': @just \ output='{{ output }}' \ image='{{ image }}' \ version='{{ _version }}' \ _build --target='{{ target }}' \ - {{ if _version == '' { '' } else { '--tag=' + image + ':' + _version + if target == 'devcontainer' { '' } else { '-' + target } } }} + {{ if _version == '' { '' } else { '--tag=' + image + ':' + _version + if target == 'devcontainer' { '' } else { '-' + target } } }} \ + {{ args }} # Build the devcontainer image _build *args='': From 20dad45e664e08e3d7e3ef404f6d80fc952184e5 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Wed, 19 Nov 2025 15:44:11 +0100 Subject: [PATCH 03/14] feat(Dockerfile): install arch-specific versions of tools --- Dockerfile | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0847b4a..47bc920 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,8 +39,9 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update # j5j Turns JSON5 into plain old JSON (i.e. to be processed by jq). FROM apt-base as j5j -ARG J5J_VERSION=v0.2.0 # repo=olix0r/j5j -RUN url="https://github.com/olix0r/j5j/releases/download/${J5J_VERSION}/j5j-${J5J_VERSION}-x86_64-unknown-linux-musl.tar.gz" ; \ +ARG J5J_VERSION=v0.2.1 # repo=unleashed/j5j +RUN arch=$(uname -m); \ + url="https://github.com/unleashed/j5j/releases/download/${J5J_VERSION}/j5j-${J5J_VERSION}-${arch}-unknown-linux-musl.tar.gz" ; \ scurl "$url" | tar zvxf - -C /usr/local/bin j5j # just runs build/test recipes. Like `make` but a bit more ergonomic. @@ -75,7 +76,8 @@ RUN url="https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz" ; \ # helm-docs generates documentation from helm charts. FROM apt-base as helm-docs ARG HELM_DOCS_VERSION=v1.14.2 # repo=norwoodj/helm-docs -RUN url="https://github.com/norwoodj/helm-docs/releases/download/$HELM_DOCS_VERSION/helm-docs_${HELM_DOCS_VERSION#v}_Linux_x86_64.tar.gz" ; \ +RUN arch=$(uname -m | sed -e 's/aarch/arm/'); \ + url="https://github.com/norwoodj/helm-docs/releases/download/$HELM_DOCS_VERSION/helm-docs_${HELM_DOCS_VERSION#v}_Linux_${arch}.tar.gz" ; \ scurl "$url" | tar xzvf - -C /usr/local/bin helm-docs # kubectl controls kubernetes clusters. @@ -153,7 +155,8 @@ RUN url="https://github.com/google/protobuf/releases/download/$PROTOC_VERSION/pr # cargo-action-fmt formats `cargo build` JSON output to Github Actions annotations. FROM apt-base as cargo-action-fmt ARG CARGO_ACTION_FMT_VERSION=v1.0.4 # ignore -RUN url="https://github.com/olix0r/cargo-action-fmt/releases/download/release%2F${CARGO_ACTION_FMT_VERSION}/cargo-action-fmt-${CARGO_ACTION_FMT_VERSION}-x86_64-unknown-linux-musl.tar.gz" ; \ +RUN arch=$(uname -m); \ + url="https://github.com/olix0r/cargo-action-fmt/releases/download/release%2F${CARGO_ACTION_FMT_VERSION}/cargo-action-fmt-${CARGO_ACTION_FMT_VERSION}-${arch}-unknown-linux-musl.tar.gz" ; \ scurl "$url" | tar zvxf - -C /usr/local/bin cargo-action-fmt FROM apt-base as cargo-auditable From 0c685e003c500d40b38d41060964e56ef7a08d7e Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Wed, 19 Nov 2025 15:48:01 +0100 Subject: [PATCH 04/14] feat(Dockerfile): install docker-compose explicitly Previously the devcontainer build infrastructure would install docker-compose in the container via scripts, but that script ended up requiring global changes to Python code in order to install docker-compose. Now we just install it here to avoid that problem. --- Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Dockerfile b/Dockerfile index 47bc920..9a52e70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -385,6 +385,12 @@ RUN --mount=type=cache,from=apt-llvm,source=/etc/apt,target=/etc/apt,ro \ ENV CC=clang-19 \ CXX=clang++-19 +# Install docker-compose since it breaks in the docker-debian script on arm64 +RUN --mount=type=cache,id=apt-docker,from=apt-base,source=/etc/apt,target=/etc/apt \ + --mount=type=cache,id=apt-docker,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ + --mount=type=cache,id=apt-docker,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ + DEBIAN_FRONTEND=noninteractive apt-get install -y docker-compose + # Use microsoft's Docker setup script to install the Docker CLI. # # A distinct cache is used because the script adds an apt repo that we don't From 8ca4a06e94773a1d13cb9b7743e488d9e63cd04e Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Wed, 19 Nov 2025 15:59:17 +0100 Subject: [PATCH 05/14] feat(justfile): support specifying architecture via docker_arch --- justfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/justfile b/justfile index 7c0b39e..34a0c34 100644 --- a/justfile +++ b/justfile @@ -12,6 +12,8 @@ _tag := if _version != '' { "--tag=" + image + ':' + _version } else { "" } k3s-image := 'docker.io/rancher/k3s' +docker_arch := '' + targets := 'go rust rust-musl tools devcontainer' load := 'false' @@ -35,6 +37,7 @@ build *args='': && _list-if-load just output='{{ output }}' \ image='{{ image }}' \ version='{{ _version }}' \ + docker_arch='{{ docker_arch }}' \ _target "$tgt" \ {{ args }} done @@ -110,6 +113,7 @@ _target target='' *args='': output='{{ output }}' \ image='{{ image }}' \ version='{{ _version }}' \ + docker_arch='{{ docker_arch }}' \ _build --target='{{ target }}' \ {{ if _version == '' { '' } else { '--tag=' + image + ':' + _version + if target == 'devcontainer' { '' } else { '-' + target } } }} \ {{ args }} @@ -119,6 +123,7 @@ _build *args='': docker buildx build . {{ _tag }} --pull \ --progress='{{ DOCKER_PROGRESS }}' \ --output='{{ output }}' \ + {{ if docker_arch != '' { '--platform=' + docker_arch } else { '' } }} \ {{ args }} From 96321c837c5ae69da5b005aae0697555586e390f Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Wed, 19 Nov 2025 16:16:01 +0100 Subject: [PATCH 06/14] feat(justfile): use dry_run=true to print but avoid executing docker commands --- justfile | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/justfile b/justfile index 34a0c34..c374ae2 100644 --- a/justfile +++ b/justfile @@ -12,6 +12,7 @@ _tag := if _version != '' { "--tag=" + image + ':' + _version } else { "" } k3s-image := 'docker.io/rancher/k3s' +dry_run := 'false' docker_arch := '' targets := 'go rust rust-musl tools devcontainer' @@ -38,6 +39,7 @@ build *args='': && _list-if-load image='{{ image }}' \ version='{{ _version }}' \ docker_arch='{{ docker_arch }}' \ + dry_run='{{ dry_run }}' \ _target "$tgt" \ {{ args }} done @@ -61,10 +63,17 @@ list: fi for tgt in {{ targets }} ; do if [ "$tgt" == "devcontainer" ]; then - docker image ls {{ image }}:{{ _version }} | sed 1d + cmd="docker image ls {{ image }}:{{ _version }} | sed 1d" else - docker image ls {{ image }}:{{ _version }}-$tgt | sed 1d + cmd="docker image ls {{ image }}:{{ _version }}-$tgt | sed 1d" fi + + echo "{{ style('error') }}$cmd{{ NORMAL }}" + if [ "{{ dry_run }}" = "true" ]; then + continue + fi + + eval "$cmd" done # Fetch the latest version of k3s images and record their tags and digests. @@ -114,17 +123,28 @@ _target target='' *args='': image='{{ image }}' \ version='{{ _version }}' \ docker_arch='{{ docker_arch }}' \ + dry_run='{{ dry_run }}' \ _build --target='{{ target }}' \ {{ if _version == '' { '' } else { '--tag=' + image + ':' + _version + if target == 'devcontainer' { '' } else { '-' + target } } }} \ {{ args }} # Build the devcontainer image _build *args='': - docker buildx build . {{ _tag }} --pull \ + #!/usr/bin/env bash + set -euo pipefail + + cmd="docker buildx build . {{ _tag }} --pull \ --progress='{{ DOCKER_PROGRESS }}' \ --output='{{ output }}' \ {{ if docker_arch != '' { '--platform=' + docker_arch } else { '' } }} \ - {{ args }} + {{ args }}" + + echo "{{ style('error') }}$cmd{{ NORMAL }}" + if [ "{{ dry_run }}" = "true" ]; then + exit 0 + fi + + eval "$cmd" md-lint *patterns="'**/*.md' '!repos/**'": From 9cf9466f16b752418e49424621c3ad341a54b857 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Wed, 19 Nov 2025 16:25:43 +0100 Subject: [PATCH 07/14] feat(justfile): add podman support --- justfile | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/justfile b/justfile index c374ae2..05cf4fe 100644 --- a/justfile +++ b/justfile @@ -15,17 +15,32 @@ k3s-image := 'docker.io/rancher/k3s' dry_run := 'false' docker_arch := '' +# Detect docker_bin if not specified: try docker first, then podman +docker_bin := shell('which docker 2> /dev/null || which podman 2> /dev/null || (echo >&2 "$1error$2: neither docker nor podman found" && exit 1)', style('error'), NORMAL) +# Extract basename of docker_bin to identify implementation +_docker_bin_name := file_name(docker_bin) +# Auto-detect if podman is in remote mode (unless explicitly overridden) +podman_remote := if _docker_bin_name == 'podman' { + shell('if $1 info 2>/dev/null | grep -q "remoteSocket"; then echo "true"; else echo "false"; fi', docker_bin) +} else { + 'false' +} + targets := 'go rust rust-musl tools devcontainer' load := 'false' push := 'false' -output := if push == 'true' { - 'type=registry' - } else if load == 'true' { - 'type=docker' - } else { - 'type=image' - } + +# Remote mode cannot use the --output flag +output := if podman_remote == 'true' { + '' +} else if push == 'true' { + '--output=type=registry' +} else if load == 'true' { + '--output=type=docker' +} else { + '--output=type=image' +} export DOCKER_PROGRESS := env_var_or_default('DOCKER_PROGRESS', 'auto') @@ -40,6 +55,8 @@ build *args='': && _list-if-load version='{{ _version }}' \ docker_arch='{{ docker_arch }}' \ dry_run='{{ dry_run }}' \ + docker_bin='{{ docker_bin }}' \ + podman_remote='{{ podman_remote }}' \ _target "$tgt" \ {{ args }} done @@ -63,9 +80,9 @@ list: fi for tgt in {{ targets }} ; do if [ "$tgt" == "devcontainer" ]; then - cmd="docker image ls {{ image }}:{{ _version }} | sed 1d" + cmd="{{ docker_bin }} image ls {{ image }}:{{ _version }} | sed 1d" else - cmd="docker image ls {{ image }}:{{ _version }}-$tgt | sed 1d" + cmd="{{ docker_bin }} image ls {{ image }}:{{ _version }}-$tgt | sed 1d" fi echo "{{ style('error') }}$cmd{{ NORMAL }}" @@ -124,6 +141,8 @@ _target target='' *args='': version='{{ _version }}' \ docker_arch='{{ docker_arch }}' \ dry_run='{{ dry_run }}' \ + docker_bin='{{ docker_bin }}' \ + podman_remote='{{ podman_remote }}' \ _build --target='{{ target }}' \ {{ if _version == '' { '' } else { '--tag=' + image + ':' + _version + if target == 'devcontainer' { '' } else { '-' + target } } }} \ {{ args }} @@ -133,9 +152,9 @@ _build *args='': #!/usr/bin/env bash set -euo pipefail - cmd="docker buildx build . {{ _tag }} --pull \ + cmd="{{ docker_bin }} buildx build . {{ _tag }} --pull \ --progress='{{ DOCKER_PROGRESS }}' \ - --output='{{ output }}' \ + {{ output }} \ {{ if docker_arch != '' { '--platform=' + docker_arch } else { '' } }} \ {{ args }}" From f2559c067226bb94067ac1f24abf52107a4a4bda Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Wed, 19 Nov 2025 16:35:57 +0100 Subject: [PATCH 08/14] feat(justfile): add pull_policy argument so we avoid hitting limits This is set to never with podman since I'm still experimenting. --- justfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/justfile b/justfile index 05cf4fe..4356eab 100644 --- a/justfile +++ b/justfile @@ -26,6 +26,13 @@ podman_remote := if _docker_bin_name == 'podman' { 'false' } +# pull policy +_pull_policy := if _docker_bin_name == 'podman' { + '=never' +} else { + '' +} + targets := 'go rust rust-musl tools devcontainer' load := 'false' @@ -152,7 +159,7 @@ _build *args='': #!/usr/bin/env bash set -euo pipefail - cmd="{{ docker_bin }} buildx build . {{ _tag }} --pull \ + cmd="{{ docker_bin }} buildx build . {{ _tag }} --pull{{ _pull_policy }} \ --progress='{{ DOCKER_PROGRESS }}' \ {{ output }} \ {{ if docker_arch != '' { '--platform=' + docker_arch } else { '' } }} \ From 06b24553d5f1345e8e268ff2d9533ba08b4ad39e Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Wed, 19 Nov 2025 15:44:57 +0100 Subject: [PATCH 09/14] feat(justfile, Dockerfile): make apt cache sharing configurable This is useful to avoid locking the cache, which is desirable if using buildah, since it has had bugs around this feature. The tradeoff is that you could potentially find locking issues if running multiple parallel apt commands (such as in CI). --- Dockerfile | 38 ++++++++++++++++++++------------------ justfile | 8 ++++++++ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9a52e70..a77ad34 100644 --- a/Dockerfile +++ b/Dockerfile @@ -267,11 +267,13 @@ COPY --link --from=tools-script /bin/* /bin/ ## Base images ## +ARG APT_CACHE_SHARING=",sharing=locked" + # A Go build environment. FROM docker.io/library/golang:${GO_TAG} as go RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ DEBIAN_FRONTEND=noninteractive apt-get install -y file jo jq COPY --link --from=tools-script /bin/* /usr/local/bin/ COPY --link --from=tools-go /bin/* /usr/local/bin/ @@ -284,8 +286,8 @@ ENV PROTOC_NO_VENDOR=1 \ # A Rust build environment. FROM docker.io/library/rust:${RUST_TAG}-slim-bookworm as rust RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ cmake \ curl \ @@ -297,8 +299,8 @@ RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ libssl-dev \ pkg-config RUN --mount=type=cache,from=apt-llvm,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ DEBIAN_FRONTEND=noninteractive apt-get install -y clang-19 llvm-19 RUN rustup component add clippy rustfmt COPY --link --from=tools-lint /bin/checksec /usr/local/bin/ @@ -322,8 +324,8 @@ RUN rustup target add \ aarch64-unknown-linux-musl \ x86_64-unknown-linux-musl RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ binutils-aarch64-linux-gnu \ g++-aarch64-linux-gnu \ @@ -336,8 +338,8 @@ RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ FROM docker.io/library/debian:bookworm as devcontainer RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ cmake \ curl \ @@ -374,13 +376,13 @@ RUN groupadd --gid=1000 code \ # git v2.34+ has new subcommands and supports code signing via SSH. RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ DEBIAN_FRONTEND=noninteractive apt-get install -y -t bookworm-backports git RUN --mount=type=cache,from=apt-llvm,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ DEBIAN_FRONTEND=noninteractive apt-get install -y clang-19 llvm-19 ENV CC=clang-19 \ CXX=clang++-19 @@ -398,16 +400,16 @@ RUN --mount=type=cache,id=apt-docker,from=apt-base,source=/etc/apt,target=/etc/a # # TODO(ver): replace this with a devcontainer feature? RUN --mount=type=cache,id=apt-docker,from=apt-base,source=/etc/apt,target=/etc/apt \ - --mount=type=cache,id=apt-docker,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,id=apt-docker,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,id=apt-docker,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ + --mount=type=cache,id=apt-docker,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ --mount=type=bind,from=tools,source=/bin/scurl,target=/usr/local/bin/scurl \ scurl https://raw.githubusercontent.com/microsoft/vscode-dev-containers/main/script-library/docker-debian.sh | bash -s ENV DOCKER_BUILDKIT=1 ARG MARKDOWNLINT_VERSION=0.22.1 RUN --mount=type=cache,from=apt-node,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-node,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-node,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-node,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-node,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs RUN npm install "markdownlint-cli2@${MARKDOWNLINT_VERSION}" --global diff --git a/justfile b/justfile index 4356eab..5f1d9b6 100644 --- a/justfile +++ b/justfile @@ -33,6 +33,13 @@ _pull_policy := if _docker_bin_name == 'podman' { '' } +# apt cache sharing mode hits a bug in buildah +_apt_cache_sharing := if _docker_bin_name == 'podman' { + '' +} else { + ',sharing=locked' +} + targets := 'go rust rust-musl tools devcontainer' load := 'false' @@ -163,6 +170,7 @@ _build *args='': --progress='{{ DOCKER_PROGRESS }}' \ {{ output }} \ {{ if docker_arch != '' { '--platform=' + docker_arch } else { '' } }} \ + --build-arg APT_CACHE_SHARING={{ _apt_cache_sharing }} \ {{ args }}" echo "{{ style('error') }}$cmd{{ NORMAL }}" From c958e1ce40a9ccc4f6c51c546ee0c30a23c4e213 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Ruiz Date: Wed, 19 Nov 2025 19:06:07 +0100 Subject: [PATCH 10/14] Revert "feat(justfile, Dockerfile): make apt cache sharing configurable" This reverts commit 27ab1a5333cc5c5af743c6878f42da23aa5050bf. --- Dockerfile | 38 ++++++++++++++++++-------------------- justfile | 8 -------- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/Dockerfile b/Dockerfile index a77ad34..9a52e70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -267,13 +267,11 @@ COPY --link --from=tools-script /bin/* /bin/ ## Base images ## -ARG APT_CACHE_SHARING=",sharing=locked" - # A Go build environment. FROM docker.io/library/golang:${GO_TAG} as go RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y file jo jq COPY --link --from=tools-script /bin/* /usr/local/bin/ COPY --link --from=tools-go /bin/* /usr/local/bin/ @@ -286,8 +284,8 @@ ENV PROTOC_NO_VENDOR=1 \ # A Rust build environment. FROM docker.io/library/rust:${RUST_TAG}-slim-bookworm as rust RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ cmake \ curl \ @@ -299,8 +297,8 @@ RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ libssl-dev \ pkg-config RUN --mount=type=cache,from=apt-llvm,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ - --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y clang-19 llvm-19 RUN rustup component add clippy rustfmt COPY --link --from=tools-lint /bin/checksec /usr/local/bin/ @@ -324,8 +322,8 @@ RUN rustup target add \ aarch64-unknown-linux-musl \ x86_64-unknown-linux-musl RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ binutils-aarch64-linux-gnu \ g++-aarch64-linux-gnu \ @@ -338,8 +336,8 @@ RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ FROM docker.io/library/debian:bookworm as devcontainer RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ cmake \ curl \ @@ -376,13 +374,13 @@ RUN groupadd --gid=1000 code \ # git v2.34+ has new subcommands and supports code signing via SSH. RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y -t bookworm-backports git RUN --mount=type=cache,from=apt-llvm,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ - --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y clang-19 llvm-19 ENV CC=clang-19 \ CXX=clang++-19 @@ -400,16 +398,16 @@ RUN --mount=type=cache,id=apt-docker,from=apt-base,source=/etc/apt,target=/etc/a # # TODO(ver): replace this with a devcontainer feature? RUN --mount=type=cache,id=apt-docker,from=apt-base,source=/etc/apt,target=/etc/apt \ - --mount=type=cache,id=apt-docker,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ - --mount=type=cache,id=apt-docker,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ + --mount=type=cache,id=apt-docker,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,id=apt-docker,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ --mount=type=bind,from=tools,source=/bin/scurl,target=/usr/local/bin/scurl \ scurl https://raw.githubusercontent.com/microsoft/vscode-dev-containers/main/script-library/docker-debian.sh | bash -s ENV DOCKER_BUILDKIT=1 ARG MARKDOWNLINT_VERSION=0.22.1 RUN --mount=type=cache,from=apt-node,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-node,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ - --mount=type=cache,from=apt-node,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ + --mount=type=cache,from=apt-node,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-node,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs RUN npm install "markdownlint-cli2@${MARKDOWNLINT_VERSION}" --global diff --git a/justfile b/justfile index 5f1d9b6..4356eab 100644 --- a/justfile +++ b/justfile @@ -33,13 +33,6 @@ _pull_policy := if _docker_bin_name == 'podman' { '' } -# apt cache sharing mode hits a bug in buildah -_apt_cache_sharing := if _docker_bin_name == 'podman' { - '' -} else { - ',sharing=locked' -} - targets := 'go rust rust-musl tools devcontainer' load := 'false' @@ -170,7 +163,6 @@ _build *args='': --progress='{{ DOCKER_PROGRESS }}' \ {{ output }} \ {{ if docker_arch != '' { '--platform=' + docker_arch } else { '' } }} \ - --build-arg APT_CACHE_SHARING={{ _apt_cache_sharing }} \ {{ args }}" echo "{{ style('error') }}$cmd{{ NORMAL }}" From d14731333e1e0fd1ebba43df58a316f947446385 Mon Sep 17 00:00:00 2001 From: Raymond Kroeker Date: Thu, 9 Jul 2026 12:11:24 -0700 Subject: [PATCH 11/14] feat(arm64): upgrade the container Use the latest stable version of debian (trixie) resulting in some cascading changes. Add llvm's repo key without using the removed 'add-key' binary. This *also* bumps the version of llvm from bookworm-19 to trixie-22. Drop j5j from a curl install to using 'node-json5' available from the debian repo. It is a drop-in replacement for j5j that strips json5 and outputs base json. Install just and yq from the deb repo vs from a url. Install git from default deb repo vs backports. Install docker using devcontainer/features versus from legacy microsoft repo. 'origin/amr/multiarch-and-podman-support'. --- Dockerfile | 49 +++++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/Dockerfile b/Dockerfile index 9a52e70..d8bf6e6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,13 +7,13 @@ ARG GO_TAG=1.26 ARG RUST_TAG=1.90.0 +ARG DEBIAN_RELEASE=trixie # These layers include Debian apt caches, so layers that extend `apt-base` # should not be published. Instead, these layers should be used to provide # cached data to individual `RUN` commands. -FROM docker.io/library/debian:bookworm-slim as apt-base -RUN echo 'deb http://deb.debian.org/debian bookworm-backports main' >>/etc/apt/sources.list +FROM docker.io/library/debian:${DEBIAN_RELEASE}-backports AS apt-base RUN DEBIAN_FRONTEND=noninteractive apt-get update RUN DEBIAN_FRONTEND=noninteractive apt-get install -y curl unzip xz-utils COPY --link bin/scurl /usr/local/bin/ @@ -28,21 +28,26 @@ RUN apt-get update && apt-get install nodejs -y # See https://apt.llvm.org/. FROM apt-base as apt-llvm RUN DEBIAN_FRONTEND=noninteractive apt-get install -y gnupg2 -RUN curl --tlsv1.2 -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key |apt-key add - -RUN ( echo 'deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-19 main' \ - && echo 'deb-src http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-19 main' ) >> /etc/apt/sources.list +RUN /usr/bin/curl --tlsv1.2 -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key |/usr/bin/tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + +ARG DEBIAN_RELEASE +# https://docs.docker.com/reference/dockerfile#understand-how-arg-and-from-interact +# ^ declare arg to use the default value in RUN below +RUN ( echo "deb http://apt.llvm.org/${DEBIAN_RELEASE}/ llvm-toolchain-${DEBIAN_RELEASE}-22 main" \ + && echo "deb-src http://apt.llvm.org/${DEBIAN_RELEASE}/ llvm-toolchain-${DEBIAN_RELEASE}-22 main" ) > /etc/apt/sources.list.d/llvm-toolchain.list +RUN cat /etc/apt/sources.list.d/llvm-toolchain.list RUN DEBIAN_FRONTEND=noninteractive apt-get update ## ## Scripting tools ## -# j5j Turns JSON5 into plain old JSON (i.e. to be processed by jq). -FROM apt-base as j5j -ARG J5J_VERSION=v0.2.1 # repo=unleashed/j5j -RUN arch=$(uname -m); \ - url="https://github.com/unleashed/j5j/releases/download/${J5J_VERSION}/j5j-${J5J_VERSION}-${arch}-unknown-linux-musl.tar.gz" ; \ - scurl "$url" | tar zvxf - -C /usr/local/bin j5j +# json5 transforms json +FROM apt-base AS apt-json5 +RUN DEBIAN_FRONTEND=noninteractive apt-get update +RUN DEBIAN_FRONTEND=noninteractive apt-get install -y node-json5 +# consumers use j5j as the interface to stripping comments from json +RUN ln -s /usr/bin/json5 /usr/local/bin/j5j # just runs build/test recipes. Like `make` but a bit more ergonomic. FROM apt-base as just @@ -57,9 +62,6 @@ RUN url="https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linu scurl -o /yq "$url" && chmod +x /yq FROM scratch as tools-script -COPY --link --from=j5j /usr/local/bin/j5j /bin/ -COPY --link --from=just /usr/local/bin/just /bin/ -COPY --link --from=yq /yq /bin/ COPY --link bin/scurl /bin/ ## @@ -282,7 +284,7 @@ ENV PROTOC_NO_VENDOR=1 \ PROTOC_INCLUDE=/usr/local/include # A Rust build environment. -FROM docker.io/library/rust:${RUST_TAG}-slim-bookworm as rust +FROM docker.io/library/rust:${RUST_TAG}-slim-${DEBIAN_RELEASE} as rust RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ @@ -316,7 +318,6 @@ ENV CARGO_INCREMENTAL=0 \ RUSTUP_MAX_RETRIES=10 ENTRYPOINT ["/usr/local/bin/just-cargo"] -COPY --link --from=just /usr/local/bin/just /usr/local/bin/ FROM rust as rust-musl RUN rustup target add \ aarch64-unknown-linux-musl \ @@ -334,7 +335,7 @@ RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ ## Devcontainer ## -FROM docker.io/library/debian:bookworm as devcontainer +FROM docker.io/library/debian:${DEBIAN_RELEASE} AS devcontainer RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ @@ -343,6 +344,7 @@ RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ curl \ dnsutils \ file \ + git \ iproute2 \ jo \ jq \ @@ -372,12 +374,6 @@ RUN groupadd --gid=1000 code \ && echo "code ALL=(root) NOPASSWD:ALL" >/etc/sudoers.d/code \ && chmod 0440 /etc/sudoers.d/code -# git v2.34+ has new subcommands and supports code signing via SSH. -RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ - DEBIAN_FRONTEND=noninteractive apt-get install -y -t bookworm-backports git - RUN --mount=type=cache,from=apt-llvm,source=/etc/apt,target=/etc/apt,ro \ --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ @@ -391,17 +387,14 @@ RUN --mount=type=cache,id=apt-docker,from=apt-base,source=/etc/apt,target=/etc/a --mount=type=cache,id=apt-docker,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ DEBIAN_FRONTEND=noninteractive apt-get install -y docker-compose -# Use microsoft's Docker setup script to install the Docker CLI. -# +# devcontainers/features: install docker do not use moby (not supported on trixie) # A distinct cache is used because the script adds an apt repo that we don't # want to pull in for other layers. -# -# TODO(ver): replace this with a devcontainer feature? RUN --mount=type=cache,id=apt-docker,from=apt-base,source=/etc/apt,target=/etc/apt \ --mount=type=cache,id=apt-docker,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ --mount=type=cache,id=apt-docker,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ --mount=type=bind,from=tools,source=/bin/scurl,target=/usr/local/bin/scurl \ - scurl https://raw.githubusercontent.com/microsoft/vscode-dev-containers/main/script-library/docker-debian.sh | bash -s + scurl https://raw.githubusercontent.com/devcontainers/features/refs/heads/main/src/docker-outside-of-docker/install.sh | MOBY=false bash -s ENV DOCKER_BUILDKIT=1 ARG MARKDOWNLINT_VERSION=0.22.1 From ea2c210a4a677a8072ae32dcb52faea739c8d912 Mon Sep 17 00:00:00 2001 From: Raymond Kroeker Date: Fri, 10 Jul 2026 12:13:53 -0700 Subject: [PATCH 12/14] feat(arm64): refactor unused stages Include node-json5, just and yq packages in devcontainer. Previously the stages were orphaned. True up all of the cache mount options. --- Dockerfile | 54 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/Dockerfile b/Dockerfile index d8bf6e6..f0380ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -271,9 +271,9 @@ COPY --link --from=tools-script /bin/* /bin/ # A Go build environment. FROM docker.io/library/golang:${GO_TAG} as go -RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ +RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,sharing=locked \ --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt,target=/var/lib/apt,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y file jo jq COPY --link --from=tools-script /bin/* /usr/local/bin/ COPY --link --from=tools-go /bin/* /usr/local/bin/ @@ -285,9 +285,9 @@ ENV PROTOC_NO_VENDOR=1 \ # A Rust build environment. FROM docker.io/library/rust:${RUST_TAG}-slim-${DEBIAN_RELEASE} as rust -RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ +RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,sharing=locked \ --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt,target=/var/lib/apt,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ cmake \ curl \ @@ -298,9 +298,9 @@ RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ jq \ libssl-dev \ pkg-config -RUN --mount=type=cache,from=apt-llvm,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ +RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt,target=/var/lib/apt,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y clang-19 llvm-19 RUN rustup component add clippy rustfmt COPY --link --from=tools-lint /bin/checksec /usr/local/bin/ @@ -322,9 +322,9 @@ FROM rust as rust-musl RUN rustup target add \ aarch64-unknown-linux-musl \ x86_64-unknown-linux-musl -RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ +RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,sharing=locked \ --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt,target=/var/lib/apt,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ binutils-aarch64-linux-gnu \ g++-aarch64-linux-gnu \ @@ -336,9 +336,9 @@ RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ ## FROM docker.io/library/debian:${DEBIAN_RELEASE} AS devcontainer -RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ +RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,sharing=locked \ --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt,target=/var/lib/apt,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ cmake \ curl \ @@ -348,17 +348,23 @@ RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,ro \ iproute2 \ jo \ jq \ + just \ libssl-dev \ locales \ lsb-release \ netcat-openbsd \ + node-json5 \ pkg-config \ skopeo \ sudo \ time \ tshark \ umoci \ - unzip + unzip \ + yq + +# consumers use j5j as the interface to stripping comments from json +RUN ln -s /usr/bin/json5 /usr/local/bin/j5j # Link the gnu versions of ranlib to the musl toolchain. # See: https://github.com/linkerd/linkerd2/issues/13350 @@ -374,34 +380,34 @@ RUN groupadd --gid=1000 code \ && echo "code ALL=(root) NOPASSWD:ALL" >/etc/sudoers.d/code \ && chmod 0440 /etc/sudoers.d/code -RUN --mount=type=cache,from=apt-llvm,source=/etc/apt,target=/etc/apt,ro \ +RUN --mount=type=cache,from=apt-llvm,source=/etc/apt,target=/etc/apt,sharing=locked \ --mount=type=cache,from=apt-llvm,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-llvm,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ + --mount=type=cache,from=apt-llvm,source=/var/lib/apt,target=/var/lib/apt,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y clang-19 llvm-19 ENV CC=clang-19 \ CXX=clang++-19 # Install docker-compose since it breaks in the docker-debian script on arm64 -RUN --mount=type=cache,id=apt-docker,from=apt-base,source=/etc/apt,target=/etc/apt \ - --mount=type=cache,id=apt-docker,from=apt-base,source=/var/cache/apt,target=/var/cache/apt${APT_CACHE_SHARING} \ - --mount=type=cache,id=apt-docker,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists${APT_CACHE_SHARING} \ +RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt,target=/var/lib/apt,sharing=locked \ DEBIAN_FRONTEND=noninteractive apt-get install -y docker-compose # devcontainers/features: install docker do not use moby (not supported on trixie) # A distinct cache is used because the script adds an apt repo that we don't # want to pull in for other layers. -RUN --mount=type=cache,id=apt-docker,from=apt-base,source=/etc/apt,target=/etc/apt \ - --mount=type=cache,id=apt-docker,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,id=apt-docker,from=apt-base,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ +RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt,target=/var/lib/apt,sharing=locked \ --mount=type=bind,from=tools,source=/bin/scurl,target=/usr/local/bin/scurl \ scurl https://raw.githubusercontent.com/devcontainers/features/refs/heads/main/src/docker-outside-of-docker/install.sh | MOBY=false bash -s ENV DOCKER_BUILDKIT=1 ARG MARKDOWNLINT_VERSION=0.22.1 -RUN --mount=type=cache,from=apt-node,source=/etc/apt,target=/etc/apt,ro \ - --mount=type=cache,from=apt-node,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ - --mount=type=cache,from=apt-node,source=/var/lib/apt/lists,target=/var/lib/apt/lists,sharing=locked \ - DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs +RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/cache/apt,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,from=apt-base,source=/var/lib/apt,target=/var/lib/apt,sharing=locked \ + DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y nodejs npm RUN npm install "markdownlint-cli2@${MARKDOWNLINT_VERSION}" --global COPY --link --from=go /usr/local/go /usr/local/go From 16053b9da8fe1b9ad3a03b83a2c588ecb9e27da4 Mon Sep 17 00:00:00 2001 From: Raymond Kroeker Date: Fri, 10 Jul 2026 14:15:14 -0700 Subject: [PATCH 13/14] Drop nodejs. --- Dockerfile | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index f0380ca..8385edd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,13 +18,6 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update RUN DEBIAN_FRONTEND=noninteractive apt-get install -y curl unzip xz-utils COPY --link bin/scurl /usr/local/bin/ -FROM apt-base as apt-node -RUN apt-get install -y gnupg2 -ARG NODE_MAJOR=26 -RUN mkdir -p /etc/apt/keyrings && scurl https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg -RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" >/etc/apt/sources.list.d/nodesource.list -RUN apt-get update && apt-get install nodejs -y - # See https://apt.llvm.org/. FROM apt-base as apt-llvm RUN DEBIAN_FRONTEND=noninteractive apt-get install -y gnupg2 @@ -345,6 +338,7 @@ RUN --mount=type=cache,from=apt-base,source=/etc/apt,target=/etc/apt,sharing=loc dnsutils \ file \ git \ + gnupg2 \ iproute2 \ jo \ jq \ From 680195ead8e9966c69d917b479d63f7e1c88bd04 Mon Sep 17 00:00:00 2001 From: "Anthony Turcios (anthoturc)" Date: Thu, 27 Aug 2026 12:05:46 -0400 Subject: [PATCH 14/14] feat(arm64,amd64): remove hardcoded arch from artifact locations (urls, packages) --- Dockerfile | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8385edd..06795fe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,13 +45,16 @@ RUN ln -s /usr/bin/json5 /usr/local/bin/j5j # just runs build/test recipes. Like `make` but a bit more ergonomic. FROM apt-base as just ARG JUST_VERSION=1.54.0 # repo=casey/just -RUN url="https://github.com/casey/just/releases/download/${JUST_VERSION}/just-${JUST_VERSION}-x86_64-unknown-linux-musl.tar.gz" ; \ +ARG TARGETARCH +RUN arch=$(echo "$TARGETARCH" | sed -e 's/amd64/x86_64/' -e 's/arm64/aarch64/'); \ + url="https://github.com/casey/just/releases/download/${JUST_VERSION}/just-${JUST_VERSION}-${arch}-unknown-linux-musl.tar.gz" ; \ scurl "$url" | tar zvxf - -C /usr/local/bin just # yq is kind of like jq, but for YAML. FROM apt-base as yq ARG YQ_VERSION=v4.53.3 # repo=mikefarah/yq -RUN url="https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_amd64" ; \ +ARG TARGETARCH +RUN url="https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${TARGETARCH}" ; \ scurl -o /yq "$url" && chmod +x /yq FROM scratch as tools-script @@ -64,21 +67,24 @@ COPY --link bin/scurl /bin/ # helm templates kubernetes manifests. FROM apt-base as helm ARG HELM_VERSION=v3.21.2 # repo=helm/helm -RUN url="https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz" ; \ - scurl "$url" | tar xzvf - --strip-components=1 -C /usr/local/bin linux-amd64/helm +ARG TARGETARCH +RUN url="https://get.helm.sh/helm-${HELM_VERSION}-linux-${TARGETARCH}.tar.gz" ; \ + scurl "$url" | tar xzvf - --strip-components=1 -C /usr/local/bin "linux-${TARGETARCH}/helm" # helm-docs generates documentation from helm charts. FROM apt-base as helm-docs ARG HELM_DOCS_VERSION=v1.14.2 # repo=norwoodj/helm-docs -RUN arch=$(uname -m | sed -e 's/aarch/arm/'); \ +ARG TARGETARCH +RUN arch=$(echo "$TARGETARCH" | sed -e 's/amd64/x86_64/'); \ url="https://github.com/norwoodj/helm-docs/releases/download/$HELM_DOCS_VERSION/helm-docs_${HELM_DOCS_VERSION#v}_Linux_${arch}.tar.gz" ; \ scurl "$url" | tar xzvf - -C /usr/local/bin helm-docs # kubectl controls kubernetes clusters. FROM apt-base as kubectl ARG KUBECTL_VERSION=v1.36.2 # repo=kubernetes/kubernetes -RUN url="https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" ; \ +ARG TARGETARCH +RUN url="https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${TARGETARCH}/kubectl" ; \ scurl -o /usr/local/bin/kubectl "$url" && chmod +x /usr/local/bin/kubectl # k3d runs kubernetes clusters in docker. @@ -113,7 +119,8 @@ COPY --link --from=ghcr.io/anchore/grype:v0.96.1 /grype /bin/ # actionlint lints github actions workflows. FROM apt-base as actionlint ARG ACTIONLINT_VERSION=v1.7.12 # repo=rhysd/actionlint -RUN url="https://github.com/rhysd/actionlint/releases/download/${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION#v}_linux_amd64.tar.gz" ; \ +ARG TARGETARCH +RUN url="https://github.com/rhysd/actionlint/releases/download/${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION#v}_linux_${TARGETARCH}.tar.gz" ; \ scurl "$url" | tar xzvf - -C /usr/local/bin actionlint # checksec checks binaries for security issues. @@ -134,7 +141,10 @@ COPY --link bin/action-* bin/just-dev bin/just-sh /bin/ FROM apt-base as protobuf ARG PROTOC_VERSION=v35.1 # repo=protocolbuffers/protobuf -RUN url="https://github.com/google/protobuf/releases/download/$PROTOC_VERSION/protoc-${PROTOC_VERSION#v}-linux-$(uname -m).zip" ; \ +ARG TARGETARCH +# protobuf spells arm64 as `aarch_64`, with an underscore. +RUN arch=$(echo "$TARGETARCH" | sed -e 's/amd64/x86_64/' -e 's/arm64/aarch_64/'); \ + url="https://github.com/google/protobuf/releases/download/$PROTOC_VERSION/protoc-${PROTOC_VERSION#v}-linux-${arch}.zip" ; \ cd $(mktemp -d) && \ scurl -o protoc.zip "$url" && \ unzip protoc.zip bin/protoc include/** && \ @@ -150,31 +160,40 @@ RUN url="https://github.com/google/protobuf/releases/download/$PROTOC_VERSION/pr # cargo-action-fmt formats `cargo build` JSON output to Github Actions annotations. FROM apt-base as cargo-action-fmt ARG CARGO_ACTION_FMT_VERSION=v1.0.4 # ignore -RUN arch=$(uname -m); \ +ARG TARGETARCH +RUN arch=$(echo "$TARGETARCH" | sed -e 's/amd64/x86_64/' -e 's/arm64/aarch64/'); \ url="https://github.com/olix0r/cargo-action-fmt/releases/download/release%2F${CARGO_ACTION_FMT_VERSION}/cargo-action-fmt-${CARGO_ACTION_FMT_VERSION}-${arch}-unknown-linux-musl.tar.gz" ; \ scurl "$url" | tar zvxf - -C /usr/local/bin cargo-action-fmt FROM apt-base as cargo-auditable ARG CARGO_AUDITABLE_VERSION=v0.7.5 # repo=rust-secure-code/cargo-auditable -RUN url="https://github.com/rust-secure-code/cargo-auditable/releases/download/${CARGO_AUDITABLE_VERSION}/cargo-auditable-x86_64-unknown-linux-gnu.tar.xz" ; \ - scurl "$url" | tar xJvf - --strip-components=1 -C /usr/local/bin cargo-auditable-x86_64-unknown-linux-gnu/cargo-auditable +ARG TARGETARCH +RUN arch=$(echo "$TARGETARCH" | sed -e 's/amd64/x86_64/' -e 's/arm64/aarch64/'); \ + url="https://github.com/rust-secure-code/cargo-auditable/releases/download/${CARGO_AUDITABLE_VERSION}/cargo-auditable-${arch}-unknown-linux-gnu.tar.xz" ; \ + scurl "$url" | tar xJvf - --strip-components=1 -C /usr/local/bin "cargo-auditable-${arch}-unknown-linux-gnu/cargo-auditable" # cargo-deny checks cargo dependencies for licensing and RUSTSEC security issues. FROM apt-base as cargo-deny ARG CARGO_DENY_VERSION=0.19.9 # repo=EmbarkStudios/cargo-deny -RUN url="https://github.com/EmbarkStudios/cargo-deny/releases/download/${CARGO_DENY_VERSION}/cargo-deny-${CARGO_DENY_VERSION}-x86_64-unknown-linux-musl.tar.gz" ; \ - scurl "$url" | tar zvxf - --strip-components=1 -C /usr/local/bin "cargo-deny-${CARGO_DENY_VERSION}-x86_64-unknown-linux-musl/cargo-deny" +ARG TARGETARCH +RUN arch=$(echo "$TARGETARCH" | sed -e 's/amd64/x86_64/' -e 's/arm64/aarch64/'); \ + url="https://github.com/EmbarkStudios/cargo-deny/releases/download/${CARGO_DENY_VERSION}/cargo-deny-${CARGO_DENY_VERSION}-${arch}-unknown-linux-musl.tar.gz" ; \ + scurl "$url" | tar zvxf - --strip-components=1 -C /usr/local/bin "cargo-deny-${CARGO_DENY_VERSION}-${arch}-unknown-linux-musl/cargo-deny" # cargo-nextest is a nicer test runner. FROM apt-base as cargo-nextest ARG NEXTEST_VERSION=0.9.138 # repo=nextest-rs/nextest,prefix=cargo-nextest- -RUN url="https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-${NEXTEST_VERSION}/cargo-nextest-${NEXTEST_VERSION}-x86_64-unknown-linux-gnu.tar.gz" ; \ +ARG TARGETARCH +RUN arch=$(echo "$TARGETARCH" | sed -e 's/amd64/x86_64/' -e 's/arm64/aarch64/'); \ + url="https://github.com/nextest-rs/nextest/releases/download/cargo-nextest-${NEXTEST_VERSION}/cargo-nextest-${NEXTEST_VERSION}-${arch}-unknown-linux-gnu.tar.gz" ; \ scurl "$url" | tar zvxf - -C /usr/local/bin cargo-nextest # cargo-tarpaulin is a code coverage tool. FROM apt-base as cargo-tarpaulin ARG CARGO_TARPAULIN_VERSION=0.35.5 # repo=xd009642/tarpaulin -RUN url="https://github.com/xd009642/tarpaulin/releases/download/${CARGO_TARPAULIN_VERSION}/cargo-tarpaulin-x86_64-unknown-linux-musl.tar.gz" ;\ +ARG TARGETARCH +RUN arch=$(echo "$TARGETARCH" | sed -e 's/amd64/x86_64/' -e 's/arm64/aarch64/'); \ + url="https://github.com/xd009642/tarpaulin/releases/download/${CARGO_TARPAULIN_VERSION}/cargo-tarpaulin-${arch}-unknown-linux-musl.tar.gz" ;\ scurl "$url" | tar xzvf - -C /usr/local/bin cargo-tarpaulin FROM scratch as tools-rust