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

ENTRYPOINTbash docker-entrypoint.sh を実行するようにして、
CMDpython 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 で実行していることになった。ということでしょうか?

まとめ

起動前に何かしておきたいケースってありますよね。例えばどこからかファイルをダウンロードしておく。とか。そんなときに使う感じです!