mirror of
https://github.com/openai/codex.git
synced 2026-04-25 15:15:15 +00:00
## Summary - leave the default contributor devcontainer on its lightweight platform-only Docker runtime - install bubblewrap in setuid mode only in the secure devcontainer image for running Codex inside Docker - add Docker run args to the secure profile for bubblewrap's required capabilities - use explicit `seccomp=unconfined` and `apparmor=unconfined` in the secure profile instead of shipping a custom seccomp profile - document that the relaxed Docker security options are scoped to the secure profile ## Why Docker's default seccomp profile blocks bubblewrap with `pivot_root: Operation not permitted`, even when the container has `CAP_SYS_ADMIN`. Docker's default AppArmor profile also blocks bubblewrap with `Failed to make / slave: Permission denied`. A custom seccomp profile works, but it is hard for customers to audit and understand. Using Docker's standard `seccomp=unconfined` option is clearer: the secure profile intentionally relaxes Docker's outer sandbox just enough for Codex to construct its own bubblewrap/seccomp sandbox inside the container. The default contributor profile does not get these expanded runtime settings. ## Validation - `sed '/\\/\\*/,/\\*\\//d' .devcontainer/devcontainer.json | jq empty` - `jq empty .devcontainer/devcontainer.secure.json` - `git diff --check` - `docker build --platform=linux/arm64 -t codex-devcontainer-bwrap-test-arm64 ./.devcontainer` - `docker build --platform=linux/arm64 -f .devcontainer/Dockerfile.secure -t codex-devcontainer-secure-bwrap-test-arm64 .` - interactive `docker run -it` smoke tests: - verified non-root users `ubuntu` and `vscode` - verified secure image `/usr/bin/bwrap` is setuid - verified user/pid namespace, user/network namespace, and preserved-fd `--ro-bind-data` bwrap commands - reran secure-image smoke test with simplified `seccomp=unconfined` setup: - `bwrap-basic-ok` - `bwrap-netns-ok` - `codex-ok` - ran Codex inside the secure image: - `codex --version` -> `codex-cli 0.120.0` - `codex sandbox linux --full-auto -- /bin/sh -lc '...'` -> exited 0 and printed `codex-inner-ok` Note: direct `bwrap --proc /proc` is still denied by this Docker runtime, and Codex's existing proc-mount preflight fallback handles that by retrying without `--proc`. --------- Co-authored-by: Codex <noreply@openai.com>
50 lines
2.8 KiB
Markdown
50 lines
2.8 KiB
Markdown
# Containerized Development
|
|
|
|
We provide two container paths:
|
|
|
|
- `devcontainer.json` keeps the existing Codex contributor setup for working on this repository.
|
|
- `devcontainer.secure.json` adds a customer-oriented profile with stricter outbound network controls.
|
|
|
|
## Codex contributor profile
|
|
|
|
Use `devcontainer.json` when you are developing Codex itself. This is the same lightweight arm64 container that already exists in the repo.
|
|
|
|
## Secure customer profile
|
|
|
|
Use `devcontainer.secure.json` when you want a stricter runtime profile for running Codex inside a project container:
|
|
|
|
- installs the Codex CLI plus common build tools
|
|
- installs bubblewrap in setuid mode for Codex's Linux sandbox
|
|
- disables Docker's outer seccomp and AppArmor profiles so bubblewrap can construct Codex's inner sandbox
|
|
- enables firewall startup with an allowlist-driven outbound policy
|
|
- blocks IPv6 by default so the allowlist cannot be bypassed over AAAA routes
|
|
- requires `NET_ADMIN` and `NET_RAW` so the firewall can be installed at startup
|
|
|
|
This profile keeps the stricter networking isolated to the customer path instead of changing the default Codex contributor container.
|
|
|
|
Start it from the CLI with:
|
|
|
|
```bash
|
|
devcontainer up --workspace-folder . --config .devcontainer/devcontainer.secure.json
|
|
```
|
|
|
|
In VS Code, choose **Dev Containers: Open Folder in Container...** and select `.devcontainer/devcontainer.secure.json`.
|
|
|
|
## Docker
|
|
|
|
To build the contributor image locally for x64 and then run it with the repo mounted under `/workspace`:
|
|
|
|
```shell
|
|
CODEX_DOCKER_IMAGE_NAME=codex-linux-dev
|
|
docker build --platform=linux/amd64 -t "$CODEX_DOCKER_IMAGE_NAME" ./.devcontainer
|
|
docker run --platform=linux/amd64 --rm -it -e CARGO_TARGET_DIR=/workspace/codex-rs/target-amd64 -v "$PWD":/workspace -w /workspace/codex-rs "$CODEX_DOCKER_IMAGE_NAME"
|
|
```
|
|
|
|
Note that `/workspace/target` will contain the binaries built for your host platform, so we include `-e CARGO_TARGET_DIR=/workspace/codex-rs/target-amd64` in the `docker run` command so that the binaries built inside your container are written to a separate directory.
|
|
|
|
For arm64, specify `--platform=linux/arm64` instead for both `docker build` and `docker run`.
|
|
|
|
Currently, the contributor `Dockerfile` works for both x64 and arm64 Linux, though you need to run `rustup target add x86_64-unknown-linux-musl` yourself to install the musl toolchain for x64.
|
|
|
|
The secure profile's capability, seccomp, and AppArmor options are required when you want Codex's bubblewrap sandbox to run inside Docker as the non-root devcontainer user. Without them, Docker's default runtime profile can block bubblewrap's namespace setup before Codex's own seccomp filter is installed. This keeps the Docker relaxation explicit in the profile that is meant to run Codex inside a project container, while the default contributor profile stays lightweight.
|