https://a.storyblok.com/f/270183/132704/4682f1d631/e_python-queue-manager_1200x600.png

PythonキューマネージャプロジェクトをDocker化して簡単にデプロイする

最終更新日 April 28, 2021

所要時間:1 分

先月は、PythonとFlaskを使って PythonとFlaskを使ってSMSベースのキュー管理アプリケーションを構築する方法を紹介した。.そのアプリケーションは Nexmo SMS APIを使う基本的な例を示すには良かったのですが、プロトタイプを作ったりローカルで開発したりするのには適していませんでした。この投稿では、このアプリケーションを本番環境に対応させるためのいくつかのステップを説明します。 Docker化にそのままデプロイできるようにする。 Heroku.

その途中で、少し話をしよう:

  • 秘密管理のベストプラクティス

  • コンテナとその有用性

  • プロダクション・トラフィックを処理できるアプリケーション・サーバーでの作業

前提条件

出発点を選ぶ

私の最初の投稿にお付き合いくださった方は 最初の投稿キュー管理アプリの構築に関する私の最初の投稿に従ったのであれば、このアプリを始めるのに必要なのは、上に挙げた前提条件をすべて網羅することだけだ。これから参加する人は、完成したアプリをクローンすればいい:

git clone https://github.com/nexmo-community/sms-queue-notify.git

また Docker化された完成版で始めることもできる:

git clone https://github.com/nexmo-community/docker-queue-manager.git

この記事のセットアップ手順とビルドコマンドの多くはまだ実行する必要があるが、コードに変更を加える必要はない。

どこから始めるにしても、現在プロジェクト・ディレクトリにいることを確認してください:

cd sms-queue-notify

または

cd docker-queue-manager

秘密の管理

以前は、Nexmoのキー、シークレット、そして電話番号を直接、次のページの一番上に置いてもらっていた。 main.py.これは、多くの可動部分を持たないシンプルなアプリのデモには有効でしたが、一般的には、認証情報をコードから分離することをお勧めします。というわけで、最初に修正するのは main.pyに加える最初の修正は、環境変数から直接秘密を読み取ることだ。以下の行を変更してください:

NEXMO_KEY = <Your Nexmo Key>
NEXMO_SECRET = <Your Nexmo Secret>
NEXMO_NUMBER = <Your Nexmo Number>

に:

NEXMO_KEY = os.environ['NEXMO_KEY']
NEXMO_SECRET = os.environ['NEXMO_SECRET']
NEXMO_NUMBER = os.environ['NEXMO_NUMBER']

次に、うっかり秘密をどこかに公開してしまわないように注意したい。まだ持っていない場合は .gitignoreファイルを作成し .envが表示されていることを確認してください。その間に .dockerignoreファイルを作成してください:

.env
.git

これで、機密情報を保存するために .envという名前のファイルを作成する。ファイルの内容は次のようにする:

NEXMO_KEY=<Your Nexmo Key>
NEXMO_SECRET=<Your Nexmo Secret>
NEXMO_NUMBER=<Your Nexmo Number>

ここでは書式が重要であることに注意してほしい。等号の周りにはスペースを入れず、これらの値を main.pyでこれらの値を持っていたときとは異なり、引用符で囲むべきではありません。

今すぐアプリをテストしたい場合は、ターミナルで以下を実行し、以下のファイルに基づいて環境変数を設定する。 .envファイルに基づいて環境変数を設定する:

set -o allexport
source .env
set +o allexport

アプリの変更をテストするためにDockerを使用します。 .envファイルから直接読み込むことができる。

コンフィギュレーションの変更

の一番最後に main.pyの一番最後に

if __name__ == '__main__':
    app.run(debug=True, threaded=True)

この設定は debug=Trueを持つこの設定は、アプリケーションをテストするのに適しています。このデバッグモードは開発のみを目的としており、運用環境では使用しないでください。

もう1つのコンフィギュレーション、 threaded=Trueこれは適切に動作するためにスレッドを必要とします。まもなく学ぶように、リクエストは別のアプリケーションサーバーで処理するので、この設定も削除できます。更新後の main.pyは次のようになります:

if __name__ == '__main__':
    app.run()

