Dev Containerで始める 2-click 開発環境セットアップ

by

@wapa5pow

Dev Containerとは何でしょうか。

エンジニアの嗜みとも言える環境構築ですがなれていたとしても時間がとられます。Pythonの環境を構築するとしてもバージョンを同じにするためにpyenvなどのツールを入れる必要があるかもしれません。さらに知らない言語の環境構築ともなると一から調べねばならず非常に骨がおれます。最近だとM1など別のアーキテクチャが出てきたときにパッケージが対応しておらず環境が構築できない場合もあります。
さらに環境構築ができたとしても時間とともに新しいパッケージのバージョンに対応したりなど開発者同士で開発環境をあわせることは大変です。

Dev Containerは、この骨の折れる開発環境構築を 2-click で実現できる機能です。
仕組みとしては、.devcontainerフォルダにdevcontainer.jsonなど設定を作成します。その設定とDockerイメージをもとにVSCodeがコンテナに環境を構築し、まるでローカルで開発しているかのようにコンテナの中で開発ができます。

Dev Containerを使って、dbtプロジェクトのSQLの開発をできるようにしたのでやり方を紹介します。

dbtプロジェクトの開発で達成したいこと

明確に達成したい目標がありました。プロジェクトで、エンジニア以外はdbt cloudを使って開発していたのですが、gitのブランチが扱いずらかったりlintの結果が確認できなかったり、dbtの実行がすばやるできないなど不満がありました。
そのため以下の要件が満たせるDev Containerの環境を構築することにしました。なお動作検証したのはmacOSです。

  1. エンジニア以外もSQLを開発するので簡単に開発環境構築ができる
  2. SQLのlintであるsqlfluffが開発時に動作すること
  3. ターミナルからgitが使えること
  4. ターミナルからdbt runコマンドが実行できBigQueryに格納できること

.devcontainer/*は以下のようになっています。

.devcontainer/
├── Dockerfile
└── devcontainer.json
Dockerfile
ARG VARIANT="3.9"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}

ARG NODE_VERSION="none"
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi

COPY requirements.txt /tmp/pip-tmp/
RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
   && rm -rf /tmp/pip-tmp

RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
RUN apt-get install -y apt-transport-https ca-certificates gnupg
RUN curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -

RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
    && apt-get -y install --no-install-recommends lv google-cloud-sdk jq bash-completion \
    && rm -rf /var/lib/apt/lists/*
devcontainer.json
{
	"name": "dbt",
	"build": {
		"dockerfile": "Dockerfile",
		"context": "..",
		"args": {
			"VARIANT": "3.8",
			"NODE_VERSION": "lts/*"
		}
	},
	"mounts": [
		"source=${localEnv:HOME}/.dbt,target=/home/vscode/.dbt,type=bind,consistency=cached",
		"source=${localEnv:HOME}/.config/gcloud/application_default_credentials.json,target=/home/vscode/.gcloud/application_default_credentials.json,type=bind,consistency=cached",
	],
	"settings": {
		"python.pythonPath": "/usr/local/bin/python",
		"python.linting.enabled": true,
		"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
		"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
		"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
		"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
		"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
		"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
		"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
		"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
		"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint",
		"sql.linter.executablePath": "/usr/local/bin/sqlfluff",
		"macros": {
			"commentLine": [
				"editor.action.commentLine",
				"cursorDown"
			],
			"copyWithoutNewLine": [
				"cursorHome",
				"cursorEndSelect",
				"editor.action.clipboardCopyAction",
				"cancelSelection"
			]
		},
	},
	"extensions": [
		"ms-python.python",
		"dorzey.vscode-sqlfluff",
		"geddski.macros"
	],
	"remoteUser": "vscode",
	"remoteEnv": {
		"CLOUDSDK_CONFIG": "/home/vscode/.gcloud"
	}
}

先程の4の「ターミナルからdbt runコマンドが実行できBigQueryに格納できること」を実現するためにはgcloudの認証情報と~/.dbt/profiles.ymlが必要です。devcontainer.jsonmountsにその設定がかいてあります。gcloudの認証情報がおいてある~/.configはDev Containerで作成される~/.configとパスがかぶっているのでCLOUDSDK_CONFIGを設定することにより別のパスから読み込めるようにしてあります。

上記を動かすには事前にgcloud auth application-default loginが実行してあることと以下のような~/.dbt/profiles.ymlファイルが必要です。

default:
  target: target
  outputs:
    target:
      type: bigquery
      method: oauth
      project: project-name
      dataset: dbt_wapa5pow
      threads: 15
      timeout_seconds: 300
      location: US
      priority: interactive
      retries: 1

設定し終わったら以下のようにボタンを 2-click すると環境ができあがります。

run-dev-container

lintもばっちりきいていますね。

lint

まとめ

手間がかかりバージョン差分も出やすいローカル開発環境の悩みをDev Containerで解決しました。
たとえ環境構築にたしなみがあったとしても 2-click でできる環境構築は魅力的です。
一度設定すればずっと利用できるのでいいなと思ったらDev Container利用してみてください。