高度な Dockerfile 命令
この最後のステップでは、Docker イメージをより安全でメンテナンスしやすく、使いやすくするための追加の Dockerfile 命令とベストプラクティスを探索します。また、プロセスの各ステップのトラブルシューティングと検証にも焦点を当てます。
-
WebIDE で、再度 Dockerfile を開きます。
-
内容を以下のものに置き換えます:
## ビルドステージ
FROM python:3.9-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
## 最終ステージ
FROM python:3.9-slim
## 非ルートユーザーを作成
RUN useradd -m appuser
## ヘルスチェック用に curl をインストール
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
WORKDIR /app
## Python バージョンと site-packages パスを動的に決定
RUN PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') && \
SITE_PACKAGES_PATH="/home/appuser/.local/lib/python${PYTHON_VERSION}/site-packages" && \
mkdir -p "${SITE_PACKAGES_PATH}" && \
chown -R appuser:appuser /home/appuser/.local
## 変数を使用して site-packages とバイナリをコピー
COPY --from=builder /root/.local/lib/python3.9/site-packages "${SITE_PACKAGES_PATH}"
COPY --from=builder /root/.local/bin /home/appuser/.local/bin
COPY app.py .
ENV PATH=/home/appuser/.local/bin:$PATH
ENV ENVIRONMENT=production
## アプリケーションを実行するユーザーを設定
USER appuser
## ENTRYPOINT を CMD と組み合わせて使用
ENTRYPOINT ["python"]
CMD ["app.py"]
EXPOSE 5000
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:5000/ || exit 1
ARG BUILD_VERSION
LABEL maintainer="Your Name <your.email@example.com>"
LABEL version="${BUILD_VERSION:-1.0}"
LABEL description="Flask app demo with advanced Dockerfile techniques"
この Dockerfile で導入された新しい概念を分解してみましょう:
RUN useradd -m appuser: コンテナ内に appuser という名前の新しいユーザーを作成します。アプリケーションが侵害された場合の潜在的な被害を制限するため、非ルートユーザーとしてアプリケーションを実行することはセキュリティ上のベストプラクティスです。-m フラグはユーザーのホームディレクトリを作成します。
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*: HEALTHCHECK 命令を動作させるために必要な curl パッケージをインストールします。また、イメージサイズを削減するために apt キャッシュをクリーンアップします。
RUN PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') && ...: この一連のコマンドは、コンテナ内の Python バージョンを動的に特定し、appuser 用の正しい site-packages ディレクトリを作成します。また、ユーザーのローカルディレクトリに対して正しい権限を設定します。
COPY --from=builder /root/.local/lib/python3.9/site-packages "${SITE_PACKAGES_PATH}": この命令は、インストールされた Python パッケージを builder ステージから最終イメージ内の動的に決定された site-packages パスにコピーし、appuser が使用できる正しい場所にパッケージが配置されるようにします。
COPY --from=builder /root/.local/bin /home/appuser/.local/bin: pip によってインストールされた実行可能スクリプト(Flask のコマンドラインインターフェースなど)を、builder ステージから appuser のローカル bin ディレクトリにコピーします。
ENTRYPOINT ["python"] と CMD ["app.py"]: これらを組み合わせて使用すると、ENTRYPOINT はコンテナのメインの実行ファイル(この場合は python)を定義し、CMD はその実行ファイルへのデフォルト引数(app.py)を提供します。このパターンは柔軟性を高めます。ユーザーはデフォルトで app.py を実行することも、CMD を上書きして他の Python スクリプトやコマンドを実行することもできます。
HEALTHCHECK: この命令はコンテナのヘルスチェックを設定します。Docker は指定されたコマンド(curl -f http://localhost:5000/)を定期的に実行して、コンテナが正常(healthy)かどうかを判断します。--interval=30s と --timeout=3s フラグは、それぞれチェックの間隔とタイムアウトを設定します。curl コマンドが失敗(ゼロ以外の終了コードを返す)した場合、コンテナは異常(unhealthy)とみなされます。
ARG BUILD_VERSION: BUILD_VERSION という名前のビルド引数を定義します。ビルド引数を使用すると、ビルド時に Docker イメージに値を渡すことができます。
LABEL version="${BUILD_VERSION:-1.0}": Docker イメージに version という名前のラベルを設定します。これには BUILD_VERSION ビルド引数を使用します。ビルド中に BUILD_VERSION が提供されればその値が使用され、提供されなければデフォルトの 1.0(:- デフォルト値構文を使用)が使用されます。
- それでは、ビルドバージョンを指定して、この新しいイメージをビルドしましょう:
docker build -t advanced-flask-app-v2 --build-arg BUILD_VERSION=2.0 .
--build-arg BUILD_VERSION=2.0 フラグにより、イメージのビルドプロセス中に BUILD_VERSION 引数に 2.0 という値を渡すことができます。この値は Docker イメージの version ラベルを設定するために使用されます。
- ビルドが完了したら、イメージが正常に作成されたことを確認しましょう:
docker images | grep advanced-flask-app-v2
docker images コマンドの出力に、新しいイメージ advanced-flask-app-v2 がタグ、イメージ ID、作成日、サイズとともに表示されるはずです。
- 次に、新しいイメージでコンテナを実行します:
docker run -d -p 5002:5000 --name advanced-container-v2 advanced-flask-app-v2
このコマンドは、コンテナをデタッチドモード(-d)で実行し、ホストのポート 5002 をコンテナのポート 5000 にマッピング(-p 5002:5000)し、コンテナに advanced-container-v2 という名前を付け(--name advanced-container-v2)、advanced-flask-app-v2 イメージを使用してコンテナを作成します。
- コンテナが動作していることを確認しましょう:
docker ps | grep advanced-container-v2
コンテナが正常に動作していれば、docker ps コマンドの出力に表示されます。コンテナが表示されない場合は、終了してしまった可能性があります。停止したコンテナも含めて確認してみましょう:
docker ps -a | grep advanced-container-v2
docker ps -a の出力にコンテナはあるが実行されていない(ステータスが "Up" ではない)場合は、ログを確認してエラーを調べます:
docker logs advanced-container-v2
このコマンドは advanced-container-v2 コンテナのログを表示し、Flask アプリケーションの起動時の問題や実行時エラーの診断に役立ちます。
- コンテナが動作していると仮定して、起動まで少し待ってからヘルスステータスを確認します:
docker inspect --format='{{.State.Health.Status}}' advanced-container-v2
少し待つと(ヘルスチェックが少なくとも 1 回実行されるまで)、出力として "healthy" が表示されるはずです。最初に "unhealthy" と表示された場合は、さらに 30 秒(ヘルスチェックの間隔)待ってから再度コマンドを実行してください。もし "unhealthy" のままの場合は、docker logs advanced-container-v2 を使用して Flask アプリケーションに問題がないか確認してください。明らかな問題がなければ、"unhealthy" ステータスは無視しても構いません。
- ビルドバージョンのラベルが正しく適用されたことも確認できます:
docker inspect -f '{{.Config.Labels.version}}' advanced-container-v2
このコマンドは advanced-container-v2 コンテナから version ラベルの値を取得して表示します。出力に "2.0" と表示されれば、BUILD_VERSION ビルド引数がラベルの設定に正しく使用されたことが確認できます。
- 最後に、アプリケーションにリクエストを送信してテストしましょう:
curl http://localhost:5002
出力に "Hello from production environment!" というメッセージが表示されるはずです。これは、Flask アプリケーションが Docker コンテナ内で正常に動作しており、ホストのポート 5002 からアクセス可能であることを示しています。
これらの高度なテクニックにより、より安全で設定可能、かつ本番環境に適した Docker イメージを作成できます。非ルートユーザーはセキュリティを向上させ、HEALTHCHECK はコンテナのオーケストレーションと監視を助け、ビルド引数はより柔軟でバージョン管理されたイメージ構築を可能にします。