Docker コンテナ起動時に Python スクリプトを実行する方法

DockerBeginner
オンラインで実践に進む

はじめに

Docker は、アプリケーションをコンテナ化するための強力なツールであり、ソフトウェアの開発、デプロイ、および管理を容易にします。このチュートリアルでは、Docker コンテナが起動したときに Python スクリプトを実行する方法を探求します。このアプローチにより、アプリケーションのデプロイを自動化し、開発ワークフローを効率化できます。この実験(Lab)の終わりには、起動時に Python スクリプトを自動的に実行する Docker コンテナを作成できるようになります。

簡単な Python スクリプトの作成

最初のステップとして、Docker コンテナが起動したときに実行される簡単な Python スクリプトを作成します。このスクリプトは、メッセージと現在の日時を出力します。

まず、プロジェクト用の新しいディレクトリを作成しましょう。

mkdir -p ~/project/python-docker
cd ~/project/python-docker

次に、nano テキストエディタを使用して、app.py という名前の簡単な Python スクリプトを作成します。

nano app.py

nano エディタで、次の Python コードを追加します。

import datetime
import time

print("Hello from the Docker container!")
print(f"Current date and time: {datetime.datetime.now()}")

## Keep the container running to demonstrate it's working
print("Container is running...")
while True:
    print("Container still running... Press Ctrl+C to stop.")
    time.sleep(10)

Ctrl+OEnter の順に押してファイルを保存し、Ctrl+X を押して nano を終了します。

このスクリプトは次のことを行います。

  1. ウェルカムメッセージを出力します。
  2. 現在の日時を表示します。
  3. 10 秒ごとにメッセージを表示して、コンテナを実行し続けます。

Python スクリプトが正しく動作することを確認するために、テストしてみましょう。

python3 app.py

次のような出力が表示されるはずです。

Hello from the Docker container!
Current date and time: 2023-10-12 14:30:45.123456
Container is running...
Container still running... Press Ctrl+C to stop.

Ctrl+C を押してスクリプトを停止します。

これで、動作する Python スクリプトができたので、このスクリプトを起動時に実行する Docker コンテナを作成できます。

Dockerfile の作成

これで Python スクリプトの準備ができたので、Docker コンテナの構築方法を定義する Dockerfile を作成しましょう。

Dockerfile は、Docker イメージを構築するために必要なすべてのコマンドを含むテキストファイルです。このイメージには、Python スクリプトと必要なすべての依存関係が含まれます。

同じディレクトリ (~/project/python-docker) に、Dockerfile という名前の新しいファイルを作成します。

nano Dockerfile

Dockerfile に次の内容を追加します。

## Use the official Python image as base
FROM python:3.9-slim

## Set working directory
WORKDIR /app

## Copy the Python script to the container
COPY app.py .

## Command to run when the container starts
CMD ["python", "app.py"]

Ctrl+OEnter の順に押して保存し、Ctrl+X を押して nano を終了します。

Dockerfile の各行が何をするのかを理解しましょう。

  1. FROM python:3.9-slim: これは、使用するベースイメージを指定します。サイズを小さくするために、スリムバリアントの公式 Python 3.9 イメージを使用しています。

  2. WORKDIR /app: これは、コンテナ内の作業ディレクトリを /app に設定します。

  3. COPY app.py .: これは、ホストマシンからコンテナ内の現在の作業ディレクトリ (つまり /app) に Python スクリプトをコピーします。

  4. CMD ["python", "app.py"]: これは、コンテナの起動時に実行するコマンドを指定します。この場合、Python スクリプトが実行されます。

次に、この Dockerfile を使用して Docker イメージを構築しましょう。

docker build -t python-app .

このコマンドは、現在のディレクトリ (.) の Dockerfile から Docker イメージを構築し、python-app という名前でタグ付けします (-t はタグを表します)。

次のような出力が表示されるはずです。

Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM python:3.9-slim
 ---> 1bc6a8a2a52f
Step 2/4 : WORKDIR /app
 ---> Using cache
 ---> 2a3b7a28c9e5
Step 3/4 : COPY app.py .
 ---> Using cache
 ---> 9a0b7a1c8c2d
Step 4/4 : CMD ["python", "app.py"]
 ---> Using cache
 ---> 3b0c7a2d9f1e
Successfully built 3b0c7a2d9f1e
Successfully tagged python-app:latest

出力は異なる場合がありますが、すべてがうまくいけば、「Successfully built」と「Successfully tagged」というメッセージが表示されるはずです。

これで、Python スクリプトを含み、このイメージからコンテナが起動したときにそれを実行する Docker イメージを正常に作成できました。

Docker コンテナの実行

