【開発環境コンテナ化】DevContainer✕docker composeで環境構築を自動化してみる

2024/07/12に公開

DevContainerとは

  • Dockerコンテナの中でVSCodeを開ける。
  • VSCodeの拡張機能もコンテナで管理できる。
  • 設定ファイルは.devcontainer/devcontainer.jsonに設定ファイルに記載する。
  • Dockerfileを汚さずに開発環境をチームで統一できるのが嬉しい

デモを試す

今回デモを作ったのでそれを使ってDevContainerの機能を試せます。

  1. DockerとVSCodeをインストールする。
  2. devcontainer-sampleをclone
  3. VSCodeで開いて,Reopen in Containerを選択する。
git clone https://github.com/RyosukeDTomita/devcontainer-test
cd devcontainer-test
code .

デモで試せるDevContainerの機能

compose.yamlからコンテナを起動する

  • 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のサービス名

Extensions関連

拡張機能の設定ファイルをどこにおくか

  • devcontainer.jsonと.vscode/settings.json両方に記載ができる。
  • 基本は.vscode/settings.json配下で良いと思っているが一部コンテナ名等を使う場合にはdevcontainer.jsonに記載したほうが楽かも。

ExtensionsをDevContainerで管理する

例えば,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

参考1
参考2

各種コマンドを使う

{
  "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に追加する。

ディレクトリのマウント

  • ファイル単体でのマウントはできない。
{
  "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をマウントできる
  ],
  • ~/.gitconfigはデフォルトで,DevContainer上のホームディレクトリにコピーされている。

GitHubで編集を提案

Discussion