VS Code の Dev Container で複数のコンテナを起動する
ふだんは VS Code エディタの Dev Container を利用して開発環境を構築しています。通常は一つのコンテナだけを利用していますが、グラフデータベースのNeo4jを利用したかったので、開発用に利用するPython環境のコンテナとNeo4jのDockerイメージを利用したコンテナの二つを立ちあげてみました。この記事は、そのときの設定のメモです。
概要
VS Code エディタの Dev Container は、開発環境をコンテナ内に閉じ込めることができるため、OSの環境を気にせずいじれますし、Dockerfile
やdevcontainer.json
などの設定ファイルを通じて、手軽に同一環境を構築できる点で、とても重宝しています。
特定の言語やフレームワークのみの開発であれば、単一のコンテナ上に開発環境を構築すればよいのですが、データベースの動作確認などに公式のDockerイメージを使いたいというような場合には、複数のコンテナを立ち上げることになります。
今回は、ナレッジグラフでRAGを構築することを目的に、以下の2つのコンテナを Dev Container で立ち上げてみました。
- Python + Langchain 開発環境(Pythonベースイメージにpipで必要なパッケージをインストール)
- Neo4jデータベース(Neo4j公式のDockerイメージそのまま)
docker-composeを利用して2つのコンテナを立ち上げ、Python側のコンテナからNeo4jデータベースのコンテナにアクセスさせることを目的とします。
※ナレッジグラフでRAGを動作させてみた結果については、別の記事で報告する予定です。
前提条件
今回は、Windows10上に以下のソフトウェアがインストールされていて、Dev Container を利用していることが前提となります。
- VS Code エディタ 1.87.2
- Docker desktop 4.28.0
VS Code エディタでの Dev Container の開発環境の構築方法については、以下の記事が参考になります。
各種設定
それでは、各種の設定を紹介していきます。
ファイルの配置
VS Code ワークスペースからみたファイルの配置は以下のとおりです。
(VS Code Workspace)
├─.devcontainer/
│ | devcontainer.json
|
├─app/
│ │ Dockerfile
│ │ requirements.txt
|
├─neo4j/
|
| docker-compose.yml
app
ディレクトリはPython+Langchainコンテナ用、neo4j
ディレクトリはNeo4jデータベース用です。Python+Langchainの開発環境用コンテナは、Dockerfileで構成を定義します。また、Dockerfile内で読み込むPythonのパッケージリストを記載したrequirements.txt
も配置します。
appコンテナのDockerfile
Python+Langchainの開発環境のコンテナの構成を定義するDockerfile
の内容は以下のとおりです。
FROM python:3.11
COPY requirements.txt /tmp/pip-tmp/
RUN pip3 install -r /tmp/pip-tmp/requirements.txt \
&& rm -rf /tmp/pip-tmp
# Workspace
RUN mkdir -p /workspace
Pythonの公式Dockerイメージをベースに、requirements.txt
に記載したパッケージをインストールしているだけです。
requirements.txt
は以下のとおりです。
langchain
langchain-community
langchain-openai
langchain-experimental
neo4j
wikipedia
tiktoken
python-dotenv
必要なパッケージがあれば、ここに追加してコンテナをRebuildすればOKです。Rebuildの方法はあとで説明します。
docker-compose.yml
複数のコンテナを立ち上げるために、Docker Compose を利用します。Docker Compose は以下のようなツールです。
Compose とは、複数のコンテナを定義し実行する Docker アプリケーションのためのツールです。Compose は YAML ファイルを使い、アプリケーションのサービスを設定します。コマンドを1つ実行するだけで、設定内容に基づいた全てのサービスを生成・起動します。
(出典)Docker Compose 概要(Docker公式)
複数のコンテナを立ち上げる際の構成や設定をYAML形式で簡易に記述できるツールです。設定はdocker-compose.yml
というファイルに記述します。VS Code の Dev Container からも、docker-compose.yml
ファイルを指定して起動することができます。
docker-compose.yml
の内容は以下のとおりです。
version: '3'
services:
app:
build:
context: ./app
dockerfile: Dockerfile
depends_on:
- neo4j
container_name: app_container
volumes:
- .:/workspace
environment:
- NEO4J_URI=bolt://neo4j:7687
- NEO4J_USER=neo4j
- NEO4J_PASSWORD=neo4jpassword
tty: true
command: sleep infinity
neo4j:
image: neo4j:latest
container_name: neo4j_container
ports:
- "7474:7474" # HTTP
- "7687:7687" # Bolt
environment:
- NEO4J_AUTH=neo4j/neo4jpassword
- NEO4JLABS_PLUGINS=["apoc"]
volumes:
- ./neo4j/data:/data
- ./neo4j/logs:/logs
- ./neo4j/import:/var/lib/neo4j/import
- ./neo4j/plugins:/plugins
servicesにあるapp
とneo4j
のセクションが、それぞれPython+Langchain用コンテナとNeo4jデータベース用コンテナの設定になります。
以下、ポイントを説明します。
app:
build:
context: ./app
dockerfile: Dockerfile
build
のところは、コンテナをどのように構成するかを記述します。context
に(docker-compose.yml
ファイルがあるディレクトリからみた)ディレクトリ名を、dockerfile
にDockerfileのファイル名を設定します。上の設定では、./app/Dockerfile
を利用してコンテナを構築することを示しています。
app:
...
volumes:
- .:/workspace
volumes
は、ホストのディレクトリ(今回の場合はWindows10側の作業ディレクトリ)を、コンテナ内の指定されたディレクトリにマウントするための設定です。
ホスト側のカレントディレクトリ(docker-compose.yml
があるVS Code ワークスペースのルートディレクトリ)が、appコンテナの/workspace
ディレクトリにマウントされ、コンテナ側からホストにあるソースファイル等にアクセスすることができるようになります。
app:
...
environment:
- NEO4J_URI=bolt://neo4j:7687
- NEO4J_USER=neo4j
- NEO4J_PASSWORD=neo4jpassword
environment
には、コンテナ内で参照できる環境変数を設定します。Python+Langchain側のコンテナから、Neo4jコンテナにアクセスするためのURLやUSER名、パスワードなどを設定しています。
NEO4J_URI
がbolt://neo4j:7687
となっています。ホスト名がneo4j
となっていますが、Docker Compose では、docker-compose.yml
で設定したサービス名(app
やneop4j
)で、そのコンテナにアクセスできるよう名前解決がされます。
次は、Neo4jデータベース用のコンテナの設定についてです。
neo4j:
image: neo4j:latest
Neo4j公式のDockerイメージをそのまま使うため、image
にイメージ名を設定しています。これで、Docker Hubからこのイメージをダウンロードして起動してくれます。
neo4j:
...
ports:
- "7474:7474" # HTTP
- "7687:7687" # Bolt
ports
は、ホスト側のポート番号とコンテナ側のポート番号のマッピングを記述します。ホスト側の7474番にアクセスすると、Neo4jデータベースコンテナの7474番ポートに転送されます。
ちなみに、Neo4jの7474番ポートにブラウザでアクセスすると、GUIベースでNeo4jデータベースの内容を確認できます。
neo4j:
...
volumes:
- ./neo4j/data:/data
- ./neo4j/logs:/logs
- ./neo4j/import:/var/lib/neo4j/import
- ./neo4j/plugins:/plugins
volumes
はapp
コンテナのほうで説明したものと同じです。Neo4j公式イメージでは、/data
ディレクトリにデータベースが、/log
ディレクトリにログが保存されるようになっています。データベースを永続化するために、ホスト側のフォルダ./neo4j/*
をマウントしています。
devcontainer.json
Dev Container の設定ファイルdevcontainer.json
は以下のとおりです。
{
"name": "Neo4j and Python + Langchain Development",
"dockerComposeFile": "../docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"customizations": {
"vscode": {
"extensions": [
"ms-python.isort",
"ms-python.vscode-pylance",
"eeyore.yapf",
"ms-python.python",
"njpwerner.autodocstring"
]
}
}
}
dockerComposeFile
に、先ほど作成したdocker-compose.yml
を設定します。この設定により、このdevcontainer.json
ファイルがあるフォルダで VS Code エディタを立ち上げると、docker-compose.yml
を読み込んで、app
とneo4j
の2つのコンテナを起動します。
service
には、docker-compose.ymlファイル内で定義されたサービスのうち、VS Codeで使用するサービスを指定します。app
コンテナは、Pythonでの開発環境のメインとなるコンテナですので、ここではapp
を指定しています。
"customizations": { "vscode": { "extensions": [...] } }
では、VS Codeの拡張機能を指定しています。ここはふだん利用しているものを指定しておけばよいでしょう。上の例では、Pythonのフォーマッタなどを指定しています。
Dev Container の起動
それでは、上記の設定ファイルをもとに、Dev Container を起動してみましょう。ワークスペースとなるフォルダを VS Code で開くと、エディタの右下に以下のようなメッセージが表示されます。
「コンテナーで再度開く」をクリックすると、上記の設定ファイルをもとに、コンテナを起動してくれます。始めて起動するときは、コンテナイメージをダウンロードしたり、Dockerfileをもとにコンテナを構成したりする作業が始まるため、起動するまでに少し時間がかかります。
WindowsのDocker Desktopで、コンテナが正常に起動しているかを確認してみましょう。Docker Desktopの左側の"Containers"を選択して、動作しているコンテナを確認しましょう。
app_container
とneo4j_container
の2つがRunning
と表示されていて、正常に動作していることがわかります。このコンテナの名前は、docker-compose.yml
のcontainer_name
で設定したものです。何も設定しないと、数字やアルファベットの羅列になり、何のコンテナかがわかりずらくなってしまうので、設定しておいた方が良いでしょう。
VS Code エディタの左下の表示が「開発コンテナ-: <開発コンテナ名>」となっていることも確認しておきましょう。この表示が出ているときは、コンテナ内の開発環境でVS Codeが起動していることになります。
Neo4jデータベースのコンテナにもアクセスしてみましょう。ホスト側のWindowsのブラウザから、localhost:7474
にアクセスすると、上のような画面が表示されます。設定したユーザ名とパスワードを入力すれば、グラフデータベースの中身を確認できる画面へ移動できます。
ホスト側のWindowsからアクセスできるのは、docker-compose.yml
のports
で、ホスト側とコンテナのポート番号のマッピング(転送設定)をしてあるためです。開発環境のapp
コンテナからは、neo4j
というホスト名でアクセスできます。
コンテナの再構成(Rebuild)
コンテナの構成ファイルとなるDockerfile
やdocker-compose.yml
などを変更した場合には、コンテナの再構成が必要となります。
VS Code エディタをいったん閉じて、再度開くと、再構成後のコンテナイメージで起動するはずです。コンテナイメージはキャッシュされていて、必要なものだけをダウンロード、あるいは、再構成しますので、初回起動時ほどは時間がかからないはずです。
ただ、たまにうまく再構成できない場合もあります。そのような場合は、VS Code のコマンドパレットからDev Containers: Rebuild Container Without Cache
を実行すると、キャッシュを利用せずに、一からコンテナイメージを作り直してくれます。
まとめ
VS Code の Dev Container で、複数のコンテナを動作させてみました。
ポイントとなるのは Docker Compose の設定ファイルとなるdocker-compose.yml
です。YAMLで簡潔に記述できますし、内容もそれほど難しいものではありません。docker-compose.yml
の書き方さえマスターしてしまえば、2つといわず、3つでも4つでもコンテナを立ち上げることができます。
なお、今回は、メインの開発環境のコンテナapp
+データベースのコンテナneo4j
という構成で、データベース側のコンテナはほどんといじる必要はありません。そのため、VS Code エディタ上からは、メインのapp
コンテナのターミナルやファイルだけを操作できる構成としています。
複数のコンテナのターミナルやファイルにアクセスする必要がある場合は、もう少し工夫する必要があります。例えば、以下の記事が参考になります。
Discussion