目次
前回の記事で、VS Code+Dev Containerを導入しました。 残課題として「マルチコンテナ化」があるという話もしました。今回はDev Containerのdocker-compose.yml対応をした話をメモとして残しておきます。 実際、VS Code + Dev Containerに移行した後に、Esを起動してアプリからつなげるというのがうまくいかないというのがあったので対応がんばりました。。。
Dev Containerのdocker compose設定
この記事ではすでにdocker-compose.ymlが存在している状態の話をします。 変更する前は、devcontainer.jsonでベースのコンテナイメージの指定、マウントの設定などを行っていましたが、docker-compose.ymlにいくつかを移動しないといけません。 対応した時の作業の流れは以下のような感じです。
- ワークスペース用のDockerfileの作成
- docker-compose.ymlにワークスペース用のサービスを追加
- devcontainer.jsonをdokcer-compose.ymlを利用する形に書き換え
- アプリでの接続文字列をlocalhostからdocker-compose.ymlのサービス名に変更
参考:対応した時のコミットです。差分などはこちらをごらんください。
devcontainerのリポジトリにPython+PostgreSQLのサンプルが公開されており、こちらを参考にしながら作業をしました。
1. Dockerfileの作成
docker-compose.ymlだけでも完結するのかもしれないですが、いろいろやりたいことも出てくるかもしれないので別のファイルに切り出しました。 といっても、コンテナのイメージはdevcontainer.jsonに記述していたものを使っています。
ARG VARIANT=3.11-bookworm
FROM mcr.microsoft.com/devcontainers/python:${VARIANT}
ENV PYTHONUNBUFFERED 1
ENV TZ Asia/Tokyo
TZ
はdevcontainer.jsonで指定していたものを、こちらに移行した形になります。
PYTHONUNBUFFERED
は参考にしたDockerfileの記載です。標準出力・エラーをバッファリングしない指定になっています。
2. dokcer-compose.ymlにサービス追加
backend
という名前のサービスをdevcontainer(VS Code)から接続するコンテナのサービス名にしています。
services:
backend:
build:
context: .
dockerfile: .devcontainer/Dockerfile
init: true
environment:
- TZ=Asia/Tokyo
command: sleep infinity
volumes:
- .:/workspace/search-research:cached
- venv-search-research-backend:/workspace/search-research/.venv
...
volumes:
venv-search-research-backend:
1.で作成したDockerfileを利用します。docker-compose.ymlファイル自体は、プロジェクトのルートディレクトリに配置していますが、Dockerfileは.devcontainer
ディレクトリに入れたため、context
とdockerfile
はこのような指定になっています。
init
は、devcontainer.json
で指定していた"runArgs": ["--init"],
の設定になります。
command
の部分は、コンテナが起動したままにしておくための設定です。
volumes
では2つのボリュームに関しての指定があります。
1つ目の/workspace...
は、VS Codeがコンテナにプロジェクトをマウントする場所の指定です。
devcontainer.json
だけを利用していた場合は意識していませんでしたが、/workspace/プロジェクト名
というディレクトリにプロジェクトがマウントされていました。
docker-compose.ymlを利用する場合は、明示的に指定が必要です。
2つ目のvenv-...
は.venv
のディレクトリをコンテナの中だけのものにする設定を移植したものになります。
前回の記事ではコンテナIDをボリューム名に含めていましたが、こちらのほうがわかりやすいかと思い、プロジェクトの名前とサービス名をつけるようにしてみました。
Dev Containerで起動した場合はsearch-research_venv-search-research-backend
という名前がついています(最初の部分はDev Containerがつけてるのかな?)
3. dovcontainer.jsonの変更
devcountainer.json
から呼び出すものの準備ができたので、devcontainer.json
を書き換えます。
公式のドキュメントとしてDocker Compose向けのプロパティが紹介されています。
変更したものは次のような形です。
{
"name": "search-research",
"dockerComposeFile": "../docker-compose.yml",
"service": "backend",
"workspaceFolder": "/workspace/search-research",
"postCreateCommand": "/bin/sh ./.devcontainer/postCreateCommand.sh",
"customizations": {
...
- dockerComposeFile : 利用するdocker-compose.ymlのファイルパス
- service:VS Codeが利用するワークスペース用のサービス名
- workspaceFoldeer:VS Codeがコンテナに接続したときに開くフォルダのパス
を指定します。これで、VS Codeでこのプロジェクトを開いた時に、Dev Containerがdocker-compose.ymlを使ってコンテナの起動(ビルドとか)を行ってくれます。
4. アプリの接続文字列の書き換え
こちらはおまけです。
PythonのアプリからElasticsearchに接続するときの文字列として、Dev Container化の前は、http://localhost:9200
と指定をしていました。
Elasticsearch用のサービス(es
)で、ポートフォワードをしていたためです。
アプリ側もコンテナ化したので、Docker Composeが名前の解決をしてくれるので、http://es:9200
という接続文字列で接続ができるようになりました。
ということで、ここまでで、VS Codeでプロジェクトを開くと、2つのコンテナ(backend
とes
)が起動してVS Code上でPythonアプリからEsへの接続ができるようになりました。
追加の変更
参考のプルリクでは、上記まででしたがさらにいくつかの変更をそのあとやっています。
- 起動するサービスの指定(開発だけするときはEsを起動したくない)
devcontainer.json
でrunServices
を使って指定できます(公式ドキュメント)
- GPUをコンテナから利用できるように
devcontainer.json
でfeatures
のnvidia-cuda
を指定し、docker-compose.ymlでnvidia
のドライバーなどを設定することで対応しました。- nvidiaが公開しているcuda対応のコンテナイメージでもよかったのですが、こちらのほうが楽そうだったという理由です。
features
とコンテナのビルド、postCreateCommandの順序などはもうちょっと勉強しないといけない気がしています。
これらの対応はこちらのコミットで対応しています。
GPUの対応は、私個人の環境はこれでいいのですが、複数の人がこのリポジトリを使う場合はどうやって切り替えたりするんだろう?という疑問が残っています。。。 今回はrinna/japanese-clipのモデルを使って、テキストからベクトルを生成する部分の処理のためにGPUを使いたいというモチベーションがあり、コンテナでもGPUを使えるようにしています(CPUだと時間がすごくかかる。。。)。
サービス起動の新たな問題点
runServices
で起動するサービス名を指定したのはよかったのですが、Elasticsearchのサービスを起動して、データ登録や検索の確認を行おうと思った時に、EsのコンテナをVS Codeだけで起動する方法がまだわかっていません。。。
一度コンテナをビルドした後なら、「Remote Explorer」でOther Containerというくくりで表示され、右クリックで起動や停止ができそうなのだけど、新規サービスをdocker-compose.ymlに追加した場合は、自分でターミナルなどでコンテナのビルドをしないといけないかもしれないです。もうちょっと調べてみないとなぁ。
副次的な効果
Docker Compose対応をしたことで、前回の記事での疑問点のうち、「コンテナ名」「VolumeのID」については懸念点がなくなりました。
「コンテナ名」は、docker-compose.ymlのサービス名がコンテナ起動時に名前として利用されるため、Docker Desktopで見た時などの探しにくさはなくなりました。
ただ、「イメージ名」については、いまだに2つできています。「-uid」がつかないものの代わりに、search-research-backend
というイメージが作られています。
ただし、実際に利用されるのは前回の記事に書いたようなvsc-search-research-bf04371c017c8d2f1dd5ad2529841b02e9ea1d1aaa4354c19edf53cef3f0c13b-uid
という名前のイメージです。
「VolumeのID」については、docker-compose.ymlのファイルで自分で名前をつけるようにしたので、コンテナのIDが利用されなくなったという次第です。 代わりに、プロジェクト名である「search-research」という名前を直接記述しているので、変数などで置き換えたほうがいいのかも?という気がしています。
まとめ
ということで、複数のコンテナを利用するプロジェクトでVS Code+Dev Container対応ができそうだということがわかりました。 ついでに、GPU対応もできたのでこれで、やっと他の検索エンジン対応などができる気がしています。 (その前にpre-commitを保存時にチェックする形に変更かなぁ) やりたいことからちょっとずつ外れている気もするけれど、新しいことを調べるのは楽しいですね。
comments powered by Disqus
See Also by Hugo
- VS CodeとDev Containerの導入(まだ途中)
- VS CodeとDev Container(コンテナ名の指定)
- ブログ記述環境としてのDev Container
- pre-commitとvenvとPyCharm(困ったな?)
- TerraformでAzure Cognitive Searchのクラスターを起動