Dockerファイルを作成する

プロジェクトを簡単にデプロイできるようにするため、すべてをDockerコンテナにパッケージ化する。コンテナは、正しいオペレーティング・システムや依存関係など、アプリケーションの実行に必要なすべてのリソースを確保するための軽量な方法です。アプリケーションをコンテナとしてバンドルすることで、他にどのようなプロセスや構成、ソフトウェアが既に存在しているかを気にすることなく、様々なプラットフォームでデプロイすることが可能になります。

Dockerは、Dockerfileと呼ばれるものを使ってコンテナイメージを構築します。Dockerfileには、アプリが実行される環境を作成するために必要な手順が一行ずつ記載されています。Dockerfileは、アプリケーションを正しく実行するために必要なセットアップを再現する方法をDockerに指示するレシピです。Dockerfileの各行はレイヤーを作成し、Dockerイメージを再構築する際には、変更のあったレイヤーのみが再構築されます。つまり、最も一般的なセットアップ(OSと必要なパッケージ)から始め、より具体的な要件に向かって作業することをお勧めします。

このアプリケーションでは、まず Dockerfileという名前の新しいファイルを作りましょう:

FROM python:3.6-slim-buster

COPY requirements.txt requirements.txt

RUN pip install -r requirements.txt

これはDockerに、軽量版の DebianバスターOSとPythonバージョン3.6を含むベースイメージから開始するようDockerに指示します。これは標準的なベースイメージで Docker Hubコンテナイメージのパブリックレジストリである

Dockerfileの次の2行は、アプリケーションに必要な依存関係(Flask、Flask-SQLAlchemy、Nexmo SDK)がインストールされていることを確認します。を変更しない限り requirements.txtを変更するか、別のベースイメージを使用しない限り、これらのステップは一度だけ行う必要があります。その後のビルド(コードの変更など)は、すでにあるこれらのレイヤーを使うことができます。

プロダクション・アプリケーション・サーバー

Flaskにはテスト用のビルトインWebサーバーがあり、これは前回の投稿で使用したものです。このサーバーは本番での使用を想定していません。一度に1つのリクエストを処理するのが主な目的であり、本番アプリケーションで想定されるトラフィックを処理するために拡張することはできません。

本番では、専用のウェブ・サーバーが必要です。 Pythonアプリケーションとの通信を処理する別のアプリケーションサーバーを用意したいものです。これらのための2つの一般的な選択肢は NginxGunicorn.Webサーバーを提供してくれるHerokuにデプロイする予定なので、Gunicorn(と同様に スレッド処理のためにスレッドを処理するためのgeventも)。Dockerfileに以下を追加する:

RUN pip install gunicorn gevent

データベースの設定

最初の投稿を思い出してほしい。 最初の投稿を思い出すと、コマンドラインで直接Pythonコマンドを使ってデータベースを作成した。コンテナでアプリをデプロイする場合、手動で環境をセットアップしたくないので、これはあまりうまくいかない。自動化を維持するために、次のような新しい create_db.pyファイルを作成する:

from main import db
db.create_all()

簡単だった!これで Dockerfileを次のように仕上げることができる:

COPY . /app

WORKDIR /app

CMD python create_db.py && gunicorn -k gevent -b 0.0.0.0:$PORT main:app

最後のステップでは、プロジェクト・ディレクトリの内容を、コンテナ内の /appという名前のフォルダにコピーします。最後の行は、コンテナの起動時に実行するコマンドを指示している。まずデータベースを作成し、それが完了したらgunicornサーバーを起動してアプリを実行する。環境変数 $PORT環境変数は、コンテナの実行時にHerokuによって設定されます。

Dockerを使ってローカルでテストする

Dockerファイルが完成したので、ローカルですべてが動作しているかテストするのは簡単だ。まず、Dockerがあなたのコンピュータ上で起動していることを確認する。そしてプロジェクト・ディレクトリで以下を実行し、Dockerイメージをビルドする。 --tagを使って、参照しやすい名前を設定する:

docker build --tag queue_app .

ビルドに成功したら、コンテナを実行できる:

docker run -d -p 5000:5000 --env-file .env -e PORT=5000 queue_app

