はじめに
現在、Dev Containers を使ってバックエンド開発をしています。
ローカルを汚すことなく、コマンド一発で開発環境を立ち上げることができて便利です ☺️
しかし、Docker コンテナに入って開発するので、設定なしではコンテナ内から git push できません。
毎回ホストに戻るのはめんどくさいので、コンテナ内からリモートリポジトリに接続できるようにしました。
リモートリポジトリは、GitHub を使っています 🐙🐈
環境
Ubuntu 24.04 (WSL2)
最終的な Dockerfile
FROM <container_image>
ARG USERNAME=devuser
ARG USER_UID=1000
ARG USER_GID=1000
RUN apt-get update && apt-get install -y \
git \
ca-certificates \
curl \
vim \
less \
sudo \
procps \
# GitHub CLIのGPG鍵を設定する
&& mkdir -p -m 755 /etc/apt/keyrings \
&& curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
-o /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
# GitHub CLIのリポジトリを追加する
&& mkdir -p -m 755 /etc/apt/sources.list.d \
&& echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] \
https://cli.github.com/packages stable main" \
| tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
# GitHub CLIをインストールする
&& apt-get update \
&& apt-get install -y gh \
# APTのキャッシュを削除してイメージを軽量化する
&& rm -rf /var/lib/apt/lists/*
RUN groupadd --gid ${USER_GID} ${USERNAME} \
&& useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} \
&& echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USERNAME} \
&& chmod 0440 /etc/sudoers.d/${USERNAME}
WORKDIR /workspace
RUN chown -R ${USERNAME}:${USERNAME} /workspace
COPY . /workspace
# 略
コンテナに関わる設定を Docker に集約させる目的で明示的にマウント(COPY . /workspace)していますが、場合によっては不要です。
If you add the
imageordockerFileproperties todevcontainer.json, VS Code will automatically "bind" mount your current workspace folder into the container. Ifgitis present on the host'sPATHand the folder containing.devcontainer/devcontainer.jsonis within agitrepository, the current workspace mounted will be the root of the repository. Ifgitis not present on the host'sPATH, the current workspace mounted will be the folder containing.devcontainer/devcontainer.json.
Change the default source code mount | Visual Studio Code
手順
今回はリモートリポジトリを HTTPS で認証することを想定しています。
HTTPS での認証を選択した理由は後で述べます 💁♂️
ホストからもリモートリポジトリに接続したい場合、ホストにも GitHub CLI をインストールする必要があります。
GitHub CLI リポジトリ を参考にインストールしてください。
1. 開発コンテナ内で使用するユーザーを作成する
ホスト OS のユーザー(UID:1000, GID:1000)とコンテナ内のユーザーの権限を一致させています。
こうしないと、.git/ の権限が壊れ、ホストから Git 操作ができなくなることがあります。
ARG USERNAME=devuser
ARG USER_UID=1000
ARG USER_GID=1000
# 略
RUN groupadd --gid ${USER_GID} ${USERNAME} \
&& useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} \
&& echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USERNAME} \
&& chmod 0440 /etc/sudoers.d/${USERNAME}
WORKDIR /workspace
RUN chown -R ${USERNAME}:${USERNAME} /workspace
2. .git ディレクトリをマウントする
リポジトリルートをマウントすれば .git もマウントされます 🦍
COPY . /workspace
3. Git と必要なパッケージをインストールする
GitHub を HTTPS で認証するために ca-certificates、
GitHub の GPG 鍵をダウンロードするのに curl が必要です。
その他のパッケージは開発に必要そうなものたちです。
RUN apt-get update && apt-get install -y \
git \
ca-certificates \
curl \
vim \
less \
sudo \
procps \
ここまでで .git と Git が揃い、ローカルリポジトリの操作であれば可能になります。
4. GitHub CLI をインストールする
GitHub CLI リポジトリ を参考にインストールします。
# GitHub CLIのGPG鍵を設定する
&& mkdir -p -m 755 /etc/apt/keyrings \
&& curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
-o /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
# GitHub CLIのリポジトリを追加する
&& mkdir -p -m 755 /etc/apt/sources.list.d \
&& echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] \
https://cli.github.com/packages stable main" \
| tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
# GitHub CLIをインストールする
&& apt-get update \
&& apt-get install -y gh \
# APTのキャッシュを削除してイメージを軽量化する
&& rm -rf /var/lib/apt/lists/*
必要であれば、リモートリポジトリの URL を変更します。
git remote set-url origin https://github.com/<your_name>/<repo_name>.git
次のコマンドで GitHub を認証します。
コンソールの出力に従って操作してください。
gh auth login
これでリモートリポジトリに接続できます 🤝
リモートリポジトリを HTTPS で認証する理由
コンテナ内から SSH 接続をする方法として、次の 2 つの方法があります。
いずれの方法も、メリットが薄い or 設定が複雑なため採用しませんでした。
SSH 接続するためには、openssh-client のインストールが必要です。
apt-get install のところに追加してください。
1. ホストの SSH キーをマウントして使う
${HOME}/.ssh:/home/devuser/.ssh のようにマウントすることで、コンテナ内からリモートリポジトリに接続できます。
しかし、SSH キーは制約が厳しく、次の 2 つを満たさないと Permission Denied になります 🙅
- 所有者:鍵を使うユーザー本人である
- 権限:600(rw-------)または 400(r--------)である
ひょんなことから鍵を壊してしまうリスクがあると言えます。
SSH 接続を使うメリットも、「慣れているから」くらいしか見当たりませんでした。
コンテナ内に鍵を配置してまで得たいものでもなかったため、不採用としました。
2. ssh-agent のソケットをマウントして使う
ホストで ssh-agent を起動し、そのソケットをマウントする方法です。
コンテナ内に鍵を配置する必要がないため、安全と言えます。
しかし、以下の理由で、適切にマウントするには設定が複雑になってしまうため、不採用としました。
- 別プロセスから環境変数経由でソケットにアクセスできない
- 起動するたびにソケットの名前が変わる
おわりに
開発コンテナ内で、コーディングに関わる作業が完結するようになりました。
柔らかな気持ちになりました 🍑
余談
GitHub は、オーストラリアだと SNS に分類されるらしいです 😳