Ubuntu20.04でDockerを使用してFlaskアプリケーションを構築およびデプロイする方法
著者は、 Write forDOnationsプログラムの一環として寄付を受け取るためにTechEducationFundを選択しました。
序章
Docker は、管理者がコンテナーを使用してアプリケーションを作成、管理、デプロイ、および複製できるようにするオープンソースアプリケーションです。 コンテナは、アプリケーションがオペレーティングシステムレベルで実行するために必要な依存関係を格納するパッケージと考えることができます。 これは、Dockerを使用してデプロイされた各アプリケーションが独自の環境に存在し、その要件が個別に処理されることを意味します。
Flask は、Python上に構築されたWebマイクロフレームワークです。 実行に特定のツールやプラグインを必要としないため、マイクロフレームワークと呼ばれます。 Flaskフレームワークは軽量で柔軟性がありますが、高度に構造化されているため、Pythonで記述された小さなWebアプリで特に人気があります。
Dockerを使用してFlaskアプリケーションをデプロイすると、最小限の再構成で異なるサーバー間でアプリケーションを複製できます。
このチュートリアルでは、Flaskアプリケーションを作成し、Dockerを使用してデプロイします。 このチュートリアルでは、展開後にアプリケーションを更新する方法についても説明します。
前提条件
このチュートリアルに従うには、次のものが必要です。
- Ubuntu 20.04を使用したサーバーの初期設定ガイドに従って構成された、sudo権限を持つroot以外のユーザー。
- Dockerがインストールされた1台のUbuntu20.04サーバー。このチュートリアルに従ってセットアップします。
- Nginx は、 Ubuntu20.04チュートリアルにNginxをインストールする方法のステップ1に従ってインストールされます。
ステップ1—Flaskアプリケーションのセットアップ
開始するには、Flaskアプリケーションを保持するディレクトリ構造を作成します。 このチュートリアルでは、というディレクトリを作成します TestApp
の /var/www
、ただし、コマンドを変更して、好きな名前を付けることができます。
- sudo mkdir /var/www/TestApp
新しく作成されたものに移動します TestApp
ディレクトリ:
- cd /var/www/TestApp
次に、Flaskアプリケーションの基本フォルダー構造を作成します。
- sudo mkdir -p app/static app/templates
The -p
フラグは mkdir
ディレクトリと存在しないすべての親ディレクトリを作成します。 この場合、 mkdir
を作成します app
作成中の親ディレクトリ static
と templates
ディレクトリ。
The app
ディレクトリには、ビューやブループリントなど、Flaskアプリケーションに関連するすべてのファイルが含まれます。 Views は、アプリケーションへの要求に応答するために作成するコードです。 ブループリントは、アプリケーションコンポーネントを作成し、アプリケーション内または複数のアプリケーション間で共通のパターンをサポートします。
The static
ディレクトリは、画像、CSS、JavaScriptファイルなどのアセットが存在する場所です。 The templates
ディレクトリは、プロジェクトのHTMLテンプレートを配置する場所です。
基本フォルダー構造が完成したので、Flaskアプリケーションの実行に必要なファイルを作成する必要があります。 まず、作成します __init__.py
内部のファイル app
nanoまたは選択したテキストエディタを使用したディレクトリ。 このファイルは、Pythonインタープリターに次のことを伝えます。 app
ディレクトリはパッケージであり、そのように扱う必要があります。
次のコマンドを実行してファイルを作成します。
- sudo nano app/__init__.py
Pythonのパッケージを使用すると、モジュールを論理的な名前空間または階層にグループ化できます。 このアプローチにより、コードを特定の機能を実行する個別の管理可能なブロックに分割できます。
次に、にコードを追加します __init__.py
これにより、Flaskインスタンスが作成され、からロジックがインポートされます。 views.py
このファイルを保存した後に作成するファイル。 次のコードを新しいファイルに追加します。
from flask import Flask
app = Flask(__name__)
from app import views
そのコードを追加したら、ファイルを保存して閉じます。 を押すと、ファイルを保存して閉じることができます Ctrl+X,
次に、プロンプトが表示されたら、 Y
と Enter
.
とともに __init__.py
ファイルが作成されたら、作成する準備ができました views.py
あなたのファイル app
ディレクトリ。 このファイルには、ほとんどのアプリケーションロジックが含まれています。
- sudo nano app/views.py
次に、コードを views.py
ファイル。 このコードは hello world!
Webページにアクセスするユーザーへの文字列:
from app import app
@app.route('/')
def home():
return "hello world!"
The @app.route
関数の上の行は、デコレータと呼ばれます。 デコレータは、Flaskで広く使用されているPython言語の規則です。 それらの目的は、それらの直後の関数を変更することです。 この場合、デコレータはどのURLがトリガーするかをFlaskに通知します home()
関数。 The hello world
によって返されるテキスト home
機能はブラウザ上でユーザーに表示されます。
とともに views.py
ファイルを配置すると、作成する準備が整います。 uwsgi.ini
ファイル。 このファイルには、アプリケーションのuWSGI構成が含まれます。 uWSGIは、プロトコルとアプリケーションサーバーの両方であるNginxの展開オプションです。 アプリケーションサーバーは、uWSGI、FastCGI、およびHTTPプロトコルを提供できます。
このファイルを作成するには、次のコマンドを実行します。
- sudo nano uwsgi.ini
次に、次のコンテンツをファイルに追加して、uWSGIサーバーを構成します。
[uwsgi]
module = main
callable = app
master = true
このコードは、Flaskアプリケーションが提供されるモジュールを定義します。 この場合、これは main.py
ここで参照されるファイル main
. The callable
オプションは、uWSGIに使用するように指示します app
メインアプリケーションによってエクスポートされたインスタンス。 The master
オプションを使用すると、アプリケーションを実行し続けることができるため、アプリケーション全体をリロードする場合でもダウンタイムはほとんどありません。
次に、を作成します main.py
アプリケーションへのエントリポイントであるファイル。 エントリポイントは、アプリケーションとの対話方法についてuWSGIに指示します。
- sudo nano main.py
次に、以下をコピーしてファイルに貼り付けます。 これにより、Flaskインスタンスという名前がインポートされます app
以前に作成されたアプリケーションパッケージから。
from app import app
最後に、 requirements.txt
依存関係を指定するファイル pip
パッケージマネージャーがDockerデプロイメントにインストールされます。
- sudo nano requirements.txt
次の行を追加して、Flaskを依存関係として追加します。
Flask>=2.0.2
インストールするFlaskのバージョンを指定します。 このチュートリアルを書いている時点では、2.0.2が最新のFlaskバージョンであり、 >=2.0.2
バージョン2.0.2以降を確実に入手できます。 このチュートリアルでは基本的なテストアプリを作成しているため、Flaskの将来の更新によって構文が古くなる可能性は低くなりますが、安全でありながらマイナーな更新を受け取りたい場合は、そうでないことを指定できます。次のようなものを指定して、将来のメジャーバージョンをインストールしたい Flask>=2.0.2,<3.0
. 更新を確認するには、 Flask の公式Webサイト、またはFlaskライブラリのPythonPackageIndexのランディングページを参照してください。
ファイルを保存して閉じます。 これでFlaskアプリケーションが正常にセットアップされ、Dockerをセットアップする準備が整いました。
ステップ2—Dockerをセットアップする
このステップでは、2つのファイルを作成します。 Dockerfile
と start.sh
、Dockerデプロイメントを作成します。 The Dockerfile
画像の組み立てに使用されるコマンドを含むテキストドキュメントです。 The start.sh
fileは、イメージを構築し、そこからコンテナを作成するシェルスクリプトです。 Dockerfile
.
まず、を作成します Dockerfile
.
- sudo nano Dockerfile
次に、必要な構成をに追加します Dockerfile
. これらのコマンドは、イメージの構築方法と、含まれる追加の要件を指定します。
FROM tiangolo/uwsgi-nginx-flask:python3.8-alpine
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
、DockerHubにあります。 この特定のDockerイメージは、さまざまなPythonバージョンとOSイメージをサポートしているため、他のイメージよりも優れています。
最初の2行は、アプリケーションの実行とbashコマンドプロセッサのインストールに使用する親イメージを指定します。 nano
テキストエディタ。 また、をインストールします git
GitHub、GitLab、Bitbucketなどのバージョン管理ホスティングサービスにプルおよびプッシュするためのクライアント。 ENV STATIC_URL /static
このDockerイメージに固有の環境変数です。 画像、CSSファイル、JavaScriptファイルなどのすべてのアセットが提供される静的フォルダーを定義します。
最後の2行は requirements.txt
ファイルをコンテナに入れて実行できるようにしてから、 requirements.txt
指定された依存関係をインストールするファイル。
構成を追加したら、ファイルを保存して閉じます。
あなたと Dockerfile
所定の位置に、あなたはあなたの書く準備がほぼできています start.sh
Dockerコンテナをビルドするスクリプト。 書く前に start.sh
スクリプトでは、最初に、構成で使用するポートが開いていることを確認してください。 ポートが空いているかどうかを確認するには、次のコマンドを実行します。
- sudo nc localhost 56733 < /dev/null; echo $?
上記のコマンドの出力が 1
、その後、ポートは空いていて使用可能です。 それ以外の場合は、で使用する別のポートを選択する必要があります start.sh
構成ファイル。
使用する開いているポートを見つけたら、 start.sh
脚本:
sudo nano start.sh
The start.sh
スクリプトは、からイメージを構築するシェルスクリプトです。 Dockerfile
結果のDockerイメージからコンテナーを作成します。 新しいファイルに構成を追加します。
#!/bin/bash
app="docker.test"
docker build -t ${app} .
docker run -d -p 56733:80 \
--name=${app} \
-v $PWD:/app ${app}
最初の行はシバンと呼ばれます。 これがbashファイルであり、コマンドとして実行されることを指定します。 次の行は、画像とコンテナに付ける名前を指定し、名前の付いた変数として保存します app
. 次の行は、Dockerにイメージをビルドするように指示します Dockerfile
現在のディレクトリにあります。 これにより、という画像が作成されます docker.test
この例では。
最後の3行は、という名前の新しいコンテナを作成します docker.test
それは港で公開されています 56733
. 最後に、現在のディレクトリをにリンクします /var/www
コンテナのディレクトリ。
あなたは -d
デーモンモードで、またはバックグラウンドプロセスとしてコンテナを開始するためのフラグ。 あなたは -p
サーバー上のポートをDockerコンテナの特定のポートにバインドするためのフラグ。 この場合、ポートをバインドしています 56733
ポートへ 80
Dockerコンテナ上。 The -v
flagは、コンテナにマウントするDockerボリュームを指定します。この場合、プロジェクトディレクトリ全体をにマウントします。 /var/www
Dockerコンテナのフォルダ。
構成を追加したら、ファイルを保存して閉じます。
を実行します 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://ip-address:56733
次のようなページが表示されます。
このステップでは、FlaskアプリケーションをDockerに正常にデプロイしました。 次に、テンプレートを使用してコンテンツをユーザーに表示します。
ステップ3—テンプレートファイルを提供する
テンプレートは、アプリケーションにアクセスするユーザーに静的および動的コンテンツを表示するファイルです。 このステップでは、アプリケーションのホームページを作成するためのHTMLテンプレートを作成します。
作成することから始めます home.html
のファイル app/templates
ディレクトリ:
- sudo nano app/templates/home.html
テンプレートのコードを追加します。 このコードは、タイトルといくつかのテキストを含むHTML5ページを作成します。
<!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
まず、ファイルの先頭に次の行を追加して、 render_template
フラスコからの方法。 このメソッドは、HTMLファイルを解析して、ユーザーにWebページをレンダリングします。
from flask import render_template
...
ファイルの最後に、テンプレートファイルをレンダリングするための新しいルートも追加します。 このコードは、ユーザーにコンテンツが提供されることを指定します home.html
彼らが訪問するたびにファイル /template
アプリケーションでルーティングします。
...
@app.route('/template')
def template():
return render_template('home.html')
更新された 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 docker.test && sudo docker start docker.test
次のアプリケーションにアクセスしてください http://your-ip-address:56733/template
提供されている新しいテンプレートを確認します。
これで、アプリケーションの訪問者にサービスを提供するDockerテンプレートファイルを作成しました。 次のステップでは、Dockerコンテナを再起動しなくても、アプリケーションに加えた変更をどのように有効にできるかを確認します。
ステップ4—アプリケーションを更新する
新しい要件のインストール、Dockerコンテナーの更新、HTMLとロジックの変更など、アプリケーションに変更を加える必要がある場合があります。 このセクションでは、構成します touch-reload
Dockerコンテナを再起動せずにこれらの変更を行うため。
Python autoreloading は、ファイルシステム全体の変更を監視し、変更を検出するとアプリケーションを更新します。 自動リロードは、リソースをすぐに消費する可能性があるため、本番環境では推奨されません。 このステップでは、 touch-reload
特定のファイルへの変更を監視し、ファイルが更新または置換されたときにリロードします。
これを実装するには、まず uwsgi.ini
ファイル:
- sudo nano uwsgi.ini
次に、強調表示された行をファイルの最後に追加します。
module = main
callable = app
master = true
touch-reload = /app/uwsgi.ini
これは、アプリケーション全体のリロードをトリガーするように変更されるファイルを指定します。 変更を加えたら、ファイルを保存して閉じます。
これを実証するために、アプリケーションに小さな変更を加えます。 あなたのを開くことから始めます app/views.py
ファイル:
- sudo nano app/views.py
によって返された文字列を置き換えます home
関数:
from flask import render_template
from app import app
@app.route('/')
def home():
return "<b>There has been a change</b>"
@app.route('/template')
def template():
return render_template('home.html')
変更を加えたら、ファイルを保存して閉じます。
次に、アプリケーションのホームページを開いた場合 http://ip-address:56733
、変更が反映されていないことに気付くでしょう。 これは、リロードの条件が uwsgi.ini
ファイル。 アプリケーションをリロードするには、 touch
条件をアクティブにするには:
- sudo touch uwsgi.ini
アプリケーションのホームページをブラウザに再度ロードします。 アプリケーションに変更が組み込まれていることがわかります。
このステップでは、 touch-reload
変更を加えた後にアプリケーションを更新するための条件。
結論
このチュートリアルでは、Flaskアプリケーションを作成してDockerコンテナーにデプロイしました。 また、構成しました touch-reload
コンテナを再起動せずにアプリケーションを更新します。
Docker上の新しいアプリケーションを使用すると、簡単にスケーリングできるようになります。 Dockerの使用の詳細については、Dockerの公式ドキュメントを確認してください。