Docker イメージを構築したので、このイメージに基づいてコンテナを実行できます。コンテナは、起動時に自動的に Python スクリプトを実行します。

イメージからコンテナを実行するには、次のコマンドを使用します。

docker run --name python-container python-app

このコマンドは、前のステップで作成した python-app イメージから、python-container という名前の新しいコンテナを起動します。

次のような出力が表示されるはずです。

Hello from the Docker container!
Current date and time: 2023-10-12 15:45:30.123456
Container is running...
Container still running... Press Ctrl+C to stop.
Container still running... Press Ctrl+C to stop.

コンテナは現在実行されており、Python スクリプトを実行しています。スクリプトは、10 秒ごとにメッセージを出力し、無期限に実行されるように設計されています。

ログの表示を停止するには、Ctrl+C を押しますが、コンテナはバックグラウンドでまだ実行されていることに注意してください。

コンテナが実行されていることを確認するには、次のコマンドを使用します。

docker ps

実行中のコンテナのリストに、コンテナが表示されるはずです。

CONTAINER ID   IMAGE        COMMAND           CREATED         STATUS         PORTS     NAMES
1a2b3c4d5e6f   python-app   "python app.py"   1 minute ago    Up 1 minute              python-container

コンテナを停止するには、次のコマンドを使用します。

docker stop python-container

コンテナを再度起動するには、次を使用します。

docker start python-container

実行中のコンテナのログを表示するには、次を使用します。

docker logs python-container

これにより、Python スクリプトの出力が表示されます。Ctrl+C を押してログ表示を終了できます。

完了したらコンテナを削除するには、まず実行中の場合は停止し、次に削除します。

docker stop python-container
docker rm python-container

これで、起動時に Python スクリプトを実行する Docker コンテナを正常に作成し、実行できました。

Docker での Python での環境変数の使用

環境変数は、コードを変更せずにアプリケーションを構成するための優れた方法です。このステップでは、Python スクリプトを変更して環境変数を使用し、これらの変数を提供するように Dockerfile を更新します。

まず、Python スクリプトを更新して環境変数を読み込みましょう。

nano app.py

スクリプトを変更して、環境変数のサポートを含めます。

import datetime
import time
import os

## Get the environment variable with a default value if not set
user_name = os.environ.get('USER_NAME', 'Guest')

print(f"Hello, {user_name}, from the Docker container!")
print(f"Current date and time: {datetime.datetime.now()}")

## Keep the container running to demonstrate it's working
print("Container is running...")
while True:
    print("Container still running... Press Ctrl+C to stop.")
    time.sleep(10)

Ctrl+OEnter の順に押して保存し、Ctrl+X を押して nano を終了します。

次に、環境変数を含めるように Dockerfile を更新しましょう。

nano Dockerfile

Dockerfile を更新して、環境変数を含めます。

## Use the official Python image as base
FROM python:3.9-slim

## Set working directory
WORKDIR /app

## Set environment variable
ENV USER_NAME="Docker User"

## Copy the Python script to the container
COPY app.py .

## Command to run when the container starts
CMD ["python", "app.py"]

保存して nano を終了し、Docker イメージを再構築します。

docker build -t python-app-env .

次に、デフォルトの環境変数を使用してコンテナを実行します。

docker run --name python-env-container python-app-env

出力に「Docker User」という挨拶が表示されるはずです。

Hello, Docker User, from the Docker container!
Current date and time: 2023-10-12 16:30:45.123456
Container is running...

Ctrl+C を押してログの表示を停止します。

コンテナを停止して削除します。

docker stop python-env-container
docker rm python-env-container

コンテナの実行時に環境変数を上書きすることもできます。

docker run --name python-env-container -e USER_NAME="LabEx Student" python-app-env

今回は、挨拶にカスタム名が表示されるはずです。

Hello, LabEx Student, from the Docker container!
Current date and time: 2023-10-12 16:35:15.789012
Container is running...

Ctrl+C を押してログの表示を停止します。

コンテナを停止して削除します。

docker stop python-env-container
docker rm python-env-container

環境変数を使用することは、小さな変更のためにイメージを再構築することなく、コンテナをより構成可能にするために Docker でよく行われる方法です。

Dockerfile での ENTRYPOINT と CMD の使用

Docker では、コンテナの起動時に実行するコマンドを指定するための 2 つの命令があります。CMDENTRYPOINT です。これらは異なる目的と動作を持ち、その違いを理解することはコンテナ管理にとって重要です。

ENTRYPOINT と CMD の理解

  • ENTRYPOINT: コンテナの起動時に実行される実行可能ファイルを定義します。実行時に上書きすることは困難です。
  • CMD: ENTRYPOINT のデフォルト引数を提供するか、ENTRYPOINT が使用されていない場合はコマンド全体を指定できます。実行時に簡単に上書きできます。

