🙌
【夏休みの自由研究】Dev Containersを使って開発環境をコンテナ化してみよう
記事を書いた理由
- リポジトリはこちらdevcontainer-test
- Dev Containersを開発現場で導入するにあたって各種機能を試してナレッジが溜まったのでDev Containersの機能を試すようのリポジトリを作りました。
Dev Containersとはなにか
コンテナ内の環境をVSCodeで維持れるようになります。
ssh先でVSCodeを使うやつのコンテナバージョンでより便利な機能がたくさんあるよ〜くらいのイメージを持っていただければと思います。
Dev Containersを使うメリット
コンテナを使うことでチームで同じ開発環境を使うことができますが,Dev Containersを使うことでより同じ開発環境を使うことができ,新規開発者の参画のスピードアップが図れます。
- VSCodeのExtensionsをDev Containers使用時に自動インストール&set upできる
→Formatterやlinter,その他必要なExtensionsのセットアップを自動化できる。運用でExtensionsを導入してもらうのではなく,仕組みとしてExtensionsをチーム全体で使用できる。 - Dockerfile外でツールのインストールができる
→Dockerfileを汚さずに,使用するデバックツール等をコンテナで管理できる。 - Dev Containers用のcompose.yamlを配置して使えるのが結構便利
→開発用のcompose.yamlを使ってビルドできるので本番用のcompose.yamlを汚さずにすむ。
作成した検証用リポジトリで学べること
検証用リポジトリ→devcontainer-test
dotfilesを使って開発環境に必要な設定ファイルを持ち込む
- ~/.bashrc等をDev Containersに持ち込む機能。
- VSCodeの個人用のsettings.jsonに記載する。
- 設定は自分のGitHub上で管理している
dotfiles
リポジトリに合わせて変更すること。
// Dev Containersでdotfilesを使う。
// NOTE: .gitconfigは何もしなくてもDev ContainersのHOMEディレクトリにコピーされる。
"dotfiles.repository": "https://github.com/RyosukeDTomita/dotfiles.git",
"dotfiles.targetPath": "~/dotfiles",
"dotfiles.installCommand": "install.sh", // ~/dotfilesのrepository topからみたスクリプトのパスを指定する。
[!NOTE]
dotfiles.installCommand
には~/dotfilesのrepository topから見たスクリプトのパスを指定する。--> dotfilesのGitHub Repositoryにinstall.shは配置が必要。
指定しない場合のデフォルトファイル名は以下が認識される。
- install.sh
- install
- bootstrap.sh
- setup.sh
- setup
Extensions関連
拡張機能の設定ファイルをどこにおくか
- devcontainer.jsonと.vscode/settings.json両方に記載ができる。
- 基本は.vscode/settings.json配下で良いと思っているが一部コンテナ名等を使う場合にはdevcontainer.jsonに記載したほうが楽かも。
Extensionsを追する方法
例えば,peacockをインストールしたい場合には,インストールコマンドext install johnpapa.vscode-peacock
にて記載されるjohnpapa.vscode-peacock
をdevcontainer.jsonに記載すればよい。
DevContainerに自分だけが使用するExtensionsを持ち込む
- 個人用のsettings.jsonに記載する。.vscode/settings.jsonではないので注意。
// Devcontainerの個人的に使うExtensionsを入れる。
"dev.containers.defaultExtensions": [
"formulahendry.auto-rename-tag",
],
}
Dockerfileのマルチステージビルドを使ってDevContainer用の環境を作る
- Dockerfileを使う場合にはdevcontainer.jsonでtargetの指定ができる。
- 一方,compose.yamlを使う場合には別のcompose.yamlを準備する必要がある。
[!NOTE]
compose.yamlの優先順位は.devcontainer/compose.yamlが優先される。
# for devcontainer
version: '3'
services:
react-app:
build:
target: devcontainer // targetを指定
context: ./
dockerfile: Dockerfile
image: react-img-devcontainer:latest
container_name: react-container-devcontainer
ports:
- 80:8080 # localport:dockerport
# DevContainer
FROM node:20-bullseye AS devcontainer # targetに指定する値
WORKDIR /app
COPY . .
RUN cd react-default-app && npm install
# Build Image
FROM node:20-bullseye AS build
WORKDIR /app
COPY ./react-default-app .
RUN npm install && npm run build
[!NOTE]
- compose.yamlのサービス名をdevcontainer.jsonのserviceを同じにする必要がある。
# compose.yaml
version: '3'
services:
react-app: # devcontainer.jsonに指定するサービス名
build:
target: devcontainer
context: ./
dockerfile: Dockerfile
image: react-img-devcontainer:latest
container_name: react-container-devcontainer
ports:
- 80:8080 # localport:dockerport
{
"name": "dev-container-test", // 任意の名前
"dockerComposeFile": [
"../compose.yaml",
"compose.yaml"
],
"service": "react-app", // compose.yamlのサービス名
各種コマンドの使い方
{
"name": "dev-container-test",
"dockerComposeFile": [
"../compose.yaml",
"compose.yaml"
],
"service": "react-app",
"workspaceFolder": "/app",
"overrideCommand": true, // コンテナを起動したままにする DockerfileのCMDで永続するコマンドを実行しているなら不要
// rvest.vscode-prettier-eslintに使うパッケージをinstall
"postCreateCommand": "yarn add -D prettier@^3.1.0 eslint@^8.52.0 prettier-eslint@^16.1.2 @typescript-eslint/parser@^5.0.1 typescript@^4.4.4",
"postStartCommand": ["echo", "Hello, DevContainer"], // DevContainer起動時
"postAttachCommand": ["echo", "Hello, DevContainer"], // DevContainerに既存コンテナをattach時
"initializeCommand": ["echo", "Starting DevContainer..."], // DevContainerのビルド前,実行前にローカルで実行されるコマンド
installスクリプトを使う
必要そうなパッケージをまとめたinstall-pkg.sh
を作成し,postCreateCommandで実行する。
ディレクトリのマウント
- ファイル単体でのマウントはできないぽい。設定ファイルとかは前述のdotfilesを使って共有する。
{
"name": "dev-container-test",
"dockerComposeFile": [
"../compose.yaml",
"compose.yaml"
],
"service": "react-app",
"workspaceFolder": "/app",
"overrideCommand": true,
"mounts": [
"source=~/.aws,target=/home/root/.aws,type=bind" // ~/.awsをマウントできる
],
Discussion