Skip to content

MAINT: Optimize devcontainer Dockerfile#1437

Open
spencrr wants to merge 3 commits intoAzure:mainfrom
spencrr:spencrr/devcontainer-dockerfile-optimize
Open

MAINT: Optimize devcontainer Dockerfile#1437
spencrr wants to merge 3 commits intoAzure:mainfrom
spencrr:spencrr/devcontainer-dockerfile-optimize

Conversation

@spencrr
Copy link
Contributor

@spencrr spencrr commented Mar 4, 2026

Description

Optimizes the devcontainer Dockerfile to improve build speed, reduce image size, and tighten permissions.

Key changes:

Build performance

  • Use BuildKit cache mounts (--mount=type=cache) for all apt-get layers instead of apt-get clean && rm -rf /var/lib/apt/lists/* — cached packages persist across local rebuilds, so subsequent builds skip re-downloading unchanged packages. Note: these mounts only benefit local builds; in CI, GHA layer caching (cache-from: type=gha) handles caching at the layer level.
  • The apt-get clean && rm -rf /var/lib/apt/lists/* cleanup commands are removed because BuildKit cache mounts store apt data outside the image layer, so nothing needs to be cleaned up — the layer never contains it.
  • Install uv via COPY --from=ghcr.io/astral-sh/uv:0.10.8 multi-stage copy instead of curl | sh — avoids a network round-trip, shell pipe execution, and the extra cleanup of /root/.local/bin.

Image size

  • Apply --no-install-recommends consistently to all apt-get install invocations (previously only used on the Speech SDK block) — prevents pulling in unnecessary Recommends dependencies (e.g., X11 libs, man pages).

Reproducibility

  • Pin base image to python:3.11-bookworm instead of python:3.11 — prevents silent shifts between Debian releases (e.g., Bookworm to Trixie) when the base image is updated. (and match existing bookworm apt repo call)
  • Pin uv to a specific version (0.10.8) via multi-stage COPY --from — the previous curl | sh always fetched the latest release, making builds non-deterministic.
  • Set DEBIAN_FRONTEND=noninteractive as a global ENV instead of inline per-command — prevents any apt-get invocation from prompting for interactive input.

Security hardening

  • Change chmod 777 to chmod 755 for all cache directories (pip, pylance, venv, uv, mypy) — 777 is unnecessarily permissive in a single-user devcontainer where vscode owns these directories.
  • Removed unecessary shebang from scripts that were always called with python script_name.py to avoid precommit complaint.

Dependency cleanup

  • Drop redundant apt-transport-https from explicit install — this is a transitional no-op package on Debian Bookworm (HTTPS support is built into apt natively). The base image already includes it.
  • Drop redundant lsb-release from explicit install — the base image already includes it
  • Remove stale rm -rf /opt/venv and debug ls -la /opt/venv/bin/activate from the uv/venv setup step.

Node.js

  • Bump to Node.js 24.x (LTS), move npm install -g @github/copilot to a devcontainer feature to remove unecessary tool from production builds.

Minor cleanup

  • Fix trailing whitespace on chmod line and indentation on "Set cache directories" comment.

Tests and Documentation

  • No code or API changes — this only affects the devcontainer build infrastructure.
  • Verified the Dockerfile builds successfully.
  • No JupyText changes needed.

@spencrr spencrr force-pushed the spencrr/devcontainer-dockerfile-optimize branch from e6bdaa7 to 98ffd93 Compare March 6, 2026 22:01
@spencrr spencrr changed the title [WIP] MAINT: Optimize devcontainer Dockerfile MAINT: Optimize devcontainer Dockerfile Mar 6, 2026
@spencrr spencrr marked this pull request as ready for review March 6, 2026 22:11
@spencrr spencrr force-pushed the spencrr/devcontainer-dockerfile-optimize branch 2 times, most recently from f5782c4 to c76738c Compare March 6, 2026 23:02
@spencrr spencrr force-pushed the spencrr/devcontainer-dockerfile-optimize branch from c76738c to 0d08b6b Compare March 6, 2026 23:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes the development container and related tooling scripts to improve devcontainer build performance, reduce image size, and tighten default permissions while updating Node.js expectations.

Changes:

  • Updated .devcontainer/Dockerfile to use a pinned Bookworm base image, BuildKit apt cache mounts, --no-install-recommends, multi-stage uv install, and Node.js 24.x.
  • Tightened cache directory permissions (e.g., mypy cache, various .cache/* directories) from 777 to 755.
  • Moved CLI installs into devcontainer features and updated packaging guidance to expect Node.js 24.x.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
.devcontainer/Dockerfile BuildKit caching, pinned base image, uv multi-stage install, Node.js 24.x, and permission tightening.
.devcontainer/devcontainer.json Adds devcontainer features (Azure CLI, Copilot CLI).
.devcontainer/devcontainer_setup.sh Tightens mypy cache permissions and keeps devcontainer setup behavior.
build_scripts/prepare_package.py Removes shebang and updates Node.js version guidance in error output.
docker/build_pyrit_docker.py Removes shebang (script intended to be run via python ...).
docker/run_pyrit_docker.py Removes shebang (script intended to be run via python ...).

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +15 to +17
RUN --mount=type=cache,target=/var/cache/apt \
--mount=type=cache,target=/var/lib/apt \
apt-get update \
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using --mount=type=cache for apt directories, concurrent builds can contend on apt lock files stored inside the shared cache (and occasionally corrupt the cache). It’s safer to set sharing=locked on these cache mounts (and mount the more specific .../apt/lists path) to avoid intermittent build failures when multiple builds run in parallel.

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +99
"ghcr.io/devcontainers/features/azure-cli:1": {
"version": "latest"
},
"ghcr.io/devcontainers/features/copilot-cli:1": {
"version": "latest"
}
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using "version": "latest" for devcontainer features makes devcontainer builds non-reproducible and can introduce breaking changes without a PR. Pin these features to a specific, known-good version (or a semver range you’re comfortable with) to align with the PR’s reproducibility goals.

Suggested change
"ghcr.io/devcontainers/features/azure-cli:1": {
"version": "latest"
},
"ghcr.io/devcontainers/features/copilot-cli:1": {
"version": "latest"
}
"ghcr.io/devcontainers/features/azure-cli:1": {},
"ghcr.io/devcontainers/features/copilot-cli:1": {}

Copilot uses AI. Check for mistakes.
Comment on lines 1 to +17
@@ -11,66 +12,61 @@ USER root
RUN rm -f /etc/apt/sources.list.d/yarn.list 2>/dev/null || true

# Install required system packages + ODBC prerequisites
RUN apt-get update && apt-get install -y \
sudo \
unixodbc \
unixodbc-dev \
libgl1 \
git \
curl \
xdg-utils \
build-essential \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
RUN --mount=type=cache,target=/var/cache/apt \
--mount=type=cache,target=/var/lib/apt \
apt-get update \
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Dockerfile now relies on BuildKit-only RUN --mount=type=cache syntax. If BuildKit is disabled (or an older Dockerfile frontend is used), the build will fail parsing these RUN lines. Consider adding a # syntax=docker/dockerfile:<version> directive at the top (and/or ensuring the build entrypoints set DOCKER_BUILDKIT=1) so the devcontainer build works reliably across environments.

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +59
RUN --mount=type=cache,target=/var/cache/apt \
--mount=type=cache,target=/var/lib/apt \
curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \
&& apt-get install -y --no-install-recommends nodejs
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The curl -fsSL https://deb.nodesource.com/setup_24.x | bash - pattern downloads and executes a remote script as root without any integrity or authenticity verification, creating a supply-chain risk. If the NodeSource endpoint or DNS is compromised, an attacker could run arbitrary code during the image build and persist backdoored tooling into the devcontainer image. Replace this pipe-to-bash installer with a method that verifies a pinned script or package (e.g., manually configuring the APT repository with a GPG key or verifying a checksum/signature before execution).

Copilot uses AI. Check for mistakes.
&& rm -rf /var/lib/apt/lists/*
libpulse0

# Install Node.js 24.x LTS for frontend development
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching from 18 to 24 there could be a lot of changes. If that's absolutely needed right now I'd defer until later because it could significantly slow down ongoing front end work that was built with 18.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@romanlutz I can pull this change out, but Node 20 is EOL April 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants