The aider container¶
aider packages Aider — the git-native terminal
pair-programming agent — in a hardened container. It runs as an unprivileged
user with a read-only root filesystem, a minimal capability set, and
deny-by-default outbound networking. This is particularly useful for Aider:
it can edit a project, run shell commands and configured tests, fetch URLs,
and send the selected code context to a model provider.
The image uses Python 3.12 because the packaged Aider release supports Python
3.10--3.12. It pins aider-chat==0.86.2; rebuilding does not silently change
the agent or its model-provider dependency graph. The normal terminal CLI is
included, but the optional browser UI and Playwright/Chromium web scraper are
not.
Build¶
The image's build context needs agent-images/shared supplied as a named
Buildx build context,
because the Dockerfile uses the shared egress and entrypoint scripts:
Matching your host user's UID/GID¶
The image defaults to UID/GID 1000:1000. Everything the agent writes to
the bind-mounted project directory or the persistent home volume is owned
by whatever UID/GID the container ran as — if that doesn't match your host
account, those files aren't owned by you on the host (permission errors,
needing sudo to clean up). Rebuild with matching values instead:
docker build --build-context shared=agent-images/shared \
--build-arg UID=$(id -u) --build-arg GID=$(id -g) \
-t aider:$(whoami) agent-images/aider
Dockerfile splits into a base stage that installs everything —
apt/Node.js/uv baseline, packages-apt.txt/packages-uv.txt, Aider
itself, and the account-scoped packages-npm.txt/tools-uv.txt — under a
fixed placeholder account (UID/GID 1000:1000), and a final stage that
only remaps that account to the UID/GID build args (usermod/groupmod
plus a chown -R of what base already installed) when they differ from
the placeholder. Nothing in final reinstalls packages, so rebuilding for a
different UID after the first build is fast.
On a host shared by multiple accounts, tag the image per user
(aider:alice, aider:bob) rather than overwriting a shared aider tag —
and use that same tag, plus a per-user home volume (aider-home-alice
rather than the shared aider-home), in the run command below. The
shell-shortcut functions
do both substitutions automatically from a single CONTAINED_AIDER_TAG
variable; if invoking docker run directly instead, substitute your tag
into both the aider-home volume name and the trailing aider image
reference in the command below — copying it unchanged still runs the shared
aider:latest.
Run¶
Choose one model provider and allow only its API hostname. For example, this invocation forwards an Anthropic key from the host environment without placing it in the image, build arguments, project, or command history:
docker run -it --rm \
--security-opt=no-new-privileges \
--read-only --tmpfs /tmp --tmpfs /run \
--cap-drop=ALL --cap-add=NET_ADMIN --cap-add=NET_RAW --cap-add=SETUID --cap-add=SETGID \
-e ANTHROPIC_API_KEY \
-e 'AGENT_ALLOWED_EGRESS=api.anthropic.com' \
-v aider-home:/home/aider \
-v "$PWD":"/workspace/$(basename "$PWD")" \
-w "/workspace/$(basename "$PWD")" \
aider
For OpenAI, forward OPENAI_API_KEY and allow api.openai.com instead.
Aider supports many other providers and custom API bases. Add only the
hostname(s) required by the provider and the project's package or
source-control tooling; the image does not carry a broad provider allowlist.
| Flag | Why it is present |
|---|---|
--read-only |
Stops Aider, project commands, and dependencies changing the image filesystem. |
--tmpfs /tmp and --tmpfs /run |
Provide ephemeral writable locations for the egress-control tooling and runtime files. |
--cap-drop=ALL |
Removes Docker's default capabilities. |
NET_ADMIN and NET_RAW |
Required for the in-container default-deny egress rules. |
SETUID and SETGID |
Let gosu hand off from firewall setup to the unprivileged aider user. |
The aider-home volume keeps Aider's home-level configuration, optional
provider credentials, caches, and user-installed npm/Python tools outside the
image. It is shared mutable state; use a separate volume for a different trust
boundary. The mounted project is also writable, so review Aider's edits and
anything it leaves for the host to execute later.
Credentials and configuration¶
Pass an API key as a runtime environment variable as above, or retain
user-managed credentials in aider-home. Do not put credentials in a
repository .env or .aider.conf.yml: Aider searches for .env files in its
home, the git root, and the current directory, so a project-controlled file can
both expose a secret and redirect how an invocation behaves.
Aider's home-level configuration can live at /home/aider/.aider.conf.yml.
Keep it in aider-home for normal use. A separately managed, non-secret
configuration can be mounted read-only after testing it with the selected
Aider version. It can also read project .aider.conf.yml,
.aider.model.settings.yml, and .aiderignore files. Treat these project
files as configuration supplied by the project: they can select model settings
and configure commands Aider runs. See
custom configuration files for
mounting guidance.
The image sets these upstream options by default:
AIDER_CHECK_UPDATE=falseprevents a startup version check.AIDER_ANALYTICS=falseprevents analytics prompting or collection.AIDER_DISABLE_PLAYWRIGHT=trueprevents a prompt to install a browser and browser dependencies at runtime.
Users may intentionally override these at runtime, but doing so can require additional egress or a derived image.
Egress control¶
Without AGENT_ALLOWED_EGRESS or a mounted
/etc/agent/egress-allowlist.txt, the image denies all outbound traffic. The
sample at agent-images/aider/examples/egress-allowlist.txt lists the direct
Anthropic and OpenAI API hosts only as a starting point. It is not a default
policy and should be narrowed to the provider actually selected.
Mount an allowlist file when the policy includes several deliberate services:
docker run -it --rm \
--security-opt=no-new-privileges \
--read-only --tmpfs /tmp --tmpfs /run \
--cap-drop=ALL --cap-add=NET_ADMIN --cap-add=NET_RAW --cap-add=SETUID --cap-add=SETGID \
-e ANTHROPIC_API_KEY \
-v aider-home:/home/aider \
-v "$PWD":"/workspace/$(basename "$PWD")" \
-w "/workspace/$(basename "$PWD")" \
-v "$PWD/agent-images/aider/examples/egress-allowlist.txt":/etc/agent/egress-allowlist.txt:ro \
aider
Do not set AGENT_ALLOWED_EGRESS=* unless unrestricted egress is an explicit
trade-off. Quoting prevents shells such as zsh from expanding the wildcard.
Aider's /web can scrape arbitrary user-provided URLs, while /run, /test,
configured linters, and configured test commands execute in the container.
Those commands retain the container boundary, but can write the mounted
project and reach every host you allow. Add web hosts, package registries,
source-control hosts individually and only when a workflow needs them.
Optional browser and voice support¶
The standard Python package can fetch ordinary URLs with its HTTP client. The optional Playwright/Chromium support and experimental browser UI are omitted: they require extra Python packages, browser binaries, and a substantial set of system libraries. Do not let an interactive session install them into the home volume. If the capability is needed, create and test a derived image that installs the chosen extras at build time, then add only the site's hostname to the runtime allowlist.
Voice input is also omitted from the base container's operating-system
dependencies. Aider documents libportaudio2 (and, in some environments,
libasound2-plugins) for voice capture. Add it only in a derived image and
provide an audio device deliberately; the documented hardened invocation does
not expose host audio devices.
Gateway-client mode¶
Set AGENT_GATEWAY_HOST to tunnel all workload egress to an
agent-gateway container or separately operated
gateway. The gateway, rather than Aider, then owns the allowlist;
AGENT_ALLOWED_EGRESS and /etc/agent/egress-allowlist.txt are ignored by
the workload. Follow the Claude Code gateway guide
for the key, host-key pinning, narrow bootstrap rule, and Cloudflare Access
configuration.
Optional build-time tools¶
Edit packages-apt.txt, packages-npm.txt, tools-uv.txt, or
packages-uv.txt and rebuild to add general-purpose tools. packages-apt.txt
starts with the common CLI utilities used by the other first-party images.
tools-uv.txt (uv tool install) is for standalone Python CLI tools, each in
its own isolated venv; packages-uv.txt (uv pip install --system) is for
plain importable libraries with no console-script of their own, installed
into the image's system Python instead. Do not seed API keys, provider
configuration, plugins, a browser, or a local-model runtime in the image.
The image also sets UV_LINK_MODE=copy — see claude-code's uv cache
notes for why.