MongoDBとDockerでFlaskを設定する方法
著者は、 Write for DOnations プログラムの一環として、 InternetArchiveを選択して寄付を受け取りました。
序章
Webアプリケーションの開発は、さまざまなテクノロジーを構築および保守する場合、複雑で時間がかかる可能性があります。 アプリケーションの複雑さと生産までの時間を短縮するように設計された軽量オプションを検討すると、より柔軟でスケーラブルなソリューションが得られます。 Python 上に構築されたマイクロWebフレームワークとして、 Flask は、プロジェクトに統合できる拡張機能を通じて開発者がアプリケーションを拡張するための拡張可能な方法を提供します。 開発者の技術スタックのスケーラビリティを継続するために、 MongoDB はNoSQLデータベースであり、頻繁な変更に対応できるように拡張および動作するように設計されています。 開発者はDockerを使用して、アプリケーションのパッケージ化とデプロイのプロセスを簡素化できます。
Docker Compose は、アプリケーションサービス、ネットワークボリューム、バインドマウントなどのインフラストラクチャを単一のファイルで定義できるようにすることで、開発環境をさらに簡素化しました。 Docker Composeを使用すると、複数のdocker container run
コマンドを実行するよりも使いやすくなります。 これにより、すべてのサービスを1つの作成ファイルで定義でき、1つのコマンドで、構成からすべてのサービスを作成して開始できます。 これにより、コンテナインフラストラクチャ全体でバージョン管理が確実に行われます。 Docker Composeはプロジェクト名を使用して環境を相互に分離します。これにより、単一のホストで複数の環境を実行できます。
このチュートリアルでは、Docker container 内でFlask、Nginx、およびMongoDBを使用してTo Do Webアプリケーションをビルド、パッケージ化、および実行します。 スタック構成全体をdocker-compose.yml
ファイルで定義し、Python、MongoDB、およびNginxの構成ファイルも定義します。 FlaskはHTTPリクエストを処理するためにWebサーバーを必要とするため、アプリケーションを処理するためにPythonWSGIHTTPサーバーであるGunicornも使用します。 Nginxは、処理のためにリクエストをGunicornに転送するリバースプロキシサーバーとして機能します。
前提条件
このチュートリアルに従うには、次のものが必要です。
- 初期サーバー設定チュートリアルの手順に従って構成された
sudo
権限を持つ非rootユーザー。 - Dockerのインストールと使用方法のステップ1とステップ2の手順でDockerをインストールしました。
- Docker Composeのインストール方法のステップ1の手順に従って、DockerComposeをインストールします。
ステップ1—DockerComposeでスタック構成を作成する
Dockerでアプリケーションを構築すると、DockerComposeで行った構成の変更に応じてインフラストラクチャを簡単にバージョン管理できます。 インフラストラクチャは、単一のファイルで定義し、単一のコマンドで構築できます。 このステップでは、Flaskアプリケーションを実行するためのdocker-compose.yml
ファイルを設定します。
docker-compose.yml
ファイルを使用すると、アプリケーションインフラストラクチャを個別のサービスとして定義できます。 サービスは相互に接続でき、永続ストレージ用にボリュームを接続できます。 ボリュームは、Docker(Linuxでは/var/lib/docker/volumes/
)によって管理されるホストファイルシステムの一部に保存されます。
ボリューム内のデータはエクスポートしたり、他のアプリケーションと共有したりできるため、ボリュームはDockerでデータを永続化するための最良の方法です。 Dockerでのデータ共有の詳細については、Dockerコンテナとホスト間でデータを共有する方法を参照してください。
開始するには、サーバーのホームディレクトリにアプリケーションのディレクトリを作成します。
mkdir flaskapp
新しく作成したディレクトリに移動します。
cd flaskapp
次に、docker-compose.yml
ファイルを作成します。
nano docker-compose.yml
docker-compose.yml
ファイルは、DockerComposeファイルのバージョンを識別するバージョン番号で始まります。 DockerComposeファイルバージョン3
は、このセットアップの前提条件であるDockerEngineバージョン1.13.0+
を対象としています。 また、次の手順で定義するservices
タグを追加します。
docker-compose.yml
version: '3' services:
ここで、flask
をdocker-compose.yml
ファイルの最初のサービスとして定義します。 次のコードを追加して、Flaskサービスを定義します。
docker-compose.yml
. . . flask: build: context: app dockerfile: Dockerfile container_name: flask image: digitalocean.com/flask-python:3.6 restart: unless-stopped environment: APP_ENV: "prod" APP_DEBUG: "False" APP_PORT: 5000 MONGODB_DATABASE: flaskdb MONGODB_USERNAME: flaskuser MONGODB_PASSWORD: your_mongodb_password MONGODB_HOSTNAME: mongodb volumes: - appdata:/var/www depends_on: - mongodb networks: - frontend - backend
build
プロパティは、ビルドのcontext
を定義します。 この場合、Dockerfile
を含むapp
フォルダー。
container_name
プロパティを使用して、各コンテナの名前を定義します。 image
プロパティは、イメージ名とDockerイメージのタグ付け対象を指定します。 restart
プロパティは、コンテナを再起動する方法を定義します。この場合は、unless-stopped
です。 つまり、Docker Engineが停止/再起動された場合、またはコンテナーを明示的に停止した場合にのみ、コンテナーが停止します。 unless-stopped
プロパティを使用する利点は、Dockerエンジンが再起動されるか、エラーが発生すると、コンテナーが自動的に起動することです。
environment
プロパティには、コンテナに渡される環境変数が含まれています。 環境変数MONGODB_PASSWORD
の安全なパスワードを提供する必要があります。 volumes
プロパティは、サービスが使用しているボリュームを定義します。 あなたの場合、ボリュームappdata
はコンテナ内の/var/www
ディレクトリにマウントされています。 depends_on
プロパティは、Flaskが正しく機能するために依存するサービスを定義します。 この場合、mongodb
サービスはアプリケーションのデータベースとして機能するため、flask
サービスはmongodb
に依存します。 depends_on
は、mongodb
サービスが実行されている場合にのみflask
サービスが実行されるようにします。
networks
プロパティは、flask
サービスがアクセスできるネットワークとしてfrontend
とbackend
を指定します。
flask
サービスが定義されたら、MongoDB構成をファイルに追加する準備が整います。 この例では、公式の4.0.8
バージョンのmongo
イメージを使用します。 flask service
に続くdocker-compose.yml
ファイルに次のコードを追加します。
docker-compose.yml
. . . mongodb: image: mongo:4.0.8 container_name: mongodb restart: unless-stopped command: mongod --auth environment: MONGO_INITDB_ROOT_USERNAME: mongodbuser MONGO_INITDB_ROOT_PASSWORD: your_mongodb_root_password MONGO_INITDB_DATABASE: flaskdb MONGODB_DATA_DIR: /data/db MONDODB_LOG_DIR: /dev/null volumes: - mongodbdata:/data/db networks: - backend
このサービスのcontainer_name
はmongodb
で、再起動ポリシーはunless-stopped
です。 command
プロパティを使用して、コンテナの起動時に実行されるコマンドを定義します。 コマンドmongod --auth
は、資格情報なしでMongoDBシェルへのログインを無効にします。これにより、認証を要求することでMongoDBを保護します。
環境変数MONGO_INITDB_ROOT_USERNAME
およびMONGO_INITDB_ROOT_PASSWORD
は、指定された資格情報を持つrootユーザーを作成するため、プレースホルダーを強力なパスワードに置き換えてください。
MongoDBは、デフォルトでデータを/data/db
に保存するため、/data/db
フォルダー内のデータは、永続化のために名前付きボリュームmongodbdata
に書き込まれます。 その結果、再起動してもデータベースが失われることはありません。 mongoDB
サービスはポートを公開しないため、サービスにはbackend
ネットワーク経由でのみアクセスできます。
次に、アプリケーションのWebサーバーを定義します。 docker-compose.yml
ファイルに次のコードを追加して、Nginxを構成します。
docker-compose.yml
. . . webserver: build: context: nginx dockerfile: Dockerfile image: digitalocean.com/webserver:latest container_name: webserver restart: unless-stopped environment: APP_ENV: "prod" APP_NAME: "webserver" APP_DEBUG: "false" SERVICE_NAME: "webserver" ports: - "80:80" - "443:443" volumes: - nginxdata:/var/log/nginx depends_on: - flask networks: - frontend
ここでは、Dockerfile
を含むnginx
フォルダーであるbuild
のcontext
を定義しました。 image
プロパティを使用して、コンテナのタグ付けと実行に使用するイメージを指定します。 ports
プロパティは、:80
および:443
を介してパブリックにアクセスできるようにNginxサービスを構成し、volumes
はコンテナー内にnginxdata
ボリュームをマウントします/var/log/nginx
ディレクトリ。
Webサーバーサービスdepends_on
が適用されるサービスをflask
として定義しました。 最後に、networks
プロパティは、Webサーバーサービスがfrontend
にアクセスできるネットワークを定義します。
次に、ブリッジネットワークを作成して、コンテナが相互に通信できるようにします。 ファイルの最後に次の行を追加します。
docker-compose.yml
. . . networks: frontend: driver: bridge backend: driver: bridge
接続するサービス用に、frontend
とbackend
の2つのネットワークを定義しました。 Nginxなどのフロントエンドサービスは、パブリックアクセス可能である必要があるため、frontend
ネットワークに接続します。 MongoDBなどのバックエンドサービスは、backend
ネットワークに接続して、サービスへの不正アクセスを防ぎます。
次に、ボリュームを使用して、データベース、アプリケーション、および構成ファイルを永続化します。 アプリケーションはデータベースとファイルを使用するため、それらに加えられた変更を永続化することが不可欠です。 ボリュームはDockerによって管理され、ファイルシステムに保存されます。 このコードをdocker-compose.yml
ファイルに追加して、ボリュームを構成します。
docker-compose.yml
. . . volumes: mongodbdata: driver: local appdata: driver: local nginxdata: driver: local
volumes
セクションは、アプリケーションがデータを永続化するために使用するボリュームを宣言します。 ここでは、MongoDBデータベース、Flaskアプリケーションデータ、およびNginx Webサーバーログをそれぞれ永続化するためのボリュームmongodbdata
、appdata
、およびnginxdata
を定義しました。 これらのボリュームはすべて、local
ドライバーを使用してデータをローカルに保存します。 ボリュームはこのデータを永続化するために使用されるため、コンテナーを再起動すると、MongoDBデータベースやNginxWebサーバーログなどのデータが失われる可能性があります。
完全なdocker-compose.yml
ファイルは次のようになります。
docker-compose.yml
version: '3' services: flask: build: context: app dockerfile: Dockerfile container_name: flask image: digitalocean.com/flask-python:3.6 restart: unless-stopped environment: APP_ENV: "prod" APP_DEBUG: "False" APP_PORT: 5000 MONGODB_DATABASE: flaskdb MONGODB_USERNAME: flaskuser MONGODB_PASSWORD: your_mongodb_password MONGODB_HOSTNAME: mongodb volumes: - appdata:/var/www depends_on: - mongodb networks: - frontend - backend mongodb: image: mongo:4.0.8 container_name: mongodb restart: unless-stopped command: mongod --auth environment: MONGO_INITDB_ROOT_USERNAME: mongodbuser MONGO_INITDB_ROOT_PASSWORD: your_mongodb_root_password MONGO_INITDB_DATABASE: flaskdb MONGODB_DATA_DIR: /data/db MONDODB_LOG_DIR: /dev/null volumes: - mongodbdata:/data/db networks: - backend webserver: build: context: nginx dockerfile: Dockerfile image: digitalocean.com/webserver:latest container_name: webserver restart: unless-stopped environment: APP_ENV: "prod" APP_NAME: "webserver" APP_DEBUG: "true" SERVICE_NAME: "webserver" ports: - "80:80" - "443:443" volumes: - nginxdata:/var/log/nginx depends_on: - flask networks: - frontend networks: frontend: driver: bridge backend: driver: bridge volumes: mongodbdata: driver: local appdata: driver: local nginxdata: driver: local
ファイルを保存し、構成を確認した後、エディターを終了します。
docker-compose.yml
ファイルでアプリケーションスタック全体のDocker構成を定義しました。 次に、FlaskとWebサーバー用のDockerfileの作成に進みます。
ステップ2—フラスコとWebサーバーのDockerfileを作成する
Dockerを使用すると、Dockerfileというファイルからアプリケーションを実行するためのコンテナーを構築できます。 Dockerfileは、アプリケーションに必要なソフトウェアをインストールし、要件に基づいてコンテナーを構成するために使用できるカスタムイメージを作成できるツールです。 作成したカスタムイメージをDockerHubまたは任意のプライベートレジストリにプッシュできます。
このステップでは、FlaskおよびWebサーバーサービスのDockerfileを記述します。 開始するには、Flaskアプリケーションのapp
ディレクトリを作成します。
mkdir app
次に、app
ディレクトリにFlaskアプリのDockerfile
を作成します。
nano app/Dockerfile
次のコードをファイルに追加して、Flaskコンテナをカスタマイズします。
app / Dockerfile
FROM python:3.6.8-alpine3.9 LABEL MAINTAINER="FirstName LastName <[email protected]>" ENV GROUP_ID=1000 \ USER_ID=1000 WORKDIR /var/www/
このDockerfile
では、Python3.6.8がプリインストールされたAlpine3.9に基づく3.6.8-alpine3.9imageの上にイメージを作成しています。
ENV
ディレクティブは、グループとユーザーIDの環境変数を定義するために使用されます。 Linux Standard Base(LSB)は、UIDおよびGID0〜99がシステムによって静的に割り当てられることを指定します。 UID 100〜999 は、システムユーザーおよびグループに動的に割り当てられることになっています。 UID 1000-59999 は、ユーザーアカウントに動的に割り当てられることになっています。 このことを念頭に置いて、1000
のUIDとGIDを安全に割り当てることができます。さらに、要件に合わせてGROUP_ID
とUSER_ID
を更新することでUID/GIDを変更できます。
WORKDIR
ディレクティブは、コンテナの作業ディレクトリを定義します。 必ずLABEL MAINTAINER
フィールドを自分の名前とメールアドレスに置き換えてください。
次のコードブロックを追加して、Flaskアプリケーションをコンテナーにコピーし、必要な依存関係をインストールします。
app / Dockerfile
. . . ADD ./requirements.txt /var/www/requirements.txt RUN pip install -r requirements.txt ADD . /var/www/ RUN pip install gunicorn
次のコードは、ADD
ディレクティブを使用して、ローカルのapp
ディレクトリからコンテナの/var/www
ディレクトリにファイルをコピーします。 次に、DockerfileはRUN
ディレクティブを使用して、Gunicornと、チュートリアルの後半で作成するrequirements.txt
ファイルで指定されたパッケージをインストールします。
次のコードブロックは、新しいユーザーとグループを追加し、アプリケーションを初期化します。
app / Dockerfile
. . . RUN addgroup -g $GROUP_ID www RUN adduser -D -u $USER_ID -G www www -s /bin/sh USER www EXPOSE 5000 CMD [ "gunicorn", "-w", "4", "--bind", "0.0.0.0:5000", "wsgi"]
デフォルトでは、Dockerコンテナはrootユーザーとして実行されます。 root ユーザーはシステム内のすべてにアクセスできるため、セキュリティ違反の影響は悲惨なものになる可能性があります。 このセキュリティリスクを軽減するために、これにより、/var/www
ディレクトリにのみアクセスできる新しいユーザーとグループが作成されます。
このコードは、最初にaddgroup
コマンドを使用して、www
という名前の新しいグループを作成します。 -g
フラグは、グループIDをDockerfile
で以前に定義されたENV GROUP_ID=1000
変数に設定します。
adduser -D -u $USER_ID -G www www -s /bin/sh
行は、ENV
変数で定義されているように、1000
のユーザーIDを持つwww
ユーザーを作成します。 -s
フラグは、ユーザーのホームディレクトリが存在しない場合はそれを作成し、デフォルトのログインシェルを/bin/sh
に設定します。 -G
フラグは、ユーザーの初期ログイングループを前のコマンドで作成されたwww
に設定するために使用されます。
USER
コマンドは、コンテナーで実行されるプログラムがwww
ユーザーを使用することを定義します。 Gunicornは:5000
をリッスンするので、EXPOSE
コマンドでこのポートを開きます。
最後に、CMD [ "gunicorn", "-w", "4", "--bind", "0.0.0.0:5000", "wsgi"]
行は、ポート5000
でリッスンしている4人のワーカーでGunicornサーバーを起動するコマンドを実行します。 数は通常、サーバーのコアあたり2〜4ワーカーである必要があります。Gunicornのドキュメントでは、最初のワーカー数として(2 x $ num_cores)+1を推奨しています。
完成したDockerfile
は次のようになります。
app / Dockerfile
FROM python:3.6.8-alpine3.9 LABEL MAINTAINER="FirstName LastName <[email protected]>" ENV GROUP_ID=1000 \ USER_ID=1000 WORKDIR /var/www/ ADD . /var/www/ RUN pip install -r requirements.txt RUN pip install gunicorn RUN addgroup -g $GROUP_ID www RUN adduser -D -u $USER_ID -G www www -s /bin/sh USER www EXPOSE 5000 CMD [ "gunicorn", "-w", "4", "--bind", "0.0.0.0:5000", "wsgi"]
ファイルを保存して、テキストエディタを終了します。
次に、Nginx構成を保持するための新しいディレクトリを作成します。
mkdir nginx
次に、nginx
ディレクトリにNginxWebサーバー用のDockerfile
を作成します。
nano nginx/Dockerfile
次のコードをファイルに追加して、NginxコンテナーのイメージをビルドするDockerfileを作成します。
nginx / Dockerfile
FROM alpine:latest LABEL MAINTAINER="FirstName LastName <[email protected]>" RUN apk --update add nginx && \ ln -sf /dev/stdout /var/log/nginx/access.log && \ ln -sf /dev/stderr /var/log/nginx/error.log && \ mkdir /etc/nginx/sites-enabled/ && \ mkdir -p /run/nginx && \ rm -rf /etc/nginx/conf.d/default.conf && \ rm -rf /var/cache/apk/* COPY conf.d/app.conf /etc/nginx/conf.d/app.conf EXPOSE 80 443 CMD ["nginx", "-g", "daemon off;"]
このNginxDockerfile
は、alpine
ベースイメージを使用します。これは、セキュリティのために構築された最小限の攻撃対象領域を持つ小さなLinuxディストリビューションです。
RUN
ディレクティブでは、nginx
をインストールし、エラーとアクセスログを標準エラー(/dev/stderr
)と出力( [ X178X])。 コンテナは一時的なものであるため、エラーを標準エラーと出力に公開することがベストプラクティスです。これを行うと、ログはDockerログに送信され、そこからログをElasticスタックなどのログサービスに転送して永続化できます。 これが完了したら、コマンドを実行してdefault.conf
と/var/cache/apk/*
を削除し、結果の画像のサイズを縮小します。 これらすべてのコマンドを1つのRUN
で実行すると、画像内のレイヤー数が減り、結果の画像のサイズも小さくなります。
COPY
ディレクティブは、app.conf
Webサーバー構成をコンテナー内にコピーします。 EXPOSE
ディレクティブは、コンテナーがポート:80
および:443
でリッスンすることを保証します。これは、アプリケーションが:80
で実行され、:443
がセキュアであるためです。ポート。
最後に、CMD
ディレクティブは、Nginxサーバーを起動するコマンドを定義します。
ファイルを保存して、テキストエディタを終了します。
Dockerfile
の準備ができたので、トラフィックをFlaskアプリケーションにルーティングするようにNginxリバースプロキシを構成する準備が整いました。
ステップ3—Nginxリバースプロキシの構成
このステップでは、:5000
上のGunicornにリクエストを転送するためのリバースプロキシとしてNginxを構成します。 リバースプロキシサーバーは、クライアント要求を適切なバックエンドサーバーに転送するために使用されます。 クライアントとサーバー間のネットワークトラフィックのスムーズな流れを確保するために、抽象化と制御の追加レイヤーを提供します。
nginx/conf.d
ディレクトリを作成することから始めます。
mkdir nginx/conf.d
Nginxを構成するには、nginx/conf.d/
フォルダーに次の構成でapp.conf
ファイルを作成する必要があります。 app.conf
ファイルには、リバースプロキシがリクエストをGunicornに転送するために必要な構成が含まれています。
nano nginx/conf.d/app.conf
次の内容をapp.conf
ファイルに入れます。
nginx / conf.d / app.conf
upstream app_server { server flask:5000; } server { listen 80; server_name _; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; client_max_body_size 64M; location / { try_files $uri @proxy_to_app; } location @proxy_to_app { gzip_static on; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; proxy_buffering off; proxy_redirect off; proxy_pass http://app_server; } }
これにより、最初にアップストリームサーバーが定義されます。これは、ルーティングまたは負荷分散のためにWebサーバーまたはアプリサーバーを指定するために一般的に使用されます。
アップストリームサーバーapp_server
は、コンテナー名flask:5000
で識別されるserver
ディレクティブを使用してサーバーアドレスを定義します。
Nginx Webサーバーの構成は、server
ブロックで定義されています。 listen
ディレクティブは、サーバーが着信要求をリッスンするポート番号を定義します。 error_log
およびaccess_log
ディレクティブは、ログを書き込むためのファイルを定義します。 proxy_pass
ディレクティブは、リクエストをhttp://app_server
に転送するためのアップストリームサーバーを設定するために使用されます。
ファイルを保存して閉じます。
Nginx Webサーバーを構成したら、Flaskto-doAPIの作成に進むことができます。
ステップ4— FlaskTo-DoAPIを作成する
環境を構築したので、アプリケーションを構築する準備が整いました。 このステップでは、POSTリクエストから送信されたToDoメモを保存して表示するToDoAPIアプリケーションを作成します。
app
ディレクトリにrequirements.txt
ファイルを作成することから始めます。
nano app/requirements.txt
このファイルは、アプリケーションの依存関係をインストールするために使用されます。 このチュートリアルの実装では、 Flask 、 Flask-PyMongo 、およびrequestsを使用します。 requirements.txt
ファイルに以下を追加します。
app / requireds.txt
Flask==1.0.2 Flask-PyMongo==2.2.0 requests==2.20.1
ファイルを保存し、要件を入力した後、エディターを終了します。
次に、app.py
ファイルを作成して、app
ディレクトリにFlaskアプリケーションコードを含めます。
nano app/app.py
新しいapp.py
ファイルに、依存関係をインポートするコードを入力します。
app / app.py
import os from flask import Flask, request, jsonify from flask_pymongo import PyMongo
os
パッケージは、環境変数をインポートするために使用されます。 flask
ライブラリから、Flask
、request
、およびjsonify
オブジェクトをインポートして、それぞれアプリケーションのインスタンス化、リクエストの処理、JSONレスポンスの送信を行いました。 flask_pymongo
から、MongoDBと対話するためにPyMongo
オブジェクトをインポートしました。
次に、MongoDBに接続するために必要なコードを追加します。
app / app.py
. . . application = Flask(__name__) application.config["MONGO_URI"] = 'mongodb://' + os.environ['MONGODB_USERNAME'] + ':' + os.environ['MONGODB_PASSWORD'] + '@' + os.environ['MONGODB_HOSTNAME'] + ':27017/' + os.environ['MONGODB_DATABASE'] mongo = PyMongo(application) db = mongo.db
Flask(__name__)
は、アプリケーションオブジェクトをapplication
変数にロードします。 次に、コードはos.environ
を使用して環境変数からMongoDB接続文字列を構築します。 application
オブジェクトをPyMongo()
メソッドに渡すと、mongo
オブジェクトが得られ、db
オブジェクトがmongo.db
から得られます。 ]。
次に、インデックスメッセージを作成するためのコードを追加します。
app / app.py
. . . @application.route('/') def index(): return jsonify( status=True, message='Welcome to the Dockerized Flask MongoDB app!' )
@application.route('/')
は、APIの/
GETルートを定義します。 ここで、index()
関数は、jsonify
メソッドを使用してJSON文字列を返します。
次に、/todo
ルートを追加して、すべてのToDoを一覧表示します。
app / app.py
. . . @application.route('/todo') def todo(): _todos = db.todo.find() item = {} data = [] for todo in _todos: item = { 'id': str(todo['_id']), 'todo': todo['todo'] } data.append(item) return jsonify( status=True, data=data )
@application.route('/todo')
は、APIの/todo
GETルートを定義します。これにより、データベース内のToDoが返されます。 db.todo.find()
メソッドは、データベース内のすべてのToDoを返します。 次に、_todos
を繰り返し処理して、data
に追加するオブジェクトからid
とtodo
のみを含むitem
を構築します。 ]配列を作成し、最後にそれらをJSONとして返します。
次に、やることを作成するためのコードを追加します。
app / app.py
. . . @application.route('/todo', methods=['POST']) def createTodo(): data = request.get_json(force=True) item = { 'todo': data['todo'] } db.todo.insert_one(item) return jsonify( status=True, message='To-do saved successfully!' ), 201
@application.route('/todo')
は、APIの/todo
POSTルートを定義します。これにより、データベースにToDoメモが作成されます。 request.get_json(force=True)
は、ルートに投稿したJSONを取得し、item
は、ToDoに保存されるJSONを構築するために使用されます。 db.todo.insert_one(item)
は、データベースに1つのアイテムを挿入するために使用されます。 To Doがデータベースに保存された後、ステータスコード201 CREATED
のJSON応答を返します。
次に、アプリケーションを実行するためのコードを追加します。
app / app.py
. . . if __name__ == "__main__": ENVIRONMENT_DEBUG = os.environ.get("APP_DEBUG", True) ENVIRONMENT_PORT = os.environ.get("APP_PORT", 5000) application.run(host='0.0.0.0', port=ENVIRONMENT_PORT, debug=ENVIRONMENT_DEBUG)
条件__name__ == "__main__"
は、モジュール内のグローバル変数__name__
がプログラムへのエントリポイントであるかどうかを確認し、アプリケーションを実行するために使用されます。 __name__
が"__main__"
と等しい場合、if
ブロック内のコードは、このコマンドapplication.run(host='0.0.0.0', port=ENVIRONMENT_PORT, debug=ENVIRONMENT_DEBUG)
を使用してアプリを実行します。
次に、os.environ.get()
を使用して、環境変数からENVIRONMENT_DEBUG
とENVIRONMENT_PORT
の値を取得します。最初のパラメーターとしてキーを使用し、2番目のパラメーターとしてデフォルト値を使用します。 application.run()
は、アプリケーションのhost
、port
、およびdebug
の値を設定します。
完成したapp.py
ファイルは次のようになります。
app / app.py
import os from flask import Flask, request, jsonify from flask_pymongo import PyMongo application = Flask(__name__) application.config["MONGO_URI"] = 'mongodb://' + os.environ['MONGODB_USERNAME'] + ':' + os.environ['MONGODB_PASSWORD'] + '@' + os.environ['MONGODB_HOSTNAME'] + ':27017/' + os.environ['MONGODB_DATABASE'] mongo = PyMongo(application) db = mongo.db @application.route('/') def index(): return jsonify( status=True, message='Welcome to the Dockerized Flask MongoDB app!' ) @application.route('/todo') def todo(): _todos = db.todo.find() item = {} data = [] for todo in _todos: item = { 'id': str(todo['_id']), 'todo': todo['todo'] } data.append(item) return jsonify( status=True, data=data ) @application.route('/todo', methods=['POST']) def createTodo(): data = request.get_json(force=True) item = { 'todo': data['todo'] } db.todo.insert_one(item) return jsonify( status=True, message='To-do saved successfully!' ), 201 if __name__ == "__main__": ENVIRONMENT_DEBUG = os.environ.get("APP_DEBUG", True) ENVIRONMENT_PORT = os.environ.get("APP_PORT", 5000) application.run(host='0.0.0.0', port=ENVIRONMENT_PORT, debug=ENVIRONMENT_DEBUG)
ファイルを保存して、エディターを終了します。
次に、app
ディレクトリにwsgi.py
ファイルを作成します。
nano app/wsgi.py
wsgi.py
ファイルは、サーバーが使用できるようにアプリケーションオブジェクト(または呼び出し可能)を作成します。 リクエストが来るたびに、サーバーはこのアプリケーションオブジェクトを使用して、URLの解析時にアプリケーションのリクエストハンドラーを実行します。
次の内容をwsgi.py
ファイルに入れ、ファイルを保存して、テキストエディタを終了します。
app / wsgi.py
from app import application if __name__ == "__main__": application.run()
このwsgi.py
ファイルは、app.py
ファイルからアプリケーションオブジェクトをインポートし、Gunicornサーバー用のアプリケーションオブジェクトを作成します。
これでToDoアプリが配置されたので、コンテナーでアプリケーションの実行を開始する準備が整いました。
ステップ5—コンテナの構築と実行
docker-compose.yml
ファイル内のすべてのサービスとその構成を定義したので、コンテナーを開始できます。
サービスは単一のファイルで定義されているため、単一のコマンドを発行してコンテナーを開始し、ボリュームを作成し、ネットワークをセットアップする必要があります。 このコマンドは、FlaskアプリケーションとNginxWebサーバーのイメージも構築します。 次のコマンドを実行して、コンテナーを作成します。
docker-compose up -d
コマンドを初めて実行すると、必要なすべてのDockerイメージがダウンロードされます。これには時間がかかる場合があります。 イメージがダウンロードされてローカルマシンに保存されると、docker-compose
によってコンテナが作成されます。 -d
フラグはプロセスをデーモン化し、バックグラウンドプロセスとして実行できるようにします。
ビルドプロセスが完了したら、次のコマンドを使用して実行中のコンテナを一覧表示します。
docker ps
次のような出力が表示されます。
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f20e9a7fd2b9 digitalocean.com/webserver:latest "nginx -g 'daemon of…" 2 weeks ago Up 2 weeks 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp webserver 3d53ea054517 digitalocean.com/flask-python:3.6 "gunicorn -w 4 --bin…" 2 weeks ago Up 2 weeks 5000/tcp flask 96f5a91fc0db mongo:4.0.8 "docker-entrypoint.s…" 2 weeks ago Up 2 weeks 27017/tcp mongodb
CONTAINER ID
は、コンテナーへのアクセスに使用される一意の識別子です。 IMAGE
は、指定されたコンテナーのイメージ名を定義します。 NAMES
フィールドは、コンテナーが作成されるサービス名です。CONTAINER ID
と同様に、コンテナーへのアクセスに使用できます。 最後に、STATUS
は、コンテナーが実行中、再起動中、または停止中かどうかに関するコンテナーの状態に関する情報を提供します。
docker-compose
コマンドを使用して、構成ファイルからコンテナーをビルドしました。 次のステップでは、アプリケーションのMongoDBユーザーを作成します。
ステップ6—MongoDBデータベースのユーザーを作成する
デフォルトでは、MongoDBはユーザーが資格情報なしでログインすることを許可し、無制限の特権を付与します。 このステップでは、MongoDBデータベースにアクセスするための専用ユーザーを作成して、MongoDBデータベースを保護します。
これを行うには、mongodb
サービスのdocker-compose.yml
ファイル環境変数MONGO_INITDB_ROOT_USERNAME
およびMONGO_INITDB_ROOT_PASSWORD
で設定したrootユーザー名とパスワードが必要です。 一般に、データベースを操作するときは、root管理者アカウントの使用を避けることをお勧めします。 代わりに、Flaskアプリケーション専用のデータベースユーザーと、Flaskアプリがアクセスできる新しいデータベースを作成します。
新しいユーザーを作成するには、最初にmongodb
コンテナでインタラクティブシェルを起動します。
docker exec -it mongodb bash
docker exec
コマンドを使用して、実行中のコンテナー内でコマンドを実行し、-it
フラグを使用して、コンテナー内で対話型シェルを実行します。
コンテナ内に入ると、MongoDB root管理者アカウントにログインします。
mongo -u mongodbuser -p
docker-compose.yml
ファイルのMONGO_INITDB_ROOT_PASSWORD
変数の値として入力したパスワードの入力を求められます。 mongodb
サービスでMONGO_INITDB_ROOT_PASSWORD
に新しい値を設定することでパスワードを変更できます。その場合は、docker-compose up -d
コマンドを再実行する必要があります。
show dbs;
コマンドを実行して、すべてのデータベースを一覧表示します。
show dbs;
次の出力が表示されます。
Outputadmin 0.000GB config 0.000GB local 0.000GB 5 rows in set (0.00 sec)
admin
データベースは、ユーザーに管理者権限を付与する特別なデータベースです。 ユーザーがadmin
データベースへの読み取りアクセス権を持っている場合、他のすべてのデータベースへの読み取りおよび書き込み権限があります。 出力にはadmin
データベースがリストされているため、ユーザーはこのデータベースにアクセスでき、他のすべてのデータベースに対して読み取りと書き込みを行うことができます。
最初のやることメモを保存すると、自動的にMongoDBデータベースが作成されます。 MongoDBでは、use database
コマンドを使用して、存在しないデータベースに切り替えることができます。 ドキュメントがコレクションに保存されるときにデータベースを作成します。 したがって、データベースはここでは作成されません。 これは、APIからデータベースに最初のやることメモを保存するときに発生します。 use
コマンドを実行して、flaskdb
データベースに切り替えます。
use flaskdb
次に、このデータベースへのアクセスを許可する新しいユーザーを作成します。
db.createUser({user: 'flaskuser', pwd: 'your password', roles: [{role: 'readWrite', db: 'flaskdb'}]}) exit
このコマンドは、flaskdb
データベースへのreadWrite
アクセス権を持つflaskuserという名前のユーザーを作成します。 pwd
フィールドには必ず安全なパスワードを使用してください。 user
およびpwd
は、flask
サービスの環境変数セクションのdocker-compose.yml
ファイルで定義した値です。
次のコマンドを使用して、認証されたデータベースにログインします。
mongo -u flaskuser -p your password --authenticationDatabase flaskdb
ユーザーを追加したので、データベースからログアウトします。
exit
そして最後に、コンテナを終了します。
exit
これで、Flaskアプリケーション専用のデータベースとユーザーアカウントが構成されました。 データベースコンポーネントの準備ができたので、Flaskto-doアプリの実行に進むことができます。
ステップ7—FlaskTo-doアプリを実行する
サービスが構成されて実行されたので、ブラウザーでhttp://your_server_ip
に移動してアプリケーションをテストできます。 さらに、curl
を実行して、FlaskからのJSON応答を確認できます。
curl -i http://your_server_ip
次の応答が返されます。
Output{"message":"Welcome to the Dockerized Flask MongoDB app!","status":true}
Flaskアプリケーションの構成は、docker-compose.yml
ファイルからアプリケーションに渡されます。 データベース接続に関する設定は、flask
サービスのenvironment
セクションで定義されているMONGODB_*
変数を使用して設定されます。
すべてをテストするには、FlaskAPIを使用してやることメモを作成します。 これは、/todo
ルートへのPOST
curlリクエストを使用して行うことができます。
curl -i -H "Content-Type: application/json" -X POST -d '{"todo": "Dockerize Flask application with MongoDB backend"}' http://your_server_ip/todo
このリクエストにより、To DoアイテムがMongoDBに保存されると、ステータスコード201 CREATED
の応答が返されます。
Output{"message":"To-do saved successfully!","status":true}
/todo
ルートへのGETリクエストを使用して、MongoDBからのすべてのToDoノートを一覧表示できます。
curl -i http://your_server_ip/todo
Output{"data":[{"id":"5c9fa25591cb7b000a180b60","todo":"Dockerize Flask application with MongoDB backend"}],"status":true}
これにより、サーバーにデプロイされたリバースプロキシとしてNginxを使用してMongoDBバックエンドを実行するFlaskAPIをDocker化できました。 実稼働環境の場合、sudo systemctl enable docker
を使用して、Dockerサービスが実行時に自動的に開始されるようにすることができます。
結論
このチュートリアルでは、Docker、MongoDB、Nginx、およびGunicornを使用してFlaskアプリケーションをデプロイしました。 これで、スケーリング可能な最新のステートレスAPIアプリケーションが機能するようになりました。 docker container run
のようなコマンドを使用してこの結果を達成できますが、docker-compose.yml
は、このスタックをバージョン管理に入れて必要に応じて更新できるため、作業が簡素化されます。
ここから、さらにPythonFrameworkチュートリアルを見ることができます。