docker-composeのチュートリアルを進めている際に気付いたことです。
「どうも、コマンドラインでdocker-compose up
からコンテナをビルドして実行するときと、Visual Studio Codeの拡張機能であるRemoteを使うのでは、同じファイル使っててもコンテナ構築後の挙動が違うぞ・・・?」
上記の環境で実行しています。
docker-composeのチュートリアルでは、Pythonのwebアプリケーション用フレームワークであるFlaskとNoSQLデータベースのRedisを使った、簡単なwebアプリケーションの作成を行います。ここではFlaskが稼働するコンテナと、Redisが稼働するコンテナをそれぞれ構築します。コンテナを構築したあとで、ブラウザでローカルホストに対しアクセスすると「n回アクセスしたよ」と表示されます。
ええ、表示されるはずなんです。
こんな感じ。なお、表示されている回数はページ更新の際に増加しますので、更新ボタンをポチポチ押せばどんどん数が増えていきます。
チュートリアルでは、ターミナルでdocker compose up
を実行してコンテナを構築します。ところがこのとき、たまたまいつものクセでVS CodeのRemote機能を使ってコンテナをビルドしちゃったんですね。「Reopen in container」っていう、VS Codeユーザーにはいつもの「おなじみの処理」です。「まぁ、別にコマンドでビルドしても、VS Code経由でビルドしても結果は変わらないだろ」・・・そんなふうに考えていた時期が俺にもありました。
ご想像のとおり、実際は違ったわけです。どういうことだってばよ。
docker compose up
で実行すると、Flaskが起動してブラウザでアクセス可能。これが本来想定している挙動。上記がコマンドラインによる実行と、VS Code経由による実行の差です。こんな感じで、VS Codeから実行したらFlaskが起動せず、ブラウザからアクセスができませんでした。
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
上記は、チュートリアルに記載されているDockerfileの内容です。Flaskは、最終行のCMD
で起動するように指定されています。この行が無視されてFlaskが起動されていないか、起動されてもすぐさま終了してしまってアクセスできないのかなー、と思っていました。
当初、tty
の永続化が原因かなーと思っていました。つまり、「起動はしたんだけど、すぐさま終了してしまっている」ケースです。
version: "3.9"
services:
web:
build: .
ports:
- "8000:5000"
redis:
image: "redis:alpine"
上記のとおり、チュートリアルにはのdocker-compose.ymlにはtty
の記載がないため、永続化はされていないのです。そのため、「ああなんだ、tty: true
にすればいいんじゃん」と思ってtty
の記載を追加しました。
version: "3.9"
services:
web:
build: .
ports:
- "8000:5000"
tty: true ← ここ
redis:
image: "redis:buster"
追加してリビルドしてみます・・・が、結果は変わらず。tty
が直接の原因ではありませんでした。となると、「CMD
が無視されている」という線を考えなければなりません。
けど、そんなことってあるの?という半信半疑のまま、Flaskが起動するような方法を探します。最終的にはdocker-compose.ymlにentrypoint
でFlaskを起動するコマンドを仕込んでおく、という手段で解決しました。
version: "3.9"
services:
web:
build: .
ports:
- "8000:5000"
entrypoint: "/bin/sh -c 'flask run'" ← ここ
tty: true
redis:
image: "redis:buster"
docker-compose.yml側でFlaskを起動するため、Dockerfile側のCMD
は削除しておきます。
この修正を行うと、コマンドラインからdocker compose up
で実行しても、VS Codeから実行してもFlaskが起動するようになりました。
正直、VS CodeでCMD
が無視される原因はいまだに不明です(参考にしたとあるwebページには、「VS Code経由でdocker run
すると--entrypoint
オプションを自動的に付与するので、CMD
が無視される」という記載があったのですが、当方の環境では--entrypoint
オプションの自動付与を確認できませんでした)。こういう「原因がわからないけどなんか回避できた」っていうケースが一番困る・・・のですが、とりあえず回避できました。
ベストプラクティスかどうかはかなり怪しいですが、とりあえず困ったらこんな回避方法はいかがでしょうか、というところでひとつよろしくお願いしまーす_(┐「ε:)_