🐳
WWDC2025のContainerizationFrameworkでCodex CLI × Swift を安全かつ再現性高くビルドする
概要
macOS上で Codex CLI に swift build
を実行させると、キャッシュの読み書きに /tmp
ディレクトリなどへのアクセス権限がなく失敗することがあります。
簡単に解決するため、コンテナ上でCodexを実行しようと思います。
本記事では WWDC 2025 で発表された「Containerization Framework」 を利用し、Swift ネイティブなコンテナ環境で Codex CLI を安定稼働させる手順を紹介します。
Containerization Framework のインストール
GitHub Releases からインストーラを取得してセットアップします。
https://github.com/apple/container/releases/tag/0.1.0
# インストーラ (.pkg) を実行後
$ container system start
Verifying apiserver is running...
Installing base container filesystem...
No default kernel configured.
Install the recommended default kernel ...? [Y/n]: Y
Installing kernel...
Docker イメージを用意する
Containerization Framework でもイメージは作成できますが、Docker でビルド → Docker Hub へ Push → Container で Pull する方が手軽です。
以下はswift
を実行するために作成したDockerfileです。
FROM ubuntu:noble
SHELL ["/bin/bash", "-c"]
# ================================
# apt
# ================================
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true && \
apt update && \
apt install -y \
curl \
sudo \
build-essential \
make \
locales \
unzip \
fontconfig \
git \
libncurses6 \
libncurses-dev \
binutils \
unzip \
gnupg2 \
libc6-dev \
libcurl4-openssl-dev \
libedit2 \
libgcc-13-dev \
libpython3-dev \
libsqlite3-0 \
libstdc++-13-dev \
libxml2-dev \
libncurses-dev \
libz3-dev \
pkg-config \
tzdata \
zlib1g-dev \
openssl \
libssl-dev \
&& rm -r /var/lib/apt/lists/*
# ================================
# Swift Lover
# ================================
RUN echo 'swiftlover ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/swiftlover
RUN useradd --user-group --create-home --system --skel /dev/null --home-dir /swiftlover swiftlover
USER swiftlover:swiftlover
WORKDIR /swiftlover
# ================================
# Homebrew
# ================================
RUN NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
RUN echo >> /swiftlover/.bashrc
RUN echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> /swiftlover/.bashrc
RUN eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" && \
brew install \
vapor \
codex \
swift-format && \
brew unlink swift
# ================================
# GitHub gh
# ================================
RUN (type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
&& out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \
&& cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y
# ================================
# Setup Swift
# ================================
WORKDIR /swiftly
RUN NONINTERACTIVE=1 curl -O "https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz" && \
tar zxf "swiftly-$(uname -m).tar.gz" && \
./swiftly init --quiet-shell-followup && \
. ${SWIFTLY_HOME_DIR:-~/.local/share/swiftly}/env.sh && \
hash -r && \
echo "source ${SWIFTLY_HOME_DIR:-~/.local/share/swiftly}/env.sh" >> /swiftlover/.bashrc
WORKDIR /swiftlover/workspace
# ================================
# Permission
# ================================
RUN sudo chown -R swiftlover:swiftlover /swiftly
RUN sudo chown -R swiftlover:swiftlover /swiftlover/workspace
ビルド & Push
$ docker build -t swift-codex:latest -f ./Dockerfile .
$ docker login -u lemonaderoom
$ docker tag swift-codex:latest lemonaderoom/swift-codex:latest
$ docker push lemonaderoom/swift-codex:latest
Containerization Framework で実行
$ container image pull lemonaderoom/swift-codex:latest
$ container run --rm -it \
--volume "${HOME}/.codex":/swiftlover/.codex \
--volume "$(pwd)":/swiftlover/workspace \
--cpus 8 \
--memory 16g \
lemonaderoom/swift-codex bash
swiftlover@1fa98f9b-07c2-476f-9057-750f00fdfc55:~/workspace$ codex
╭──────────────────────────────────────────────────────────────╮
│ ● OpenAI Codex (research preview) v0.1.2505291658 │
╰──────────────────────────────────────────────────────────────╯
╭──────────────────────────────────────────────────────────────╮
│ localhost session: 612bce132c7b4a08b70676449d672dc5 │
│ ↳ workdir: ~/workspace │
│ ↳ model: codex-mini-latest │
│ ↳ provider: openai │
│ ↳ approval: suggest │
╰──────────────────────────────────────────────────────────────╯
パフォーマンス比較
環境 |
swift build (初回) |
swift build (2回目) |
swift test (初回) |
---|---|---|---|
macOS (ローカル) | 92.0 s | 5.7 s | 48.4 s |
Docker (Orbstack) | 193.3 s | 9.9 s | 15.3 s |
Containerization Framework | 277.9 s | 10.9 s | 17.0 s |
あとがき
- あたり前ですがmacOSがbuild最速でした。なぜか初回testでは遅くなりましたが2回目以降のtestでは1.18s程度と速かったです。
- Orbstackの性能がいいのか、コンテナ上の実行は
container
よりdocker
の方が速かったです -
container
の方は感覚ではありますが初回build時にネットワークI/Oがネックになってしまっていそうでした
Discussion