開発環境

Visual Studio Code と Docker コンテナを使って開発する

開発環境

技術部データ基盤チームの @zaimy です。今回は、 Visual Studio Code(以下 VS Code)と Docker コンテナを使って開発環境を構築する方法を紹介します。

データ基盤エンジニアの開発環境として、Python を使用する単一コンテナを例に記述しますが、他の言語や Docker Compose を使う場合でも応用できます。

背景: M1 Mac (Monterey) に Python 3.8.12 をインストールできない

先日、業務で使用するマシンを Intel Mac から M1 Mac に切り替えたのですが、CPU アーキテクチャが異なることに加えて、OS のバージョンが上がったことで Apple Clang に下位互換性のない変更が入っており、業務上ある理由で必要な Python 3.8.12 のインストールが困難でした。

そこで、私の所属するチームは全員が IDE に VS Code を使っているため、VS Code の拡張機能「Remote - Containers」を使って、Docker コンテナに開発環境を構築することにしました。

できるようになること

ホストマシン上の VS Code を使ってローカルの開発環境を触るのと同じように、コンテナ内の環境で VS Code で開発を行えるようになります。ソースコードはホストマシンからマウントされ、拡張機能はコンテナ内にインストールされます。

従来は Python のバージョンとパッケージバージョンを pyenvPoetry で統一していましたが、Docker コンテナを使うため環境自体が統一されることに加えて、コンテナ内にインストールする VSCode の拡張機能やワークスペースの設定値もコードベースで定義できるため、チーム内でおすすめの拡張機能や設定を共有することが容易になり、開発効率の向上にも繋がると考えています。

Visual Studio Code Remote - Containers拡張機能のアーキテクチャ Developing inside a Container using Visual Studio Code Remote Development より引用

用意するもの

次のファイルを .devcontainer ディレクトリ配下に用意します。以下でそれぞれ詳しく見ていきます。

  • Dockerfile
  • devcontainer.json
  • postCreateCommand.sh

Dockerfile

開発環境用の Dockerfile です。今回は素朴に以下のような環境を用意しました。git や jq など開発時に使用するコマンドと、対象とするリポジトリで Python のパッケージ管理に使用する Poetry をインストールしています。

FROM python:3.8.12-slim
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8

RUN apt-get -y update && apt-get upgrade -qqy && apt-get -y install \
        bash \
        curl \
        gcc \
        git \
        jq

# Apply https://github.com/pypa/setuptools/pull/3108
RUN pip install --upgrade setuptools

RUN curl -sSL https://install.python-poetry.org | python3 -
ENV PATH /root/.local/bin:$PATH

devcontainer.json

Dockerfile のパス、コンテナにインストールする拡張機能、VS Code の設定などを定義します。 コンテナの作成後に実行される postCreateCommand は、簡単なワンライナーなら直接定義しても良いですが、複数行に渡る場合は別ファイルに切り出すと便利です。

{
    "name": "dev",
    "dockerFile": "Dockerfile",
    "postCreateCommand": "./.devcontainer/postCreateCommand.sh",
    "extensions": [
		"ms-azuretools.vscode-docker",
		"ms-python.python",
		"ms-python.vscode-pylance",
    "...",
	],
    "settings": {
        "terminal.integrated.profiles.linux": {
            "bash": {
              "path": "/bin/bash",
            }
        },
        "terminal.integrated.defaultProfile.linux": "bash",
        "python.linting.flake8Enabled": true,
        "python.formatting.provider": "black",
        "[python]": {
            "editor.formatOnSave": true,
            "editor.codeActionsOnSave": {
                "source.organizeImports": true
            }
        },
    }
}

postCreateCommand.sh

コンテナの作成後に実行するコマンドを書いています。

devcontainer.json と postCreateCommand.sh については、リポジトリでは devcontainer.json.sample と postCreateCommand.sh.sample のようにチームに共通するおすすめの定義だけを管理しており、実際に使用する定義は個人の好みに合わせて変更しています。私はここで fishstarship のインストール、コマンドのエイリアス設定などを行い、コンテナ内のターミナル環境をホストマシン相当のものにしています。

#/bin/bash

mkdir -p ~/.config/git
echo '.DS_Store' >> ~/.config/git/ignore

rm -rf .venv
poetry config virtualenvs.create false
poetry install

起動方法

ホストマシンの VS Code に拡張機能「Remote - Containers」をインストールして、画面左下の緑色のアイコン「Open a remote menu」をクリックした後に表示されるメニューから「Reopen in Container」を選択します。

Remote menu を開くアイコン

Remote menu

または、devcontainer.json を含むリポジトリを VS Code で開くとポップアップメッセージが表示されます。ここから「Reopen in Container」を選択します。

ポップアップメッセージ

初回起動時は Dockerfile に従ってコンテナが作成された後、devcontainer.json に従って拡張機能のインストールや postCreateCommand の実行が行われます。後は、ホストマシン上の VS Code と同様に開発を始められます。

2回目以降の起動時も同様の手順でコンテナに接続できます。

その他

Docker イメージによっては、サポートするアーキテクチャに arm を含まない場合があります。ペパボで主に利用している colima では、QEMU レイヤでのエミュレーションにより M1 Mac でも x86 のイメージを動作させることができますが、同じ処理内容に掛かる実時間を比較すると数倍以上の差が出るためご注意ください。arm と x86 の両方のアーキテクチャをサポートするイメージであれば、コンテナの恩恵によりホストマシンの環境差異によらず安定的に開発環境を構築できます。

イメージがサポートするアーキテクチャは、Docker Hub の場合「Quick reference (cont.)」>「Supported architectures」の項目で確認できます。

まとめ

VS Code の拡張機能「Remote - Containers」と Docker コンテナを使って開発環境を構築する方法をご紹介しました。データ基盤チームでは、チームにメンバーが増えた際も、引き続き簡易に素早く開発環境を構築できる体制を整えて、データ駆動なサービス開発を加速させていきたいと考えています。