Skip to content

CI: ghcr の devcontainer image でビルドして apt install を省く#46

Open
thawk105 wants to merge 3 commits into
masterfrom
gha-use-devcontainer-image
Open

CI: ghcr の devcontainer image でビルドして apt install を省く#46
thawk105 wants to merge 3 commits into
masterfrom
gha-use-devcontainer-image

Conversation

@thawk105
Copy link
Copy Markdown
Owner

概要

build.yml の job を ghcr.io/thawk105/ccbench-devcontainer:latest の中で実行するようにする。devcontainer image にはすでに build-essential / autoconf / automake / libtool / pkg-config / ccache / cmake / libboost-filesystem-dev / libgflags-dev / libgoogle-glog-dev / g++ が揃っているので、毎回の apt-get install (現状 30秒〜1分) とそれを包むための apt cache 操作が丸ごと不要になる。

副次効果として、CI のツールチェインが手元の devcontainer と完全に同じ image になり、#44 で起きた「local だと通るのに CI で落ちる」型の事故も構造的に消える。

変更

   build:
     runs-on: ubuntu-latest
+    container:
+      image: ghcr.io/thawk105/ccbench-devcontainer:latest

-      - name: Cache apt packages
-        ...
-      - name: Install apt dependencies
-        ...
+    (削除)

認証

ghcr image は public:

$ curl -s "https://ghcr.io/token?service=ghcr.io&scope=repository:thawk105/ccbench-devcontainer:pull" \
    | python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])'
…anonymous token…

$ curl -sI -H "Authorization: Bearer $TOKEN" \
    -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
    https://ghcr.io/v2/thawk105/ccbench-devcontainer/manifests/latest
HTTP/2 200
content-type: application/vnd.docker.distribution.manifest.v2+json

anonymous bearer-token pull が通るので、credentials: セクションは不要。

トレードオフ

  • +: apt install (~30〜60s) + apt-cache restore/save が消える
  • +: 手元 devcontainer と toolchain が同一になる
  • : 代わりに image pull (1回 数秒〜10秒) が初手に入る。実際の数値は CI runner の Docker layer cache 状況に依る。GHA runner では layer は per-runner で揮発的だが、同一 image を別 job で連続 pull すると数秒で済む
  • : image が壊れたタイミングで CI が回らなくなるリスク。これは devcontainer-image.yml の rebuild 経路でしか起きないので、.devcontainer/** を触るときだけ注意すれば良い

注意点 (#45 との関係)

#45 (devcontainer を ubuntu:22.04 → 24.04 に bump) と独立。

どちらの順序でも壊れない。

Test plan

  • image が public で anonymous pull できることを確認
  • CI 緑
  • 旧 build.yml と新 build.yml の所要時間を比較 (apt install ステップ ~30〜60s が消えるはず)

thawk105 added a commit that referenced this pull request May 13, 2026
…e :latest

The previous single-stage image bundled zsh / clang-format / sudo /
openssh-client / curl — fine for the human-facing devcontainer, but
dead weight in CI where `actions/checkout` and the cmake build are
the only consumers. Container init in PR #46 paid for those layers on
every CI run.

Split the Dockerfile into two stages and publish them as two tags from
the same workflow:

- `base` stage  -> :ci   (minimum apt deps + vscode user, root by default)
- `dev` stage   -> :latest (`base` + zsh, clang-format, sudo,
                           openssh-client, curl, USER vscode)

`.github/workflows/devcontainer-image.yml` now invokes
`docker/build-push-action` twice, each with a different `target:`,
sharing the same `:cache` so layers are deduplicated.

Devcontainer users keep using :latest with no change. CI's build.yml
will be flipped to :ci in a follow-up PR once this lands and the new
tag is published.
@thawk105 thawk105 marked this pull request as draft May 13, 2026 01:40
thawk105 added 3 commits May 13, 2026 01:46
The devcontainer image at ghcr.io/thawk105/ccbench-devcontainer:latest
already has every apt dep installed (build-essential, autoconf, automake,
libtool, pkg-config, ccache, cmake, libboost-filesystem-dev, libgflags-dev,
libgoogle-glog-dev, g++). Running the CI job inside that image lets us
skip the per-run apt-get install plus the apt-cache restore step that
wrapped it, while also guaranteeing the CI toolchain matches the one
developers see locally.

Changes:
- Add `container: { image: ghcr.io/thawk105/ccbench-devcontainer:latest }`
  to the build job. The image is public (anonymous bearer-token pull
  works against ghcr.io), so no `credentials:` are needed.
- Delete the "Cache apt packages" step (no longer any apt packages to
  cache mid-job).
- Delete the "Install apt dependencies" step (everything is already in
  the image).
- Drive-by: update the obsolete "28 binaries" comment to "34" to match
  the current target count.

Ccache + third-party caches are kept — they're tied to source state,
not to the image.
…access

The devcontainer image's default user is vscode (uid=1000), but the GHA
runner's work dir (/__w/_temp, bind-mounted into the container) is owned
by the runner user on the host. Without `--user root` the action's
internal saveState/issueFileCommand writes fail with EACCES, taking down
the very first step.

The simplest fix is to run the container as root via container.options;
the isolation boundary still keeps it benign.
…ontainer

Running inside the container as root, /__w/ccbench/ccbench is owned by
the runner user (uid=1001) on the host while git is invoked as uid=0,
so git aborts with "fatal: detected dubious ownership". actions/checkout
sets safe.directory itself, but later run-steps invoke git from a fresh
sh -e shell that doesn't always inherit that scoped config — and the
Compute bootstrap cache key step needs `git submodule status`.

Set safe.directory globally once after checkout; every subsequent git
call (submodule status, etc.) then passes the ownership check.
@thawk105 thawk105 force-pushed the gha-use-devcontainer-image branch from 6be1518 to 819510a Compare May 13, 2026 01:47
@thawk105 thawk105 marked this pull request as ready for review May 13, 2026 01:47
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.

1 participant