Ubuntu 18.04でDockerを使用してFlaskアプリケーションをビルドおよびデプロイする方法

_著者は、https://www.brightfunds.org/funds/tech-education [Tech Education Fund]を選択して、https://do.co/w4do-cta [Write for DOnations]プログラムの一環として寄付を受け取りました。 _

前書き

Dockerは、管理者がコンテナを使用してアプリケーションを作成、管理、展開、および複製できるようにするオープンソースのアプリケーションです。 コンテナは、アプリケーションがオペレーティングシステムレベルで実行するために必要な依存関係を収容するパッケージと考えることができます。 つまり、Dockerを使用してデプロイされた各アプリケーションは独自の環境に存在し、要件は個別に処理されます。

Flaskは、https://www.python.org/ [Python]に基づいて構築されたWebマイクロフレームワークです。 特定のツールやプラグインを実行する必要がないため、マイクロフレームワークと呼ばれます。 Flaskフレームワークは軽量で柔軟ですが、高度に構造化されているため、他のフレームワークよりも優先されます。

Dockerを使用してFlaskアプリケーションをデプロイすると、最小限の再構成で異なるサーバー間でアプリケーションを複製できます。

このチュートリアルでは、Flaskアプリケーションを作成し、Dockerでデプロイします。 このチュートリアルでは、展開後にアプリケーションを更新する方法についても説明します。

前提条件

このチュートリアルを実行するには、次のものが必要です。

ステップ1-Flaskアプリケーションのセットアップ

開始するには、Flaskアプリケーションを保持するディレクトリ構造を作成します。 このチュートリアルでは、 `+ / var / www `に ` TestApp +`というディレクトリを作成しますが、コマンドを変更して好きな名前を付けることができます。

sudo mkdir /var/www/

新しく作成された `+ TestApp +`ディレクトリに移動します:

cd /var/www/

次に、Flaskアプリケーションの基本フォルダー構造を作成します。

sudo mkdir -p app/static app/templates

「+ -p 」フラグは、「 mkdir 」がディレクトリと存在しないすべての親ディレクトリを作成することを示します。 この場合、 ` mkdir `は ` static `および ` templates `ディレクトリを作成するプロセスで ` app +`親ディレクトリを作成します。

`+ app +`ディレクトリには、_views_や_blueprints_など、Flaskアプリケーションに関連するすべてのファイルが含まれます。 Viewsは、アプリケーションへのリクエストに応答するために記述するコードです。 Blueprintsアプリケーションコンポーネントを作成し、アプリケーション内または複数のアプリケーションで共通のパターンをサポートします。

`+ static `ディレクトリは、画像、CSS、JavaScriptファイルなどのアセットが存在する場所です。 ` templates +`ディレクトリは、プロジェクトのHTMLテンプレートを配置する場所です。

基本フォルダー構造が完成したので、Flaskアプリケーションの実行に必要なファイルを作成します。 最初に、 + app`ディレクトリ内に + init 。py`ファイルを作成します。 このファイルは、Pythonインタープリターに、「+ app +」ディレクトリがパッケージであり、そのように扱われるべきであることを伝えます。

次のコマンドを実行してファイルを作成します。

sudo nano app/__init__.py

Pythonのパッケージを使用すると、モジュールを論理的な名前空間または階層にグループ化できます。 このアプローチにより、コードを特定の機能を実行する個々の管理可能なブロックに分割できます。

次に、Flaskインスタンスを作成し、このファイルを保存した後に作成する `+ views.py `ファイルからロジックをインポートする ` init 。py +`にコードを追加します。 新しいファイルに次のコードを追加します。

/var/www/TestApp/init.py

from flask import Flask
app = Flask(__name__)
from app import views

そのコードを追加したら、ファイルを保存して閉じます。

`+ init 。py `ファイルを作成したら、 ` app `ディレクトリに ` views.py +`ファイルを作成する準備ができました。 このファイルには、ほとんどのアプリケーションロジックが含まれます。

sudo nano app/views.py

次に、コードを `+ views.py `ファイルに追加します。 このコードは、Webページにアクセスするユーザーに「 hello world!+」文字列を返します。

/var/www/TestApp/app/views.py

from app import app

@app.route('/')
def home():
  return "hello world!"

