序章

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に転送するリバースプロキシサーバーとして機能します。

前提条件

このチュートリアルに従うには、次のものが必要です。

  • root以外のユーザー sudo サーバーの初期設定チュートリアルの手順に従って構成された特権。
  • Dockerのインストールと使用方法のステップ1とステップ2の手順でDockerをインストールしました。
  • Docker Composeのインストール方法のステップ1の手順に従って、DockerComposeをインストールします。

ステップ1—DockerComposeでスタック構成を作成する

Dockerでアプリケーションを構築すると、DockerComposeで行った構成の変更に応じてインフラストラクチャを簡単にバージョン管理できます。 インフラストラクチャは、単一のファイルで定義し、単一のコマンドで構築できます。 このステップでは、 docker-compose.yml Flaskアプリケーションを実行するためのファイル。

The docker-compose.yml ファイルを使用すると、アプリケーションインフラストラクチャを個別のサービスとして定義できます。 サービスは相互に接続でき、永続ストレージ用にボリュームを接続できます。 ボリュームは、Dockerによって管理されるホストファイルシステムの一部に保存されます(/var/lib/docker/volumes/ Linuxの場合)。

ボリューム内のデータはエクスポートしたり、他のアプリケーションと共有したりできるため、ボリュームはDockerでデータを永続化するための最良の方法です。 Dockerでのデータ共有の詳細については、Dockerコンテナとホスト間でデータを共有する方法を参照してください。

開始するには、サーバーのホームディレクトリにアプリケーションのディレクトリを作成します。

  1. mkdir flaskapp

新しく作成したディレクトリに移動します。

  1. cd flaskapp

次に、を作成します docker-compose.yml ファイル:

  1. nano docker-compose.yml

The 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

The build プロパティは、 context ビルドの。 この場合、 app を含むフォルダ Dockerfile.

あなたは container_name 各コンテナの名前を定義するプロパティ。 The image プロパティは、イメージ名とDockerイメージのタグ付け対象を指定します。 The restart プロパティは、コンテナを再起動する方法を定義します。あなたの場合は、 unless-stopped. つまり、Docker Engineが停止/再起動された場合、またはコンテナーを明示的に停止した場合にのみ、コンテナーが停止します。 を使用する利点 unless-stopped プロパティは、Dockerエンジンが再起動されるか、エラーが発生すると、コンテナが自動的に起動することです。

The environment プロパティには、コンテナに渡される環境変数が含まれています。 環境変数に安全なパスワードを提供する必要があります MONGODB_PASSWORD. The volumes プロパティは、サービスが使用しているボリュームを定義します。 あなたの場合、ボリューム appdata でコンテナ内にマウントされています /var/www ディレクトリ。 The depends_on プロパティは、Flaskが適切に機能するために依存するサービスを定義します。 この場合、 flask サービスはに依存します mongodb 以来 mongodb サービスは、アプリケーションのデータベースとして機能します。 depends_on を保証します flask サービスは、 mongodb サービスが実行されています。

The networks プロパティは指定します frontendbackend ネットワークとして flask サービスはにアクセスできます。

とともに flask サービスが定義されたら、MongoDB構成をファイルに追加する準備が整いました。 この例では、公式を使用します 4.0.8 バージョン mongo 画像。 次のコードをに追加します docker-compose.yml 次のファイル flask service:

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

The container_name このサービスのために mongodb 再起動ポリシーが unless-stopped. あなたは command コンテナの起動時に実行されるコマンドを定義するプロパティ。 コマンド mongod --auth 資格情報なしでMongoDBシェルへのログインを無効にします。これにより、認証を要求することでMongoDBを保護します。

環境変数 MONGO_INITDB_ROOT_USERNAMEMONGO_INITDB_ROOT_PASSWORD 指定された資格情報を使用してrootユーザーを作成するため、プレースホルダーを強力なパスワードに置き換えてください。

MongoDBはそのデータをに保存します /data/db デフォルトでは、したがって、 /data/db フォルダは指定されたボリュームに書き込まれます mongodbdata 永続性のため。 その結果、再起動してもデータベースが失われることはありません。 The 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

