GitHub Codespaces の Universal イメージを Dev Container なしで使えるようにする

TL;DR
GitHub Codespaces と同じ Universal イメージをローカル (Docker Desktop など) の CLI で試すコマンドです。
docker run --rm -it --privileged -u codespace -w /home/codespace mcr.microsoft.com/devcontainers/universal:2 bash

代わりに以下のコマンドを使います。
docker run --rm -it --privileged -u codespace -w /home/codespace \
mcr.microsoft.com/devcontainers/universal:2 /usr/local/share/docker-init.sh \
/usr/local/share/ssh-init.sh bash
(背景) 以下の Pull request でイメージから ENTRYPOINT
が削除されてしまって Docker in Docker が有効にならなくなりました。 上記のように docker run
コマンドに同等のコマンドを追加することで元通りの動作になります。
diff --git a/src/universal/.devcontainer/Dockerfile b/src/universal/.devcontainer/Dockerfile
index e58ff1cc6..d9a2b2784 100644
--- a/src/universal/.devcontainer/Dockerfile
+++ b/src/universal/.devcontainer/Dockerfile
@@ -93,8 +93,6 @@ RUN apt-get clean -y && rm -rf /tmp/scripts
# Mount for docker-in-docker
VOLUME [ "/var/lib/docker" ]
-# Fire Docker/Moby script if needed
-ENTRYPOINT [ "/usr/local/share/docker-init.sh", "/usr/local/share/ssh-init.sh"]
CMD [ "sleep", "infinity" ]
# [Optional] Install debugger for development of Codespaces - Not in resulting image by default

Context
Github Codespaces
Github Codespaces のベースイメージはとても便利です。 様々なビルドツールやプログラミング言語がビルドインされており、さらに Docker も利用できます。
GitHub では .devcontainer
定義がないリポジトリで Codespaces を開くとこのイメージによる環境が立ち上がります。 「何にでも使える」けど「使い捨ての」環境が欲しい時は私はよく Blank テンプレートから Codespaces を立ち上げてます。
でも Github Codespaces は停止し忘れると無料枠を消費してしまうので、Docker が入っているローカルマシンを使っているならローカルマシンでこの使い捨て環境を利用できるといいです。
Github Codespaces 環境は Dev Containers によって構成されているのですが、環境をカスタマイズしてみようとすると、このベースイメージは Dev Containers の Universal イメージということが分かります。
それであれば VS Code の Dev Container を使ってローカルから利用してみましょう。
Dev Containers
実際に VS Code の Dev Container を使って開発コンテナ定義を追加しようとするとこの Universal イメージの選択肢が現れます。
通常の Dev Container の利用方法に従えば、これだけで GitHub Codespaces と同じイメージがローカルでも使えるようになりました!
しかし VS Code Dev Container もよいですが、わざわざ GUI からではなく単純に CLI からでも使えるようにしたいです。
イメージの URL は分かっているので docker run
コマンドで使えるようにしましょう。
mcr.microsoft.com/devcontainers/universal:2
docker CLI
失敗例
docker run --rm -it mcr.microsoft.com/devcontainers/universal:2 bash
mount: /tmp: permission denied.
いつも通りの docker run
コマンドを打ってみましたが、なぜか失敗してしまいます。 /tmp
のパーミッション?? 原因を把握する為に Universal イメージの Dockerfile
を追ってみました。
ENTRYPOINT
で特殊なスクリプトを使って Docker in Docker (及び sshd) を有効化しているようです。 その為 --privileged
フラグを使ってコンテナ内部で Docker の権限を渡します。
docker run --rm -it --privileged mcr.microsoft.com/devcontainers/universal:2 bash
Not setting dockerd DNS manually.
root ➜ / $
成功しました! なにやらメッセージが出てますが、正常系の echo のようです。
あとは root
ユーザーは使いたくないので codespace
ユーザーに書き換えれば GitHub Codespaces 環境と一致します。 (TL;DR のコマンド)
docker run --rm -it --privileged -u codespace -w /home/codespace mcr.microsoft.com/devcontainers/universal:2 bash
さらに (Windows の場合は) Windows Terminal でプロフィールを作成してこちらのコマンドを登録すればより便利になります。

Not setting dockerd DNS manually. のメッセージが気になる場合は、コマンドをハックしてみるのもいいかもしれません。 SSH が不要なら ssh-init.sh
のシェルも削除してもいいかもしれませんね。
docker run --rm -it --privileged -u codespace -w /home/codespace --entrypoint /bin/sh mcr.microsoft.com/devcontainers/universal:2 -c "/usr/local/share/ssh-init.sh /usr/local/share/docker-init.sh > /dev/null && bash"