ファイルから秘密をロードし .envファイルからロードし PORT環境変数を設定していることに注意してください。

コンテナが起動したら、ブラウザを開いて localhost:5000にアクセスし、アプリを見ることができるはずだ!

アプリを完全にテストしたい場合は、まだ1つステップがある。前回の投稿では、アプリケーションがウェブ経由でアクセスできるようにngrokをセットアップしました。アプリにSMSメッセージを送信するテストをしたい場合は、もう一度これを行う必要があります。新しいターミナルウィンドウを開き、以下を実行する:

ngrok http 5000

その後、Nexmoのダッシュボードに移動し、転送先URLを電話番号の設定にコピーしてください。 Inbound Webhook URLフィールドにコピーします: https://<your ngrok ID>.ngrok.io/webhooks/inbound-sms(次のように 前の記事を参照)。

これで、以前と同じようにテキストでアプリケーションとやりとりできるようになるはずだ!ただ、コンテナを停止して再起動すると、データベースが完全にリセットされていることがわかります。

Postgresデータベース

開発版のアプリでは SQLiteデータベースを使った。SQLiteはデータベースをプロジェクトディレクトリにファイルとして作成するので、セットアップは簡単だった。コンテナ・ベースのセットアップでは、コンテナを再起動する必要がある場合、コンテナのファイル・システムは持続しないので、これはうまくいかない。また、共有データソースがないため、複数のコンテナ間でアプリをスケールさせるのが難しくなる。

幸運なことに を使った。を使ってデータベースの仕様をコードから抽象化しているので、SQLiteをHerokuが提供する Postgresデータベースと交換するのは信じられないほど簡単だ。Postgresデータベースはコンテナの外にあるので、コンテナが再起動されても持続し、複数のコンテナからアクセスできる。

HerokuがPostgresデータベースを作成するとき、データベースのURLは環境変数 DATABASE_URL環境変数に格納されます。SQLiteからHerokuのPostgresデータベースに切り替えるためにコードに必要な唯一の変更は、次の行を置き換えることです。 main.py:

db_path = "sqlite:///queue.db"

これで

db_path = os.environ['DATABASE_URL']

という行を更新する必要がある。 Dockerfileの行を更新する必要がある:

RUN pip install gunicorn gevent

と言う:

RUN pip install gunicorn gevent psycopg2-binary

psycopg2パッケージはPython専用のPostgresデータベースアダプタです。

最後のステップは、Heroku上にPostgresデータベースを作成することで、最初にHeroku CLIにログインし、Herokuアプリケーションを作成する必要があります:

heroku login
heroku create <your application name>

次にデータベースを作成し、アプリケーション名を必ず含める:

heroku addons:create heroku-postgresql:hobby-dev -a <your application name>

コンテナをHerokuにデプロイする

アプリケーションとデータベースがHeroku上で初期化され、Docker化されたアプリをデプロイするために必要なステップはあとわずかです。まず、Nexmoの認証情報をHeroku Config Varsとして設定します。これはHerokuダッシュボードの "Settings "から行います:

Config Vars interface in HerokuConfig Vars interface in Heroku

次に、Dockerコンテナを再構築して、最近の変更を確実に取り込むようにする:

docker build --tag queue_app .

次に、Herokuコンテナ・レジストリにログインする必要がある:

heroku container:login

そして最後に、コンテナをHerokuにプッシュしてリリースする:

heroku container:push web -a <your application name>
heroku container:release web -a <your application name>

それだけだ!まあ、ほぼ。Herokuのダッシュボードからアプリケーションを起動し、動作していることを確認したら、Nexmoのダッシュボードに行き、番号の Inbound Webhook URLフィールドを更新してください: https://<your application name>.herokuapp.com/webhooks/inbound-sms.

やったね!コンテナ化の力で、簡単にスケーラブルで複製可能な本番環境のアプリケーションを手に入れることができます。

何か問題が発生したり、質問がある場合は、私たちの コミュニティ・スラック.お読みいただきありがとうございました!

シェア:

https://a.storyblok.com/f/270183/384x384/fdfdc77b6d/zachwalchuk.png
Zach Walchukヴォネージの卒業生

ザックはVonageの元開発者エデュケーターである。