Docker学習 - python+FlaskでWebアプリを開発してDockerイメージを作成しよう

2020年2月23日Docker,Flask

docker hubで公開されているオフィシャルのDockerイメージを取得(docker pull)して実行(docker run)する方法については、以下の2つの記事で紹介してきました。

今回は、pythonの軽量なWebフレームワークであるFlaskを使った簡単なWebアプリケーションを開発して、Dockerイメージを作成して実行してみましょう。

最初からpython+FlaskでプログラミングしDockerイメージを作成してもよいのですが、今回はまず、ローカル環境で動作するpython+FlaskのWebアプリケーションを作成してからDockerイメージを作成するという手順で進めていきます。

大まかな流れとしては次のように進めます。

  1. ローカル環境にpython+Flask環境を構築
  2. 簡単なWebアプリケーション開発
  3. ローカル環境で実行しブラウザから確認
  4. Dockerfileを作成
  5. docker buildコマンドでDockerイメージ作成
  6. 作成したDockerイメージをdocker runコマンドで実行
Dockerイメージだけを作成したい方

Dockerイメージの作成だけでよい。
ローカル環境にpythonインストールしたくない。
という方は1番目と3番目のローカル環境の作業はスキップしてください。

ローカル環境はUbuntu18.04+Docker17.12です。

ローカル環境にpython+Flask環境を構築

以下のコマンドを順番に実行して、python3、pip3、Flaskをインストールしましょう。

# pythonインストール
sudo apt install python3

# pipインストール
sudo apt install python3-pip

# Flaskインストール
sudo pip3 install Flask

環境によってはpythonやpipの実行がpython3やpip3になっています。

気になる方は、.bashrcファイルにaliasコマンドを追加しておきましょう。

alias python=python3
alias pip=pip3

pythonがインストールされているか以下のコマンドを実行しましょう。

$ python --version
Python 3.6.9

このようにバージョンが表示されればOKです。

python+Flaskで簡単なWebアプリケーションを作成する

今回作成するWebアプリケーションの構成を説明します。

docker_demo_flaskディレクトリ

まず、適当な名前のディレクトリを作成してください。

説明は「docker_demo_flask」として進めます。

 

app.py

Webアプリケーションのメインファイルです。

内容はFlaskを利用したpythonプログラムで、2つの機能を作成していきます。

  • http://localhost:8000/にアクセスしたらトップページ用のファイルを表示する
  • http://localhost:8000/<○○>にアクセスしたら「Hello ○○さん。」と表示する
from flask import Flask, render_template

app = Flask(__name__)

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

@app.route('/<name>')
def hello(name):
    return render_template('hello.html', title='呼び出し側でタイトル設定', name=name)

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=8000)
注意

ファイルはUTF-8で作成してください。

1行目:Flaskを利用するのでインポートします。

3行目:Flaskのインスタンスを生成します。

 

■1つ目の機能