ここで定義しました contextbuild、これは nginx を含むフォルダ Dockerfile. とともに image プロパティでは、コンテナのタグ付けと実行に使用するイメージを指定します。 The ports プロパティは、Nginxサービスがを介してパブリックにアクセスできるように構成します :80:443volumes マウントします nginxdata コンテナ内のボリューム /var/log/nginx ディレクトリ。

Webサーバーサービスの対象となるサービスを定義しました depends_on なので flask. 最後に networks プロパティは、Webサーバーサービスがアクセスできるネットワークを定義します。 frontend.

次に、ブリッジネットワークを作成して、コンテナが相互に通信できるようにします。 ファイルの最後に次の行を追加します。

docker-compose.yml
. . .
networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

2つのネットワークを定義しました—frontendbackend-接続するサービス用。 Nginxなどのフロントエンドサービスは、 frontend 公的にアクセス可能である必要があるため、ネットワーク。 MongoDBなどのバックエンドサービスは、 backend サービスへの不正アクセスを防ぐためのネットワーク。

次に、ボリュームを使用して、データベース、アプリケーション、および構成ファイルを永続化します。 アプリケーションはデータベースとファイルを使用するため、それらに加えられた変更を永続化することが不可欠です。 ボリュームはDockerによって管理され、ファイルシステムに保存されます。 このコードをに追加します docker-compose.yml ボリュームを構成するファイル:

docker-compose.yml
. . .
volumes:
  mongodbdata:
    driver: local
  appdata:
    driver: local
  nginxdata:
    driver: local

The volumes セクションは、アプリケーションがデータを永続化するために使用するボリュームを宣言します。 ここでボリュームを定義しました mongodbdata, appdata、 と nginxdata MongoDBデータベース、Flaskアプリケーションデータ、およびNginxWebサーバーログをそれぞれ永続化するため。 これらのボリュームはすべて、 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構成を docker-compose.yml ファイル。 次に、FlaskとWebサーバー用のDockerfileの作成に進みます。

ステップ2—フラスコとWebサーバーのDockerfileを作成する

Dockerを使用すると、Dockerfileというファイルからアプリケーションを実行するためのコンテナーを構築できます。 Dockerfileは、アプリケーションに必要なソフトウェアをインストールし、要件に基づいてコンテナーを構成するために使用できるカスタムイメージを作成できるツールです。 作成したカスタムイメージをDockerHubまたは任意のプライベートレジストリにプッシュできます。

このステップでは、FlaskおよびWebサーバーサービスのDockerfileを記述します。 開始するには、を作成します app Flaskアプリケーションのディレクトリ:

  1. mkdir app

次に、を作成します Dockerfile のFlaskアプリ用 app ディレクトリ:

  1. 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の上にイメージを作成しています。

The ENV ディレクティブは、グループとユーザーIDの環境変数を定義するために使用されます。 Linux Standard Base(LSB)は、UIDおよびGID0〜99がシステムによって静的に割り当てられることを指定します。 UID 100〜999 は、システムユーザーおよびグループに動的に割り当てられることになっています。 UID 1000-59999 は、ユーザーアカウントに動的に割り当てられることになっています。 これを念頭に置いて、次のUIDとGIDを安全に割り当てることができます。 1000、さらに、更新することでUID/GIDを変更できます GROUP_IDUSER_ID 要件に合わせて。

The 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. The -g フラグはグループIDをに設定します ENV GROUP_ID=1000 以前に定義された変数 Dockerfile.

The adduser -D -u $USER_ID -G www www -s /bin/sh 線は作成します www ユーザーIDが 1000、によって定義されるように ENV 変数。 The -s flagは、ユーザーのホームディレクトリが存在しない場合はそれを作成し、デフォルトのログインシェルを次のように設定します。 /bin/sh. The -G フラグは、ユーザーの初期ログイングループをに設定するために使用されます www、前のコマンドで作成されました。

The USER コマンドは、コンテナで実行されるプログラムがを使用することを定義します www ユーザー。 Gunicornは耳を傾けます :5000、したがって、このポートを EXPOSE 指図。