関数の上の `+ @ app.route `行は、http://flask.pocoo.org/docs/0.12/patterns/viewdecorators/ [decorator]と呼ばれます。 デコレータは、それに続く関数を変更します。 この場合、デコレーターはFlaskにどのURLが ` home()`関数をトリガーするかを伝えます。 ` home `関数によって返された ` hello world +`テキストは、ブラウザでユーザーに表示されます。

+ views.py`ファイルを配置したら、 + uwsgi.ini`ファイルを作成する準備ができました。 このファイルには、アプリケーションのhttps://uwsgi-docs.readthedocs.io [uWSGI]構成が含まれます。 uWSGIは、プロトコルとアプリケーションサーバーの両方であるNginxの展開オプションです。アプリケーションサーバーは、uWSGI、FastCGI、およびHTTPプロトコルを提供できます。

このファイルを作成するには、次のコマンドを実行します。

sudo nano uwsgi.ini

次に、次のコンテンツをファイルに追加して、uWSGIサーバーを構成します。

/var/www/TestApp/uwsgi.ini

[uwsgi]
module = main
callable = app
master = true

このコードは、Flaskアプリケーションが提供されるモジュールを定義します。 この場合、これは `+ main.py `ファイルで、ここでは ` main `として参照されます。 ` callable `オプションは、メインアプリケーションによってエクスポートされた ` app `インスタンスを使用するようにuWSGIに指示します。 ` master +`オプションを使用すると、アプリケーションを実行し続けることができるため、アプリケーション全体をリロードする場合でもダウンタイムはほとんどありません。

次に、アプリケーションへのエントリポイントである `+ main.py +`ファイルを作成します。 エントリポイントは、アプリケーションと対話する方法についてuWSGIに指示します。

sudo nano main.py

次に、以下をコピーしてファイルに貼り付けます。 これにより、以前に作成されたアプリケーションパッケージから「+ app +」という名前のFlaskインスタンスがインポートされます。

/var/www/TestApp/main.py

from app import app

最後に、 `+ requirements.txt `ファイルを作成して、 ` pip +`パッケージマネージャーがDockerデプロイメントにインストールする依存関係を指定します。

sudo nano requirements.txt

次の行を追加して、Flaskを依存関係として追加します。

/var/www/TestApp/app/requirements.txt

Flask==1.0.2

これは、インストールするFlaskのバージョンを指定します。 このチュートリアルを書いている時点では、 `+ 1.0.2 +`が最新のFlaskバージョンです。 Flaskの公式Webサイトで更新を確認できます。

ファイルを保存して閉じます。 Flaskアプリケーションのセットアップが正常に完了し、Dockerをセットアップする準備ができました。

ステップ2-Dockerのセットアップ

このステップでは、Dockerデプロイメントを作成するために、「+ Dockerfile 」と「 start.sh 」の2つのファイルを作成します。 ` Dockerfile `は、画像を組み立てるために使用されるコマンドを含むテキストドキュメントです。 ` start.sh `ファイルは、イメージを構築し、 ` Dockerfile +`からコンテナを作成するシェルスクリプトです。

最初に、 `+ Dockerfile`を作成します。

sudo nano Dockerfile

次に、希望の設定を `+ Dockerfile`に追加します。 これらのコマンドは、イメージの構築方法と、追加の要件を指定します。

/ var / www / TestApp / Dockerfile

FROM tiangolo/uwsgi-nginx-flask:
RUN apk --update add bash nano
ENV STATIC_URL /static
ENV STATIC_PATH /var/www/app/static
COPY ./requirements.txt /var/www/requirements.txt
RUN pip install -r /var/www/requirements.txt

この例では、Dockerイメージは既存のイメージ `+ tiangolo / uwsgi-nginx-flask +`から構築されます。これはhttps://hub.docker.com/r/tiangolo/uwsgi-nginx-flaskで見つけることができます[DockerHub]。 この特定のDockerイメージは、さまざまなPythonバージョンとOSイメージをサポートしているため、他のイメージよりも適切な選択です。

最初の2行は、アプリケーションを実行し、bashコマンドプロセッサと「+ nano 」テキストエディタをインストールするために使用する親イメージを指定します。 また、GitHub、GitLab、Bitbucketなどのバージョン管理ホスティングサービスをプルおよびプッシュするための ` git `クライアントもインストールします。 ` ENV STATIC_URL / static +`は、このDockerイメージに固有の環境変数です。 画像、CSSファイル、JavaScriptファイルなどのすべてのアセットが提供される静的フォルダーを定義します。

