Docker学習 - python+FlaskでWebアプリを開発してDockerイメージを作成しよう
docker hubで公開されているオフィシャルのDockerイメージを取得(docker pull)して実行(docker run)する方法については、以下の2つの記事で紹介してきました。
今回は、pythonの軽量なWebフレームワークであるFlaskを使った簡単なWebアプリケーションを開発して、Dockerイメージを作成して実行してみましょう。
最初からpython+FlaskでプログラミングしDockerイメージを作成してもよいのですが、今回はまず、ローカル環境で動作するpython+FlaskのWebアプリケーションを作成してからDockerイメージを作成するという手順で進めていきます。
大まかな流れとしては次のように進めます。
- ローカル環境にpython+Flask環境を構築
- 簡単なWebアプリケーション開発
- ローカル環境で実行しブラウザから確認
- Dockerfileを作成
- docker buildコマンドでDockerイメージ作成
- 作成したDockerイメージをdocker runコマンドで実行
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を表示する
ブラウザで以下のアドレスにアクセスしてみて下さい。
作成したindex.htmlが表示されればOKです。
hello.htmlを表示する
ブラウザで以下のアドレスにアクセスしてみて下さい。
「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 -