2 つの異なる Dockerfile を作成して、その違いを探ってみましょう。

まず、コマンドライン引数を受け入れる新しい Python スクリプトを作成します。

nano greeting.py

次のコードを追加します。

import sys

print("Script started!")

if len(sys.argv) > 1:
    print(f"Arguments provided: {sys.argv[1:]}")
    for arg in sys.argv[1:]:
        print(f"- {arg}")
else:
    print("No arguments provided.")

print("Script finished!")

保存して nano を終了します。

次に、CMD を使用する Dockerfile を作成しましょう。

nano Dockerfile.cmd

次の内容を追加します。

FROM python:3.9-slim

WORKDIR /app

COPY greeting.py .

CMD ["python", "greeting.py", "default", "arguments"]

保存して nano を終了します。

イメージをビルドします。

docker build -t python-cmd -f Dockerfile.cmd .

次に、ENTRYPOINT を使用する別の Dockerfile を作成します。

nano Dockerfile.entrypoint

次の内容を追加します。

FROM python:3.9-slim

WORKDIR /app

COPY greeting.py .

ENTRYPOINT ["python", "greeting.py"]
CMD ["default", "arguments"]

保存して nano を終了します。

イメージをビルドします。

docker build -t python-entrypoint -f Dockerfile.entrypoint .

CMD と ENTRYPOINT のテスト

両方のイメージからコンテナを実行し、その違いを観察してみましょう。

まず、追加の引数なしで CMD イメージを使用してコンテナを実行します。

docker run --name cmd-container python-cmd

出力は次のようになります。

Script started!
Arguments provided: ['default', 'arguments']
- default
- arguments
Script finished!

次に、CMD イメージでコンテナを実行しますが、カスタム引数を指定します。

docker run --name cmd-container-custom python-cmd hello world

出力:

Script started!
No arguments provided.
Script finished!

コマンド全体が hello world に置き換えられたことに注意してください。これらはスクリプトへの引数として渡されません。

次に、追加の引数なしで ENTRYPOINT イメージを使用してコンテナを実行します。

docker run --name entrypoint-container python-entrypoint

出力:

Script started!
Arguments provided: ['default', 'arguments']
- default
- arguments
Script finished!

最後に、ENTRYPOINT イメージでコンテナを実行し、カスタム引数を指定します。

docker run --name entrypoint-container-custom python-entrypoint hello world

出力:

Script started!
Arguments provided: ['hello', 'world']
- hello
- world
Script finished!

今回は、ENTRYPOINT が実行可能ファイルを定義し、docker run に提供された追加の引数がその実行可能ファイルに渡されるため、引数は Python スクリプトに正しく渡されます。

ベストプラクティス

  • 特定のコマンドを常に実行する必要があるコンテナ (Python スクリプトなど) には ENTRYPOINT を使用します。
  • 簡単な上書きが可能なデフォルト引数を提供するには、CMD を使用します。
  • コマンドに ENTRYPOINT を使用し、デフォルト引数に CMD を使用して両方を組み合わせます。

コンテナをクリーンアップします。

docker rm cmd-container cmd-container-custom entrypoint-container entrypoint-container-custom

これで、Docker での CMDENTRYPOINT の違いを学びました。これは、コンテナの起動時に Python スクリプトがどのように実行されるかを制御するために不可欠です。

まとめ

この実験では、Docker コンテナの起動時に Python スクリプトを実行する方法を学びました。達成した内容は次のとおりです。

  1. Docker コンテナ内で実行されるシンプルな Python スクリプトを作成しました。
  2. Dockerfile を使用して Docker イメージをビルドしました。
  3. Python スクリプトを自動的に実行する Docker コンテナを実行しました。
  4. 環境変数を使用して、Docker で Python アプリケーションを構成しました。
  5. Dockerfile における CMD と ENTRYPOINT の違いを理解しました。

これらのスキルは、Python アプリケーションをコンテナ化し、そのデプロイを自動化するための基本です。これで、次のことができるようになりました。

  • Python アプリケーションとそのすべての依存関係をパッケージ化する
  • 環境変数を使用してアプリケーションを構成する
  • Docker コンテナ内でアプリケーションがどのように起動するかを制御する
  • 特定のユースケースに適した起動メカニズム (CMD または ENTRYPOINT) を選択する

この知識があれば、起動時に Python スクリプトを自動的に実行する、より複雑な Docker アプリケーションを構築し、デプロイプロセスをより効率的かつ信頼性の高いものにすることができます。