最後に、 CMD [ "gunicorn", "-w", "4", "--bind", "0.0.0.0:5000", "wsgi"] lineは、ポートでリッスンしている4人のワーカーでGunicornサーバーを起動するコマンドを実行します 5000. 数は通常、サーバーのコアあたり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構成を保持するための新しいディレクトリを作成します。

  1. mkdir nginx

次に、を作成します Dockerfile のNginxWebサーバー用 nginx ディレクトリ:

  1. 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;"]

このNginx Dockerfile を使用します alpine ベースイメージ。これは、セキュリティのために構築された最小限の攻撃対象領域を持つ小さなLinuxディストリビューションです。

の中に RUN インストールするディレクティブ nginx エラーとアクセスログを標準エラーに公開するためのシンボリックリンクを作成するだけでなく(/dev/stderr)および出力(/dev/stdout). コンテナは一時的なものであるため、エラーを標準エラーと出力に公開することがベストプラクティスです。これを行うと、ログはDockerログに送信され、そこからログをElasticスタックなどのログサービスに転送して永続化できます。 これが行われた後、コマンドが実行されて default.conf/var/cache/apk/* 結果の画像のサイズを縮小します。 これらすべてのコマンドを1回で実行する RUN 画像のレイヤー数を減らし、結果の画像のサイズも減らします。

The COPY ディレクティブは app.conf コンテナ内のWebサーバー構成。 The EXPOSE ディレクティブは、コンテナがポートでリッスンすることを保証します :80:443、アプリケーションが実行されるように :80:443 安全なポートとして。

最後に、 CMD ディレクティブは、Nginxサーバーを起動するコマンドを定義します。

ファイルを保存して、テキストエディタを終了します。

今では Dockerfile 準備ができたら、トラフィックをFlaskアプリケーションにルーティングするようにNginxリバースプロキシを構成する準備が整いました。

ステップ3—Nginxリバースプロキシの構成

このステップでは、リクエストをGunicornに転送するためのリバースプロキシとしてNginxを構成します。 :5000. リバースプロキシサーバーは、クライアント要求を適切なバックエンドサーバーに転送するために使用されます。 クライアントとサーバー間のネットワークトラフィックのスムーズな流れを確保するために、抽象化と制御の追加レイヤーを提供します。

を作成することから始めましょう nginx/conf.d ディレクトリ:

  1. mkdir nginx/conf.d

Nginxを構成するには、 app.conf 次の構成のファイル nginx/conf.d/ フォルダ。 The app.conf ファイルには、リバースプロキシがリクエストをGunicornに転送するために必要な構成が含まれています。

  1. 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、でサーバーアドレスを定義します server コンテナ名で識別されるディレクティブ flask:5000.

Nginx Webサーバーの構成は、 server ブロック。 The listen ディレクティブは、サーバーが着信要求をリッスンするポート番号を定義します。 The error_logaccess_log ディレクティブは、ログを書き込むためのファイルを定義します。 The proxy_pass ディレクティブは、リクエストをに転送するためのアップストリームサーバーを設定するために使用されます http://app_server.

ファイルを保存して閉じます。

Nginx Webサーバーを構成したら、Flaskto-doAPIの作成に進むことができます。

ステップ4— FlaskTo-DoAPIを作成する

環境を構築したので、アプリケーションを構築する準備が整いました。 このステップでは、POSTリクエストから送信されたToDoメモを保存して表示するToDoAPIアプリケーションを作成します。

を作成することから始めましょう requirements.txt のファイル app ディレクトリ:

  1. 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 にFlaskアプリケーションコードを含めるファイル app ディレクトリ:

  1. nano app/app.py

あなたの新しいで app.py ファイルに、依存関係をインポートするコードを入力します。

app / app.py
import os
from flask import Flask, request, jsonify
from flask_pymongo import PyMongo

The os パッケージは、環境変数をインポートするために使用されます。 から flask インポートしたライブラリ Flask, request、 と jsonify アプリケーションをインスタンス化し、リクエストを処理し、JSONレスポンスを送信するオブジェクト。 から flask_pymongo インポートしました PyMongo MongoDBと対話するオブジェクト。

次に、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

The Flask(__name__) アプリケーションオブジェクトをにロードします application 変数。 次に、コードはを使用して環境変数からMongoDB接続文字列を構築します os.environ. 合格 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!'
    )

The @application.route('/') を定義します / APIのルートを取得します。 ここにあなたの index() 関数は、を使用してJSON文字列を返します jsonify 方法。

次に、 /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
    )

The @application.route('/todo') を定義します /todo APIのGETルート。これにより、データベース内のToDoが返されます。 The db.todo.find() メソッドは、データベース内のすべてのToDoを返します。 次に、繰り返します _todos を構築するには item それだけが含まれています idtodo それらを追加するオブジェクトから data 配列し、最後にそれらを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

The @application.route('/todo') を定義します /todo APIのPOSTルート。これにより、データベースにToDoメモが作成されます。 The request.get_json(force=True) ルートに投稿したJSONを取得し、 item ToDoに保存されるJSONを構築するために使用されます。 The db.todo.insert_one(item) 1つのアイテムをデータベースに挿入するために使用されます。 To Doがデータベースに保存された後、ステータスコードが次のJSON応答を返します。 201 CREATED.

次に、アプリケーションを実行するためのコードを追加します。

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__、モジュール内はプログラムへのエントリポイントであり、 "__main__"、次にアプリケーションを実行します。 の場合 __name__ に等しい "__main__" 次に、内部のコード if ブロックはこのコマンドを使用してアプリを実行します application.run(host='0.0.0.0', port=ENVIRONMENT_PORT, debug=ENVIRONMENT_DEBUG).

次に、の値を取得します ENVIRONMENT_DEBUGENVIRONMENT_PORT を使用して環境変数から os.environ.get()、最初のパラメーターとしてキーを使用し、2番目のパラメーターとしてデフォルト値を使用します。 The 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)

ファイルを保存して、エディターを終了します。

次に、を作成します wsgi.py のファイル app ディレクトリ。

  1. nano app/wsgi.py

The wsgi.py fileは、サーバーがそれを使用できるように、アプリケーションオブジェクト(または呼び出し可能)を作成します。 リクエストが来るたびに、サーバーはこのアプリケーションオブジェクトを使用して、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サーバーのイメージも構築します。 次のコマンドを実行して、コンテナーを作成します。

  1. docker-compose up -d

コマンドを初めて実行すると、必要なすべてのDockerイメージがダウンロードされます。これには時間がかかる場合があります。 画像がダウンロードされてローカルマシンに保存されたら、 docker-compose コンテナを作成します。 The -d flagはプロセスをデーモン化し、バックグラウンドプロセスとして実行できるようにします。

ビルドプロセスが完了したら、次のコマンドを使用して実行中のコンテナを一覧表示します。

  1. docker ps

次のような出力が表示されます。

Output
CONTAINER 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

The CONTAINER ID コンテナへのアクセスに使用される一意の識別子です。 The IMAGE 指定されたコンテナのイメージ名を定義します。 The NAMES フィールドは、コンテナが作成されるサービス名であり、次のようになります。 CONTAINER ID これらは、コンテナへのアクセスに使用できます。 最後に、 STATUS コンテナーが実行中、再起動中、または停止中かどうかに関するコンテナーの状態に関する情報を提供します。

あなたは使用しました docker-compose 構成ファイルからコンテナーを構築するコマンド。 次のステップでは、アプリケーションのMongoDBユーザーを作成します。

ステップ6—MongoDBデータベースのユーザーを作成する

デフォルトでは、MongoDBはユーザーが資格情報なしでログインすることを許可し、無制限の特権を付与します。 このステップでは、MongoDBデータベースにアクセスするための専用ユーザーを作成して、MongoDBデータベースを保護します。

これを行うには、で設定したルートユーザー名とパスワードが必要になります docker-compose.yml ファイル環境変数 MONGO_INITDB_ROOT_USERNAMEMONGO_INITDB_ROOT_PASSWORD のために mongodb サービス。 一般に、データベースを操作するときは、root管理者アカウントの使用を避けることをお勧めします。 代わりに、Flaskアプリケーション専用のデータベースユーザーと、Flaskアプリがアクセスできる新しいデータベースを作成します。

新しいユーザーを作成するには、最初にでインタラクティブシェルを起動します mongodb 容器:

  1. docker exec -it mongodb bash

あなたは docker exec 実行中のコンテナ内でコマンドを実行するためのコマンド -it コンテナ内でインタラクティブシェルを実行するためのフラグ。

コンテナ内に入ると、MongoDB root管理者アカウントにログインします。

  1. mongo -u mongodbuser -p

の値として入力したパスワードの入力を求められます MONGO_INITDB_ROOT_PASSWORD の変数 docker-compose.yml ファイル。 パスワードは、に新しい値を設定することで変更できます。 MONGO_INITDB_ROOT_PASSWORD の中に mongodb サービス。この場合、再実行する必要があります。 docker-compose up -d 指図。

を実行します show dbs; すべてのデータベースを一覧表示するコマンド:

  1. show dbs;

次の出力が表示されます。

Output
admin 0.000GB config 0.000GB local 0.000GB 5 rows in set (0.00 sec)

The admin データベースは、ユーザーに管理者権限を付与する特別なデータベースです。 ユーザーがへの読み取りアクセス権を持っている場合 admin データベースの場合、他のすべてのデータベースに対する読み取りおよび書き込み権限があります。 出力には admin データベースの場合、ユーザーはこのデータベースにアクセスできるため、他のすべてのデータベースの読み取りと書き込みを行うことができます。

最初のやることメモを保存すると、自動的にMongoDBデータベースが作成されます。 MongoDBを使用すると、を使用して存在しないデータベースに切り替えることができます。 use database 指図。 ドキュメントがコレクションに保存されるときにデータベースを作成します。 したがって、データベースはここでは作成されません。 これは、APIからデータベースに最初のやることメモを保存するときに発生します。 を実行します use に切り替えるコマンド flaskdb データベース:

  1. use flaskdb

次に、このデータベースへのアクセスを許可する新しいユーザーを作成します。

  1. db.createUser({user: 'flaskuser', pwd: 'your password', roles: [{role: 'readWrite', db: 'flaskdb'}]})
  2. exit

このコマンドは、flaskuserという名前のユーザーを作成します。 readWrite アクセス flaskdb データベース。 で安全なパスワードを使用してください pwd 分野。 The userpwd で定義した値は次のとおりです docker-compose.yml の環境変数セクションの下にあるファイル flask サービス。

次のコマンドを使用して、認証されたデータベースにログインします。

  1. mongo -u flaskuser -p your password --authenticationDatabase flaskdb

ユーザーを追加したので、データベースからログアウトします。

  1. exit

そして最後に、コンテナを終了します。

  1. exit

これで、Flaskアプリケーション専用のデータベースとユーザーアカウントが構成されました。 データベースコンポーネントの準備ができたので、Flaskto-doアプリの実行に進むことができます。

ステップ7—FlaskTo-doアプリを実行する

サービスが構成されて実行されたので、次のコマンドに移動してアプリケーションをテストできます。 http://your_server_ip ブラウザで。 さらに、あなたは実行することができます curl FlaskからのJSON応答を確認するには:

  1. curl -i http://your_server_ip

次の応答が返されます。

Output
{"message":"Welcome to the Dockerized Flask MongoDB app!","status":true}

Flaskアプリケーションの構成は、からアプリケーションに渡されます。 docker-compose.yml ファイル。 データベース接続に関する構成は、 MONGODB_* で定義された変数 environment のセクション flask サービス。

すべてをテストするには、FlaskAPIを使用してやることメモを作成します。 あなたはこれを行うことができます POST へのカールリクエスト /todo ルート:

  1. curl -i -H "Content-Type: application/json" -X POST -d '{"todo": "Dockerize Flask application with MongoDB backend"}' http://your_server_ip/todo

このリクエストの結果、ステータスコードは次のようになります。 201 CREATED やること項目がMongoDBに保存されるとき:

Output
{"message":"To-do saved successfully!","status":true}

GETリクエストを使用して、MongoDBからのすべてのToDoノートを一覧表示できます。 /todo ルート:

  1. 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 rundocker-compose.yml このスタックをバージョン管理に入れ、必要に応じて更新できるため、作業が簡素化されます。

ここから、さらにPythonFrameworkチュートリアルを見ることができます。