Dockerfile の ENTRYPOINT で環境変数が展開されない件の対応

2023/08/21に公開

もう述べ3回ぐらいハマってるので備忘録として。

結論

ENTRYPOINT に "sh", "-c" を付けて、実行するコマンドを文字列にまとめる。シェルが環境変数を展開するため。

ENV PORT=8000
ENV HOST=0.0.0.0

COPY server.py server.py

ENTRYPOINT ["sh", "-c", "/app/.venv/bin/uvicorn server:app --host $HOST --port $PORT"]

背景

FastAPI で書いた API サーバを docker イメージにして、アプリケーション側の docker compose でポート番号やホストを適宜変更可能にして使いたかったので、以下のように環境変数を設定するようにしたんですが、うまく変数展開がされませんでした。

ENV PORT=8000
ENV HOST=0.0.0.0

COPY server.py server.py

ENTRYPOINT ["/app/.venv/bin/uvicorn", "server:app", "--host", "$HOST", "--port", "$PORT"]

実行時エラー

Error: Invalid value for '--port': '$PORT' is not a valid integer.
Usage: uvicorn [OPTIONS] APP
Try 'uvicorn --help' for help.

公式リファレンスの記載

シェル 形式とは異なり、 exec 形式はコマンドシェルを呼び出しません。つまり、通常のシェルとしての処理が怒らないのを意味します。たとえば、 ENTRYPOINT [ "echo", "$HOME" ] では、 $HOME を変数展開しません。シェルとしての処理を行いたい場合には、 シェル 形式を使うか、 ENTRYPOINT [ "sh", "-c", "echo $HOME" ] のようにシェルを直接実行します。exec 形式を使って直接シェルを実行する場合は、シェル形式の場合と同様に、環境変数の展開をするのはシェルであり、 Docker ではありません。

https://docs.docker.jp/engine/reference/builder.html#entrypoint

Discussion