このリポジトリは、新規のプロジェクトや既存のプロジェクトにDev Containerを導入するためのスターターキットです。
- SSH経由でコンテナにログインできます。
- エディタの起動高速化: VS Code、JetBrains IDE、Cursor、Neovimの設定をキャッシュしているので、2回目以降の起動が高速化されます。
- Chezmoiがすぐ使えます。
- Nixがすぐ使えます。Nixで導入したツールがVS Codeでも使えます。
- GitHub CLI(gh)がログイン済み状態で使い始められます。
- Direnvがすぐに使えます。
.bashrc
、.zshrc
、config.fish
を「チームで共通化したい」vs「個人でカスタムしたい」が両立可能です。
- Docker Desktop for MacやOrbStackなどのDocker環境
- リモートのLinuxでDockerが利用できる状態になっていること
- リモートのLinuxにSSHでログインできること
- Dev Container CLIがインストールされていること
このリポジトリの .devcontainer
ディレクトリをコピーして、自分のプロジェクトのルートディレクトリに配置します。リリースページに.devcontainer
ディレクトリをダウンロード&展開するワンライナーがあるので、それを使うと便利です。
ホストマシン側の ~/.ssh/authorized_keys
に公開鍵を追加しておきます。
ホストマシンで gh auth login
しておきます。
ホストマシンの ~/.local/share/chezmoi
ディレクトリにChezmoiの設定ファイルを配置しておきます。
ホストマシン上で以下のコマンドを実行します。
devcontainer up --workspace-folder .
TODO
TODO
TODO
devcontainer exec --workspace-folder . bash
この方法では、SSHエージェントが使えないため、コンテナ内でプライベートリポジトリに対してgitの操作ができません。通常の開発作業ではSSH経由でログインすることをお勧めします。
docker ps
でコンテナのIDを調べて、以下のコマンドを実行します。
docker exec -it <container-id> bash
この方法では、SSHエージェントが使えないため、コンテナ内でプライベートリポジトリに対してgitの操作ができません。通常の開発作業ではSSH経由でログインすることをお勧めします。
ssh -p 2222 vscode@127.0.0.1
基本的な設定は以下の通りです。
Host devcontainer
HostName 127.0.0.1
Port 2222
User vscode
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
と UserKnownHostsFile /dev/null
は、セキュリティ的には望ましくない設定ですが、開発環境として使うためには便利です。
Dev Containerは日々破棄と構築が繰り返されることが前提であるため、フィンガープリントがちょくちょく変わることがあります。
これらをセットしておかないと、~/.ssh/known_hosts
を日々メンテナンスする必要が出てきます。
したがって以上の設定をしておき、フィンガープリントの確認をスキップする設定にしておいたほうが、開発体験が向上します。
これに加えて、SSHエージェントの転送を有効化しておくと、コンテナ内でプライベートリポジトリに対してgitの操作ができます。
TODO: SSHエージェントの転送の設定方法を追記する
鍵を使わない場合、上の「直接ログイン」の方法でログインし、sudo passwd vscode
でパスワードを設定しておく必要があります。開発環境として使うため、セキュリティ的には望ましくないと思われるので、鍵を使うことをお勧めします。
コンテナへのログインは以下の通りです。
ssh devcontainer
devcontainer build --workspace-folder .
起動中のDev Containerを削除しつつ、再ビルド、再起動まで一度に行う場合は次のコマンドを実行します。
devcontainer up --workspace-folder . --remove-existing-container
devcontainer down
コマンドは未実装のため、代わりに次の手順を行います。
docker compose ls
で当該プロジェクト名を調べます。
見つかったプロジェクト名を使って以下のコマンドを実行します。
docker compose --project-name <project-name> down
ただし、この方法では削除されるのはコンテナとネットワークだけです。イメージやボリュームもまとめて削除したい場合は以下のコマンドを実行します。
docker compose --project-name <project-name> down --volumes --rmi all --remove-orphans
このコマンドの詳細は《滅びの呪文》Docker Composeで作ったコンテナ、イメージ、ボリューム、ネットワークを一括完全消去する便利コマンド #docker-compose - Qiitaを参照してください。
このDev Containerは、チーム開発向けの設定と個人向けの設定を両立させることを目指しています。
チーム共通の設定は、
- ~/team.bash
- ~/team.zsh
- ~/team.fish
に記述します。これは、それぞれ
- ~/.bashrc
- ~/.zshrc
- ~/.config/fish/config.fish
から読み込まれることを想定しています。したがって、シェルを個人的にカスタマイズしたい場合は、これらのファイルを編集して構いませんが、チーム共通の設定を忘れずにsource
することを推奨します。
dotfilesをChezmoiで管理している場合は、すでにchezmoi
コマンドが使える状態になっているので、Dev Container内で以下のコマンドを実行します。
chezmoi init --apply
Dev Containerにはnix
コマンドがインストールされているので、Nixの設定ファイルを持っている場合は、Dev Container内で以下のコマンドを実行します。
nix develop # など
このDev Containerには、Direnvが導入済みなので、.envrc
ファイルを使って環境変数を設定することもできます。おそらくこちらの設定のほうが、毎回nix develop
を実行する必要がないので便利でしょう。
# /workspace/.envrc
use flake
プロジェクトルートのflake.nix
で指定したパッケージをVS Codeで利用するためには、direnv拡張をVS Codeにインストールしてください。
プロジェクトルートに.envrc
を作り、次の内容を書いておいてください。
use flake
この状態でVS Codeを開くと、direnv allowを求められます。許可するとNixのパッケージにパスが通るので、VS Codeの各種拡張からNixで導入したツールが利用できるようになります。許可してもうまくパスが通っていないようであれば、VS Codeを再起動してみてください。
複数のプロジェクトを同時に起動しようとすると、ポートの競合が発生します。
.devcontainer/.env
のHOST_ADDR
をプロジェクトごとにIPアドレスを変えることで、一応ポートの競合を回避できます。
ただし、この方法は開発者個々人がIPアドレスを自由に決める裁量がないため、チーム開発には向いていない可能性があります。開発者ごとに携わっているプロジェクト数が異なる可能性があるためです。このあたりの改善は今後の課題とします。
GitHub ActionsでDev Containerを再利用したいときは、devcontainer/ciアクションを使うと良いでしょう。
name: Dev Container Build Check
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run devcontainer build
uses: devcontainers/ci@v0.3
with:
runCmd: yarn test
以上はシンプルな導入例ですが、ドキュメントにはDev Containerのビルドをキャッシュする方法など高度なトピックについても記載されています。
Dev ContainerがビルドできるかをCIでテストすることができます。以下のようなGitHub Actionsの設定ファイルを用意して、リポジトリに配置します。
name: Dev Container Build Check
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
devcontainer-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Dev Container CLI
run: npm install -g @devcontainers/cli
- name: Run devcontainer build
run: devcontainer build --workspace-folder .
CIでもDev Containerの環境を用いて、テストやビルドなど何らかのタスクを行いたいことがあるかもしれません。 その場合は、以下のようなGitHub Actionsの設定ファイルを用意して、リポジトリに配置します。
name: Use Dev Container in CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
devcontainer-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Dev Container CLI
run: npm install -g @devcontainers/cli
- name: Execute something in Dev Container
run: devcontainer exec --workspace-folder . echo "Hello, Dev Container!"
このDev Containerをカスタマイズする方法はいくつかあります。
Dev Containerの設定ファイルです。本リポジトリでは扱っていない設定も沢山あります。カスタマイズが必要になったら下記公式ドキュメントを参照してみてください。
Dev Container Featuresは、開発コンテナの機能を拡張するためのモジュラーなコンポーネントです。これらを使用することで、開発者は必要な言語サポート、ツール、設定などを柔軟に追加し、プロジェクト固有の要件に合わせて開発環境をカスタマイズできます。再利用可能で、バージョン管理が可能なため、一貫性のある環境構築を容易にします。
このDev ContainerでもすでにいくつかのFeaturesを利用しています。
利用可能なDev Container Featuresの一覧は以下のURLから確認できます。
https://containers.dev/features
Dev Containerの起動が遅いと、開発体験が悪くなります。そのため、Dev Containerの起動を高速化は重要です。
Dev ContainerはDockerをベースとしているため、起動を高速化するにはDockerビルドの最適化に関する次のような知識が必要です。
- イメージを小さくする
- レイヤーキャッシュがよく効くようにする (単純にレイヤー数を減らせば速くなるわけではなく、適切に分割することが重要)
- コンテキストをできるだけ小さくする
- ボリュームを使う
この手の最適化はdive
やdocker diff
などのツールを使って、Dockerイメージのレイヤーを分析する必要があります。
Dockerビルド時にDockerデーモンに転送するファイルが増えると、ビルドが遅くなります。
Dev Containerを構成する上で不要なファイルがコンテキストに含まれていないかチェックしましょう。
チェックにはdocker-show-context
を使うと便利です。不要なファイルが除外されるように、コンテキストを指定する、.dockerignore
ファイルを適切に設定するなどの対策を行いましょう。
Dev Containerの開発体験はDockerビルドのパフォーマンスだけでなく、IDEの起動にかかる時間や、yarn install
などの初回セットアップ手順にかかる時間も重要になってきます。
このDev Containerでは、「ボリュームを使う」アプローチを用いて、初回セットアップ手順の高速化を図っています。
この最適化はツールがどこにキャッシュや設定ファイルを作るかを理解する必要があります。
ツールがどこにファイルを作るかを知るには、docker diff
コマンドを使うと便利です。
docker diff <container-id> | sort
これにより見つかったファイルをボリュームにマウントすることで、2回目以降のセットアップ手順の高速化が期待できます。
ボリュームマウントする方法は、devcontainer.json
のmounts
セクションを使うと簡単に設定できますが、このDev Containerでは docker-compose.yml
を使ってボリュームマウントを設定しています。
Dev Containerの仕様で、設定updateRemoteUserUID
が有効になっているとき、ホストマシンのユーザーIDに合わせてコンテナ内のユーザーIDを変更します。この変更がイメージとして作られた結果です。
このDev Containerは以下のリポジトリを参考に構成されています。
- https://github.com/suin/devcontainer-starter (MIT LICENSE)