Python での作業は、多くの場合、私にとって素晴らしい経験でしたが、複雑な開発環境を管理することは、プロジェクトがスケールアップするにつれて、いくつかの課題に直面することがよくありました。 ほんの数例を挙げると、私が遭遇した Python の 3 つの主要な問題を以下に示します。 1. 環境変数に依存するアプリケーションでは、アプリケーションを実行する前にこれらの変数を設定する必要がある場合があります。 2. 異なるサービス間の通信に認証証明書を使用するアプリケーションでは、アプリケーションを実行する前にこれらの証明書をローカルで生成する必要がある場合があります。 3. 同じプロジェクト内の異なるマイクロサービス間で、依存関係のバージョン管理の競合が発生する可能性があります。 相互に依存する複数のマイクロサービスを操作する場合、事態は特に厄介になる可能性があります。率直に言って、開発者として、立ち上げて実行するためだけにこのオーバーヘッドをすべて管理したくありません。これは、新しいプロジェクトに参加したばかりの場合に特に当てはまります。 Python アプリを開発する際に使用されている一般的なソリューションの 1 つは、 を使用することです。これは、Python のインストールと必要なパッケージを含む分離された環境です。ただし、仮想環境は Python インタープリター レベルでの分離しか提供しないため、複数の仮想環境およびその他の環境関連の構成を管理することは、依然として時間と手間がかかる可能性があります。これは、環境変数やポート割り当てなど、その他の環境関連の設定が、すべてのプロジェクト コンポーネントで引き続きグローバルに共有されることを意味します。 Python 仮想環境 この記事で説明するソリューションは、コンテナー化の使用です。コンテナー化とは、アプリケーションとその依存関係を自己完結型のユニットにパッケージ化する方法であり、簡単にデプロイして任意のプラットフォームで実行できます。 は、コンテナー化されたアプリケーションを開発、展開、および実行するための一般的なプラットフォームです は、単一の YAML ファイル (通常は )。 などの代替ソリューションもありますが、簡単にするために、この例では Docker と Docker Compose の使用に固執します。 Docker 。Docker Compose docker-compose.yml minikube Docker と Docker Compose を使用して、コンテナー化された開発環境をセットアップして使用する方法を示します。また、コンテナー化された開発環境を使用する際のいくつかの課題と、効果的な開発環境のための次の主要な要件に適合するように Docker と Docker Compose を構成することによってそれらを克服する方法についても説明します。 1. 実行 - ターゲット実稼働環境での実行をシミュレートするエンド ツー エンドのシナリオを実行します。 2. デプロイ - コンテナ化されていないアプリケーション ランタイム スタックと同様に、コードを変更して迅速に再デプロイします。 3. デバッグ - コンテナー化されていないアプリケーションのランタイム スタックと同様に、ブレークポイントを設定し、デバッガーを使用してコードをステップ実行し、エラーを特定して修正します。 プロジェクトのセットアップ これを例で説明するために、軽量の Python Web フレームワークである を使用する単純な Python アプリケーションを定義して、著者とその投稿に関する情報をクエリするための RESTful API を作成します。 API には単一のエンドポイントがあり、 パス パラメーターとして ID を指定することにより、特定の作成者に関する情報を取得するために使用できます。次に、アプリケーションは モジュールを使用して、別の投稿サービスに HTTP 要求を行います。このサービスは、その作成者による投稿のリストを提供することが期待されています。コードを簡潔にするために、すべてのデータは ライブラリを使用してオンザフライでランダムに生成されます。 Flask /authors/{author_id} requests Faker 最初に、プロジェクトの空のディレクトリを初期化して開きます。次に、2 つのサブディレクトリを作成します。 、そして2番目 .これらの各ディレクトリ内に、次の 3 つのファイルを作成します。 authors_service posts_service 1. : アプリを定義し、ルートを設定し、それらのルートに対してリクエストが行われたときに呼び出される関数を指定する、Flask アプリのメイン エントリ ポイントです。 app.py 2. : アプリケーションの実行に必要な Python パッケージを指定するプレーン テキスト ファイル。 requirements.txt 3. : Docker イメージをビルドするための指示を含むテキスト ファイル。前述のように、コード、ランタイム、ライブラリ、環境変数、そしてほとんど何でも。 Dockerfile それぞれに ファイルを作成したら、目的のロジックを使用して Flask マイクロサービスを実装します。 app.py のために 、 ファイルは次のようになります。 authors_service app.py app = flask.Flask(__name__) author = { } response = requests.get( ) app.run( ) import os import flask import requests from faker import Faker @app.route( "/authors/<string:author_id>" , methods=[ "GET" ] ) def get_author_by_id ( author_id: str ): "id" : author_id, "name" : Faker().name(), "email" : Faker().email(), "posts" : _get_authors_posts(author_id) return flask.jsonify(author) def _get_authors_posts ( author_id: str ): f' {os.environ[ "POSTS_SERVICE_URL" ]} / {author_id} ' return response.json() if __name__ == "__main__" : host=os.environ[ 'SERVICE_HOST' ], port= int (os.environ[ 'SERVICE_PORT' ]) このコードは、Flask アプリをセットアップし、エンドポイントへの GET リクエストを処理するルートを定義します .このエンドポイントにアクセスすると、指定された ID を持つ作成者のモック データが生成され、別の投稿サービスからその作成者の投稿のリストが取得されます。次に、Flask アプリを実行し、対応する環境変数で指定されたホスト名とポートをリッスンします。 上記のロジックは、 、 と パッケージ。これを説明するために、著者サービスの ファイルは次のとおりです。 /authors/{author_id} flask requests Faker requirements.txt flask == 2 . 2 . 2 requests == 2 . 28 . 1 Faker == 15 . 3 . 4 このガイド全体で参照されている依存関係のいずれにも、特定のパッケージのバージョン管理要件はないことに注意してください。使用したバージョンは、執筆時点で入手可能な最新のものです。 のために 、 次のようになります: posts_service app.py app = flask.Flask(__name__) posts = [ { } ] app.run( ) import os import uuid from random import randint import flask from faker import Faker @app.route( '/posts/<string:author_id>' , methods=[ 'GET' ] ) def get_posts_by_author_id ( author_id: str ): "id:" : str (uuid.uuid4()), "author_id" : author_id, "title" : Faker().sentence(), "body" : Faker().paragraph() for _ in range (randint( 1 , 5 )) return flask.jsonify(posts) if __name__ == '__main__' : host=os.environ[ 'SERVICE_HOST' ], port= int (os.environ[ 'SERVICE_PORT' ]) このコードでは、クライアント (つまり ) GET リクエストをルートに送信します 、 関数 指定された パラメータとして。この関数は、作成者が Faker ライブラリを使用して書いた 1 ~ 5 件の投稿のモック データを生成し、投稿のリストを JSON レスポンスとしてクライアントに返します。 authors_service /posts/{author_id} get_posts_by_author_id author_id また、投稿サービスにフラスコと Faker パッケージを追加する必要があります。 ファイルは次のとおりです。 requirements.txt flask == 2 . 2 . 2 Faker == 15 . 3 . 4 これらのサービスをコンテナー化する前に、そもそもなぜサービスをパッケージ化して互いに分離して実行したいのか、その一例を考えてみましょう。 どちらのサービスも環境変数を使用します と Flask サーバーが起動されるソケットを定義します。その間 は問題ではありません (複数のサービスが同じホストでリッスンできます)。 問題を引き起こす可能性があります。すべての依存関係をローカルの Python 環境にインストールし、両方のサービスを実行すると、最初に開始するサービスが指定されたポートを使用し、2 番目のサービスが同じポートを使用できないためにクラッシュすることになります。簡単な解決策の 1 つは、別の環境変数を使用することです (たとえば、 と ) 代わりは。ただし、ソース コードを変更して環境の制約に適応させることは、スケールアップ時に複雑になる可能性があります。 SERVICE_HOST SERVICE_PORT SERVICE_HOST SERVICE_PORT AUTHORS_SERVICE_PORT POSTS_SERVICE_PORT コンテナ このような問題を回避するのに役立ちます。この場合、設定できます 環境変数をサービスごとに異なる値に設定すると、各サービスは他のサービスからの干渉を受けることなく独自のポートを使用できるようになります。 サービスをコンテナー化するために、次の名前の新しいファイルを作成します。 各サービスのディレクトリにあります。このファイルの内容 (両方のサービス) は次のとおりです。 化は、その逆ではなく、アプリケーションに合わせて環境を設定することで、 SERVICE_PORT Dockerfile WORKDIR /app COPY . /app/ FROM python: 3.8 RUN mkdir /app COPY requi rements.txt /app/ RUN pip install -r requi rements.txt CMD [ "python" , "app.py" ] この Python 3.8 の からビルドし、コンテナー内にアプリケーションのディレクトリを設定します。次に、 ホスト マシンからコンテナにファイルを転送し、そのファイルにリストされている依存関係をインストールします。最後に、残りのアプリケーション コードをホスト マシンからコンテナーにコピーし、コンテナーの起動時にメイン アプリケーション スクリプトを実行します。 Dockerfile 親イメージ requirements.txt 次に、次の名前のファイルを作成します。 ルート プロジェクト ディレクトリにあります。上で簡単に説明したように、このファイルは、複数コンテナーの Docker アプリケーションを定義して実行するために使用されます。の中に ファイルを使用して、アプリケーションを構成するサービスを定義し、それらの間の依存関係を指定し、それらを構築および実行する方法を構成できます。この場合、次のようになります。 docker-compose.yml docker-compose.yml --- # Specify the version of the Docker Compose file format version: '3.9' services: # Define the authors_service service authors_service: # This service relies on, and is therefor dependent on, the below `posts_service` service depends_on: - posts_service # Specify the path to the Dockerfile for this service build: context: ./authors_service dockerfile: Dockerfile # Define environment variables for this service environment: - SERVICE_HOST=0.0.0.0 - PYTHONPATH=/app - SERVICE_PORT=5000 - POSTS_SERVICE_URL=http://posts_service:6000/posts # Map port 5000 on the host machine to port 5000 on the container ports: - "5000:5000" # Mount the authors_service source code directory on the host to the working directory on the container volumes: - ./authors_service:/app # Define the posts_service service posts_service: # Specify the path to the Dockerfile for this service build: context: ./posts_service dockerfile: Dockerfile # Define environment variables for this service environment: - PYTHONPATH=/app - SERVICE_HOST=0.0.0.0 - SERVICE_PORT=6000 # Mount the posts_service source code directory on the host to the working directory on the container volumes: - ./posts_service:/app アプリケーションの実行 コンテナーは、 指図。これを初めて実行すると、docker イメージが自動的にビルドされます。 docker-compose up これは、「実行」の最初のコア要件を満たします。 再デプロイ中 に注意してください ファイルのソース コード ディレクトリを共有するために、ボリューム マウントが使用されます。 と ホスト マシンとコンテナ間のサービス。これにより、ホスト マシン上でコードを編集し、その変更をコンテナーに自動的に反映させることができます (逆も同様です)。 docker-compose.yml authors_service posts_service たとえば、次の行は ホスト マシン上のディレクトリを のディレクトリ 容器: ./authors_service /app authors_service volumes: - . /authors_service:/ app ホスト マシンで行われた変更はコンテナーですぐに利用でき、コンテナーで行われた変更はすぐにホスト マシンのソース コード ディレクトリに永続化されます。これにより、イメージを再構築 に関連するコンテナを再起動することで、変更をすばやく再展開できるようになり、「展開」の 2 番目のコア要件を効果的に満たすことができます。 せず デバッグ これは、もう少し関与するところです。 Python のデバッガーは、インタープリターが提供するデバッグ ツールを使用して、プログラムの実行を一時停止し、特定の時点での状態を検査します。これには、トレース機能の設定が含まれます コードの各行でブレークポイントをチェックし、コール スタックや変数インスペクションなどの機能を使用します。コンテナー内で実行されている Python インタープリターをデバッグすると、ホスト コンピューターで実行されている Python インタープリターをデバッグする場合と比較して、複雑さが増す可能性があります。これは、コンテナ環境がホスト マシンから分離されているためです。 sys.settrace() これを克服するために、次の 2 つの一般的なトラックのいずれかを取ることができます: コードはコンテナー自体からデバッグするか、リモート デバッグ サーバーを使用してデバッグすることができます。 まず、 を選択したエディターとして使用して、これを実行する方法を示します。その後、 で同様に動作させる方法を説明します。 VSCode JetBrains PyCharm コンテナ自体からコードをデバッグする VSCode を使用して実行中の Docker コンテナー内からコードを開発およびデバッグするには、次のことを行います。 1. VSCode の がインストールされ、有効になっていることを確認します。 Docker 拡張機能 2. 接続先のコンテナーが稼働中であることを確認します。 3. 左側のサイドバーにある Docker アイコンをクリックして、Docker 拡張機能のエクスプローラー ビューを開きます。 4. エクスプローラー ビューで、[実行中のコンテナー] セクションを展開し、アタッチするコンテナーを選択します。 5. コンテナーを右クリックし、コンテキスト メニューから [Attach Visual Studio Code] オプションを選択します。 これにより、選択したコンテナーに Visual Studio Code がアタッチされ、コンテナー内に新しい VSCode ウィンドウが開きます。この新しいウィンドウで、ローカル環境で通常行うように、コードを記述、実行、およびデバッグできます。 コンテナーを再起動するたびに などの VSCode 拡張機能をインストールする必要がないようにするために、VSCode 拡張機能を格納するコンテナー内にボリュームをマウントできます。このようにすると、コンテナが再起動されても、拡張機能はホスト マシンに保存されているため、引き続き使用できます。このデモ プロジェクトで docker compose を使用してこれを行うには、 ファイルは次のように変更できます。 Python docker-compose.yml --- # Specify the version of the Docker Compose file format version: '3.9' services: # Define the authors_service service authors_service: ... # Mount the authors_service source code directory on the host to the working directory on the container volumes: - ./authors_service:/app # Mount the vscode extension directory on the host to the vscode extension directory on the container - /path/to/host/extensions:/root/.vscode/extensions # Define the posts_service service posts_service: ... VSCode 拡張機能は通常、次の場所にあります。 Linux および macOS で、または Windows で。 ~/.vscode/extensions %USERPROFILE%\.vscode\extensions リモート Python デバッグ サーバーの使用 上記のデバッグ方法は、スタンドアロン スクリプト、またはテストの作成、実行、およびデバッグに適しています。ただし、異なるコンテナーで実行されている複数のサービスを含む論理フローのデバッグはより複雑です。 コンテナーが開始されると、コンテナーに含まれるサービスが通常すぐに起動されます。この場合、両方のサービスの Flask サーバーは、VSCode がアタッチされるまでに既に実行されているため、[実行してデバッグ] をクリックして Flask サーバーの を起動することは、同じサービスの複数のインスタンスが実行されることになるため、実用的ではありません。これは通常、信頼できるデバッグ フローではありません。 これにより、オプション 2 に進みます。リモート Python デバッグ サーバーを使用します。リモート Python デバッグ サーバーは、リモート ホストで実行されている Python インタープリターであり、デバッガーからの接続を受け入れるように構成されています。これにより、ローカルで実行されているデバッガーを使用して、リモート環境で実行されている Python プロセスを調べて制御できます。 別のインスタンス 「リモート」という用語は、必ずしも物理的に離れたマシンや、ホスト マシンで実行されている Docker コンテナーなどのローカルだが隔離された環境を指すとは限らないことに注意することが重要です。 Python リモート デバッグ サーバーは、デバッガーと同じ環境内で実行されている Python プロセスのデバッグにも役立ちます。このコンテキストでは、デバッグしているプロセスと同じコンテナー内で実行されているリモート デバッグ サーバーを使用します。この方法と、最初に説明したデバッグのオプションとの主な違いは、コードを実行してデバッグするたびに新しいプロセスを作成するのではなく、既存のプロセスにアタッチすることです。 開始するための最初のステップは、 パッケージを 両方のサービスのファイル。 debugpy は、Python プログラムをローカルまたはリモートでデバッグするために使用できる高レベルのオープンソース Python デバッガーです。両方に次の行を追加します ファイル: debugpy requirements.txt requirements.txt debugpy == 1 . 6 . 4 次に、各サービスの Docker イメージに debugpy をインストールするために、イメージを再構築する必要があります。私は実行します これを行うコマンド。じゃあ走るよ コンテナを起動します。 docker-compose build docker-compose up 次に、上記と同様に、デバッグするプロセスを含む実行中のコンテナーに VSCode をアタッチします。 実行中の Python アプリケーションにデバッガーをアタッチするには、コードのデバッグを開始する位置に次のスニペットを追加する必要があります。 import debugpy; debugpy.listen( 5678 ) このスニペットは debugpy モジュールをインポートし、 関数は、指定されたポート番号 (この場合は 5678) でデバッガーからの接続をリッスンする debugpy サーバーを開始します。 listen デバッグしたい場合 、上記のスニペットを 内の関数宣言 ファイル - 次のように: authors_service get_author_by_id app.py app = flask.Flask(__name__) ... import os import flask import requests from faker import Faker import debugpy; debugpy.listen( 5678 ) @app.route( "/authors/<string:author_id>" , methods=[ "GET" ] ) def get_author_by_id ( author_id: str ): これにより、アプリケーションの起動時に debugpy サーバーが起動されます。 スクリプトが実行されます。 app.py 次のステップは、アプリケーションをデバッグするための VSCode 起動構成を作成することです。コンテナーをアタッチした (および VSCode ウィンドウを実行している) サービスのルート ディレクトリに、次の名前のフォルダーを作成します。 .次に、このフォルダー内に、次の名前のファイルを作成します。 の内容は次のとおりです。 .vscode launch.json { } } ] } { "version" : "0.2.0" , "configurations" : [ "name" : "Python: Remote Attach" , "type" : "python" , "request" : "attach" , "connect" : { "host" : "localhost" , "port" : 5678 この構成は、ローカル マシン (つまり、現在のコンテナー) で実行されている Python デバッガーに VSCode をポート 5678 で接続する必要があることを指定します。 上記の関数。 debugpy.listen 次に、すべての変更を保存します。 Docker 拡張機能のエクスプローラー ビューで、現在接続しているコンテナーを右クリックし、コンテキスト メニューから [コンテナーの再起動] を選択します (ローカルの VSCode インスタンスで行います)。コンテナーを再起動すると、コンテナー内の VSCode ウィンドウに、ウィンドウをリロードするかどうかを尋ねるダイアログが表示されます。正解は「はい」です。 あとは実際に動かしてみるだけです!デバッグを開始するには、コンテナーで実行されている VSCode インスタンス内で、デバッグするスクリプトを開き、F5 キーを押してデバッガーを開始します。デバッガーはスクリプトにアタッチし、次の行で実行を一時停止します。 関数が呼び出されます。 [デバッグ] タブのデバッガー コントロールを使用して、コードをステップ実行し、ブレークポイントを設定し、変数を検査できるようになりました。 debugpy.listen これにより、上記の「デバッグ」要件が満たされます。 Jetbrains Pycharm IDE を使用したリモート開発とデバッグ によると、PyCharm を使用する場合、これを行うには 2 つの方法があります。 機能を使用して Docker イメージからインタープリターを取得するか、 を使用することができます。これら 2 つのオプションは相互に排他的ではないことに注意してください。個人的には、通常、開発には主にリモート インタープリター機能に依存しており、必要に応じてリモート デバッグ サーバー構成を使用しています。 公式ドキュメント リモート インタープリター リモート デバッグ サーバー構成 リモート通訳者の設定 PyCharm でリモート インタープリターをセットアップするには、次のようにします。 1. IDE ウィンドウの右下隅にあるインタープリタータブのポップアップメニューをクリックします。 2. をクリックし、ポップアップ メニューから を選択します。 Add new interpreter On docker compose... 3. 次のポップアップ ウィンドウで、関連する docker compose ファイルを選択し、ドロップダウンから関連するサービスを選択します。 PyCharm は、docker イメージに接続して、利用可能な Python インタープリターを取得しようとします。 4. 次のウィンドウで、使用する Python インタープリターを選択します (例: )。インタープリターを選択したら、[作成] をクリックします。 /usr/local/bin/python その後、PyCharm は新しいインタープリターにインデックスを付けます。その後、通常どおりコードを実行またはデバッグできます。PyCharm は、必要なときにいつでもバックグラウンドで docker compose を調整します。 リモート デバッグ サーバー構成のセットアップ リモート デバッグ サーバー構成をセットアップするには、まず関連する 2 つの依存関係を追加する必要があります。 ファイル: 、および 。これらは、上で示した debugpy パッケージと機能が似ていますが、その名前が示すように、pydevd_pycharm は PyCharm でのデバッグ用に特別に設計されています。このデモ プロジェクトのコンテキストでは、次の 2 行を両方に追加します。 ファイル: requirements.txt pydevd pydevd_pycharm requirements.txt pydevd ~= 2 . 9 . 1 pydevd -pycharm== 223 . 8214 . 17 これが完了し、Docker イメージが再構築されたら、次のコード スニペットをコードに埋め込んで、デバッグを開始したいコード内のポイントで pydevd_pycharm デバッグ サーバーを起動します。 import pydevd_pycharm; pydevd_pycharm.settrace( 'host.docker.internal' , 5678 ) debugpy とは異なり、ここでは "host.docker.internal" という値でホスト名アドレスを指定したことに注意してください。これは、Docker コンテナー内からホスト マシンの内部 IP アドレスに解決される DNS 名です。これは、コンテナーで PyCharm を実行していないためです。代わりに リッスンするようにデバッグ サーバーを効果的に構成しています。 、ホスト マシンのポート 5678 で このオプションは debugpy にも存在しますが、その場合 で VSCode のインスタンスを実行していたので、ホスト名アドレスのデフォルトを "localhost" にするように単純化しました (つまり、コンテナー自体ではなく、コンテナー自体のループバック インターフェイス)。ホスト マシン)。 はコンテナー自体 最後のステップは、PyCharm がリモート デバッグ サーバーに接続するために使用できる実行構成をセットアップすることです。 これを行うには、次のことを行います。 1. メイン メニューから [ ] > [ ] を選択して、[Run/Debug Configuration] ダイアログを開きます。 2. ダイアログの左上隅にある [ ] ボタンをクリックし、ドロップダウン メニューから [ ] を選択します。 3. [ フィールドに、実行構成の名前を入力します。 4. [ フィールドで、デバッグするスクリプトへのパスを指定します。 5. [ フィールドに、デバッガー サーバーが実行されるホスト マシンの IP アドレスを入力します。この例では、「localhost」です。 Run Edit Configurations + Python リモート デバッグ 名前] スクリプト パス] ホスト] 6. [ フィールドに、デバッガー サーバーがリッスンするポート番号を入力します。この例では、5678 です。 ポート] 7. [ セクションで、ホスト マシン上のパスをコンテナー内のパスにマップする方法を指定できます。これは、ホストからコンテナにマウントされたコードをデバッグする場合に便利です。両方の環境でパスが同じではない可能性があるためです。この例では、マップしたいと思います ホスト マシン上で、 authors_service をデバッグするためのコンテナー内、または に posts_service をデバッグするためのコンテナー (これらは 2 つの別個の実行構成である必要があります)。 パス マッピング] path/to/project/on/host/authors_service /app path/to/project/on/host/posts_service /app 8. [ ] をクリックして実行構成を保存します。 デバッグを開始するには、[ ] ドロップダウン メニューから上記の実行構成を選択し、[ ] ボタンをクリックしてから、関連するコンテナーを 指図。 PyCharm デバッガーはスクリプトにアタッチし、次の行で実行を一時停止します。 関数が呼び出され、これらのバグを粉砕し始めることができます。 OK 実行 デバッグ docker-compose up pydevd_pycharm.settrace 要約すれば このガイドでは、コンテナー化された Python 開発環境とは何か、なぜそれらが役立つのか、それらを使用して Python コードを作成、デプロイ、およびデバッグする方法について、一般的かつ実用的な概要を説明しました。これは、これらの環境で作業するための包括的なガイドではないことに注意してください。これは、拡張するための出発点にすぎません。その目的に役立ついくつかのリンクを次に示します。 1. redhatによるコンテナ化の概要 3. Dockerの公式ドキュメント 4. リモートデバッグ用の公式 JetBrains PyCharm ドキュメント 5. 開発コンテナで Python を開発するための公式 VSCode ドキュメント このガイドがお役に立てば幸いです。お読みいただきありがとうございます。