最後の2行は、 `+ requirements.txt `ファイルをコンテナーにコピーして実行できるようにし、 ` requirements.txt +`ファイルを解析して指定された依存関係をインストールします。

構成を追加したら、ファイルを保存して閉じます。

`+ Dockerfile `を配置したら、Dockerコンテナを構築する ` start.sh `スクリプトを作成する準備がほぼ整いました。 ` start.sh +`スクリプトを記述する前に、設定で使用するポートが開いていることを確認してください。 ポートが空いているかどうかを確認するには、次のコマンドを実行します。

sudo nc localhost  < /dev/null; echo $?

上記のコマンドの出力が「1」の場合、ポートは無料で使用可能です。 そうでない場合は、 `+ start.sh +`設定ファイルで使用する別のポートを選択する必要があります。

使用する開いているポートが見つかったら、 `+ start.sh +`スクリプトを作成します。

sudo nano start.sh

`+ start.sh `スクリプトは、 ` Dockerfile +`からイメージを構築し、結果のDockerイメージからコンテナを作成するシェルスクリプトです。 新しいファイルに構成を追加します。

/var/www/TestApp/start.sh

#!/bin/bash
app=""
docker build -t ${app} .
docker run -d -p :80 \
 --name=${app} \
 -v $PWD:/app ${app}

最初の行は_shebang_と呼ばれます。 これはbashファイルであり、コマンドとして実行されることを指定します。 次の行は、画像とコンテナに付けたい名前を指定し、 `+ app `という名前の変数として保存します。 次の行は、現在のディレクトリにある ` Dockerfile `からイメージを構築するようにDockerに指示します。 この例では、 ` docker.test +`というイメージが作成されます。

最後の3行は、ポート「567​​33」で公開される「+ docker.test 」という名前の新しいコンテナを作成します。 最後に、現在のディレクトリをコンテナの ` / var / www +`ディレクトリにリンクします。

コンテナをデーモンモードで、またはバックグラウンドプロセスとして起動するには、「-d +」フラグを使用します。 サーバーのポートをDockerコンテナの特定のポートにバインドするには、「-p 」フラグを含めます。 この場合、ポート ` 56733 `をDockerコンテナのポート ` 80 `にバインドしています。 ` -v `フラグは、コンテナにマウントするDockerボリュームを指定します。この場合、プロジェクトディレクトリ全体をDockerコンテナの ` / var / www +`フォルダにマウントしています。

`+ start.sh +`スクリプトを実行してDockerイメージを作成し、結果のイメージからコンテナーを構築します。

sudo bash start.sh

スクリプトの実行が終了したら、次のコマンドを使用して、実行中のすべてのコンテナーを一覧表示します。

sudo docker ps

コンテナを示す出力を受け取ります:

OutputCONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
58b05508f4dd        docker.test         "/entrypoint.sh /sta…"   12 seconds ago      Up 3 seconds       443/tcp, 0.0.0.0:56733->80/tcp   docker.test

+ docker.test`コンテナが実行されていることがわかります。 実行されたので、ブラウザで指定されたポートのIPアドレスにアクセスします: `+ http://:+

次のようなページが表示されます。

image:https://assets.digitalocean.com/articles/CART-62081/HelloWorld.png [ホームページ]

このステップでは、FlaskアプリケーションをDockerに正常にデプロイしました。 次に、テンプレートを使用してユーザーにコンテンツを表示します。

ステップ3-テンプレートファイルの提供

http://flask.pocoo.org/docs/1.0/tutorial/templates/ [テンプレート]は、アプリケーションにアクセスしたユーザーに静的および動的コンテンツを表示するファイルです。 このステップでは、HTMLテンプレートを作成して、アプリケーションのホームページを作成します。

+ app / templates`ディレクトリに + home.html`ファイルを作成することから始めます:

sudo nano app/templates/home.html

テンプレートのコードを追加します。 このコードは、タイトルとテキストを含むHTML5ページを作成します。

/var/www/TestApp/app/templates/home.html

<!doctype html>

<html lang="en-us">
 <head>
   <meta charset="utf-8">
   <meta http-equiv="x-ua-compatible" content="ie=edge">
   <title>Welcome home</title>
 </head>

 <body>
   <h1>Home Page</h1>
   <p>This is the home page of our application.</p>
 </body>
