Docker コンテナ起動時に前処理を実行したい (original) (raw)
例えば、DB や Redis など特定のリソースが起動するまで待ってからメインのアプリケーションを起動したいときなどです。
前提
前提として、Dockerfile と docker-compose.yml の定義をします。
ここでは、簡単な Dockerfile を用意します。
Dockerfile & docker-compose.yml
FROM python:3.11.10-slim-bullseye
RUN apt update -y
COPY ./app ./app
ENTRYPOINT ["python", "app/main.py"]
services: app: build: context: . container_name: app
この程度の簡単な Docker ファイルがあったとします。
起動コマンドである python app/main.py
が実行される前に何か処理を入れたいです。
一応 main.py
は以下のような適当なものになっています。
def main(): print("START : main()")
if name == 'main': main()
entrypoint のスクリプトを用意する
ここでは、10秒間のウェイト処理をしようと思います。
[docker-entrypoint.sh]
このブロックに本当にやりたい処理を入れる
for i in {1..10}; do echo "Waiting... count: $i" sleep 1 done
exec $@
Dockerfile を変更する
FROM python:3.11.10-slim-bullseye
RUN apt update -y
COPY ./app ./app
- COPY ./docker-entrypoint.sh ./docker-entrypoint.sh
- ENTRYPOINT ["python", "app/main.py"]
- ENTRYPOINT ["bash", "docker-entrypoint.sh"]
- CMD ["python", "app/main.py"]
ENTRYPOINT
で bash docker-entrypoint.sh
を実行するようにして、CMD
で python app/main.py
を渡すようにします。
これで、10秒のカウントの後、main()
の print 文が出力されれば成功です。
試す
$ docker compose up [+] Building 2.8s (11/11) FINISHED docker:default ~省略~ [+] Running 2/2 ✔ Network my_app_default Created 0.4s ✔ Container app Created 0.2s Attaching to app app | Waiting... count: 1 app | Waiting... count: 2 app | Waiting... count: 3 app | Waiting... count: 4 app | Waiting... count: 5 app | Waiting... count: 6 app | Waiting... count: 7 app | Waiting... count: 8 app | Waiting... count: 9 app | Waiting... count: 10 app | START : main() app exited with code 0
成功!
exec $@ が重要
exec
は、Bash や他のシェルスクリプトで使われるコマンドで、現在のシェルプロセスを指定したコマンドに置き換える ために使用されます。通常のコマンド実行とは異なり、exec で実行すると、元のシェルプロセスが終了し、新しいプロセスがその場で置き換わる点が特徴 です。
$@
は、Bash スクリプトで使われる特殊な変数で、**スクリプトに渡された全ての引数** を表すものです。複数の引数を処理する際に便利な機能を提供してくれます。
ということで、
ENTRYPOINT
として docker-entrypoint.sh
を実行していたものが、CMD
で渡された python app/main.py
で実行していることになった。ということでしょうか?
まとめ
起動前に何かしておきたいケースってありますよね。例えばどこからかファイルをダウンロードしておく。とか。そんなときに使う感じです!