5~6行目:@app.route('/’)つまり「http://localhost:8000/」にアクセスしたら「index()を実行する」という意味です。

7行目:「index.html」の内容をそのまま表示します。

 

■2つ目の機能

9~10行目:@app.route('/<name>’)つまり「http://localhost:8000/○○」にアクセスしたら「hello(name)を実行する」という意味です。

11行目:「hello.html」ファイルにパラメータとして2つを渡しています。

  title→「呼び出し側でタイトル設定」という固定の文字列

  name→URLで指定された○○の部分の文字列

 

14行目:8000番ポートでアクセスを待ち受けるようにして実行します。

index.html

「http://localhost:8000/」にアクセスすると呼び出されるHTMLファイルです。

単純な静的HTMLを準備してください。例えば以下のようなもので大丈夫です。

<html>
<title>docker demo flask</title>
<head></head>
<body>
トップページです。
</body>
</html>

hello.html

「http://localhost:8000/○○」にアクセスすると呼び出されるHTMLファイルです。

index.htmlファイルとの違いは、「title」と「name」が動的に設定されるところです。

<html>
<head>
<title>{{ title }}</title>
</head>
<body>
Hello
{{ name }}さん。
</body>
</html>

3行目:{{ title }}はパラメータ「title」で指定された「呼び出し側でタイトル設定」という文字列が当てはめられます。

7行目:{{ name }}はパラメータ「name」で指定された「○○」の部分の文字列が当てはめられます。

ローカル環境で実行しブラウザから確認

作成したプログラムを実行してみましょう。

app.pyがあるディレクトリに移動し「python app.py」と実行してください。

$ python app.py
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:8000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 705-315-274

「Running on http://0.0.0.0:8000/」と表示されていることを確認し、ブラウザで表示してみましょう。

index.htmlを表示する

ブラウザで以下のアドレスにアクセスしてみて下さい。

http://localhost:8000/

作成したindex.htmlが表示されればOKです。

 

hello.htmlを表示する

ブラウザで以下のアドレスにアクセスしてみて下さい。

http://localhost:8000/snow

「snow」の部分はどんな文字列でもOKです。

「Hello ○○さん。」と表示されればOKです。

 

Webアプリケーションの開発完了

これで、python+Flaskの簡単なWebアプリケーションが完成しました。

では、いよいよ、このWebアプリケーションのDockerイメージを作成しましょう。

Dockerfileを作成

Dockerイメージを作成するためには「docker build」コマンドを実行するのですが、buildする際にDockerfileが利用されます。

Dockerfileは、Dockerイメージを作成するための設計書と思っていただければ大丈夫です。

今回のWebアプリケーションのDockerイメージを作成するためのDockerfileはこうなります。

# python 3.6 をベースにDockerイメージを作成
FROM python:3.6

# 作業ディレクトリを指定
WORKDIR /app

# カレントディレクトリのファイルをDockerコンテナの「/app」 ディレクトリにコピー
ADD . /app

# Flaskをインストール
RUN pip install Flask

# 外部に公開するポートを指定
EXPOSE 8000

# コンテナの実行コマンドを指定
CMD ["python", "app.py"]

各コマンドの詳細な説明は別の機会に紹介しますので、ソース内のコメントのレベルで理解してください。

docker buildコマンドでDockerイメージ作成

Dockerfileが作成できたら、Dockerイメージを作成しましょう。

Dockerfileのあるディレクトリに移動して、「docker build -t docker_demo_flask .」と実行しましょう。

$ docker build -t docker_demo_flask .
:
:
:
Successfully built 6055b6fdf511
Successfully tagged docker_demo_flask:latest

「Successfully tagged docker_demo_flask:latest」と表示されればOKです。

Dockerイメージが作成できているか確認してみましょう。

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker_demo_flask   latest              6055b6fdf511        2 minutes ago       923MB
python              3.6                 971c66f6a27f        2 weeks ago         914MB

「docker_demo_flask」が作成されていますね。

また「python」のバージョン3.6のDockerイメージも取得できていることがわかりますね。

これで、作成したWebアプリケーションのDockerイメージが作成できました。

作成したDockerイメージをdocker runコマンドで実行

Dockerイメージを「docker run」コマンドで実行してみましょう。

$ docker run -d -p 8000:8000 docker_demo_flask
1a8aba51d0b40e56c92db5c52e71322264abdef6a2731003226ca431fd468416

docker runの「-d」オプションはバックグランド実行で、「-p」はコンテナとローカルのポートの関連付けです。

ブラウザから確認するとローカル環境で実行した場合と同じ結果になっているはずです。

docker container lsコマンドで実行状態を確認しても、8000ポートで実行中になっていますね。

snow:$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
1a8aba51d0b4        docker_demo_flask   "python app.py"     9 seconds ago       Up 8 seconds        0.0.0.0:8000->8000/tcp   tender_shirley

また、docker logs コマンドで実行中のコンテナのログを確認するとWebアクセスのログが表示されていますね。

$ docker logs 1a
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:8000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 293-451-995
172.17.0.1 - - [23/Feb/2020 09:45:21] "GET / HTTP/1.1" 200 -
172.17.0.1 - - [23/Feb/2020 09:45:22] "GET /favicon.ico HTTP/1.1" 200 -
172.17.0.1 - - [23/Feb/2020 09:45:25] "GET /snows HTTP/1.1" 200 -
172.17.0.1 - - [23/Feb/2020 09:45:25] "GET /favicon.ico HTTP/1.1" 200 -

Docker,Flask

Posted by snow