</html>

テンプレートを追加したら、ファイルを保存して閉じます。

次に、 `+ app / views.py +`ファイルを変更して、新しく作成されたファイルを提供します。

sudo nano app/views.py

まず、ファイルの先頭に次の行を追加して、Flaskから `+ render_template +`メソッドをインポートします。 このメソッドは、HTMLファイルを解析してWebページをユーザーに表示します。

/var/www/TestApp/app/views.py

from flask import render_template
...

ファイルの最後に、テンプレートファイルをレンダリングするための新しいルートも追加します。 このコードは、ユーザーがアプリケーションの + / template a`ルートにアクセスするたびに、 + home.html`ファイルのコンテンツが提供されることを指定します。

/var/www/TestApp/app/views.py

...

@app.route('/template')
def template():
   return render_template('home.html')

更新された `+ app / views.py +`ファイルは次のようになります。

/var/www/TestApp/app/views.py

from flask import render_template
from app import app

@app.route('/')
def home():
   return "Hello world!"

@app.route('/template')
def template():
   return render_template('home.html')

完了したら、ファイルを保存して閉じます。

これらの変更を有効にするには、Dockerコンテナーを停止して再起動する必要があります。 次のコマンドを実行して、コンテナを再構築します。

sudo docker stop  && sudo docker start

`+ http://:56733 / template +`にあるアプリケーションにアクセスして、提供されている新しいテンプレートを確認します。

画像:https://assets.digitalocean.com/articles/CART-62081/HomePage.png [ホームページ]

これで、アプリケーションの訪問者にサービスを提供するDockerテンプレートファイルを作成しました。 次のステップでは、Dockerコンテナを再起動せずに、アプリケーションに加えた変更を有効にする方法を確認します。

ステップ4-アプリケーションの更新

新しい要件のインストール、Dockerコンテナの更新、HTMLおよびロジックの変更など、アプリケーションに変更を加える必要がある場合があります。 このセクションでは、Dockerコンテナを再起動せずにこれらの変更を行うように「+ touch-reload +」を設定します。

Python _autoreloading_は、ファイルシステム全体の変更を監視し、変更を検出するとアプリケーションを更新します。 自動リロードは非常に迅速にリソースを消費する可能性があるため、本番環境では推奨されません。 このステップでは、 `+ touch-reload +`を使用して特定のファイルへの変更を監視し、ファイルが更新または置換されたときにリロードします。

これを実装するには、 `+ uwsgi.ini +`ファイルを開くことから始めます:

sudo nano uwsgi.ini

次に、強調表示された行をファイルの最後に追加します。

/var/www/TestApp/uwsgi.ini

module = main
callable = app
master = true

これは、アプリケーション全体のリロードをトリガーするために変更されるファイルを指定します。 変更を行ったら、ファイルを保存して閉じます。

これを実証するには、アプリケーションに小さな変更を加えます。 まず、 `+ app / views.py +`ファイルを開いてください:

sudo nano app/views.py

`+ home +`関数によって返された文字列を置き換えます:

/var/www/TestApp/app/views.py

from flask import render_template
from app import app

@app.route('/')
def home():
   return ""

@app.route('/template')
def template():
   return render_template('home.html')

変更を行った後、ファイルを保存して閉じます。

次に、アプリケーションのホームページを「+ http://:」で開くと、変更が反映されていないことがわかります。 これは、リロードの条件が ` uwsgi.ini `ファイルの変更であるためです。 アプリケーションをリロードするには、 ` touch +`を使用して条件を有効にします:

sudo touch uwsgi.ini

ブラウザでアプリケーションのホームページを再度リロードします。 アプリケーションに変更が組み込まれていることがわかります。

image:https://assets.digitalocean.com/articles/CART-62081/ThereHasBeenAChange.png [ホームページ更新]

このステップでは、 `+ touch-reload +`条件を設定して、変更後にアプリケーションを更新します。

結論

このチュートリアルでは、Flaskアプリケーションを作成してDockerコンテナにデプロイしました。 また、コンテナを再起動することなくアプリケーションを更新するように「+ touch-reload +」を設定しました。

Dockerで新しいアプリケーションを使用すると、簡単に拡張できます。 Dockerの使用方法の詳細については、https://docs.docker.com/ [公式ドキュメント]をご覧ください。

Related