はじめに
「優しいIT」という理念の基、ITコンサルタントをしている亀井亮介と申します!
主な仕事は要求分析・要件定義の上流工程から、開発のマネジメントまでしていますが、プライベートでウェブシステム開発をしています!
目的
細かい説明は抜きにして、Git cloneし、"docker-compose up -d"するだけで、Python3, Flask, MySQL開発環境を構築します!
Dockerをインストールしていることが、前提となります!
「とりあえず動くところが見たい!」というせっかちな(私のような)方は、「1. 動作するまでの手順」を見てくださいね!
2章以降は、各項目の説明をしています!
Githubにファイルを上げているので、興味のある方は使ってくださいね!
目次
- 動作するまでの手順
- Dockerfile
- docker-compose.yml
- Flask(mysql-connector-python)
- Jinja2 テンプレートエンジン
- ローカルでファイル操作し、コンテナに即時反映
1. 動作するまでの手順
1-1. Git cloneする
Gitが使えることが前提です。
$ git clone git@github.com:RyosukeKamei/python-flask-mysql.git
$ cd python-flask-mysql
1-2. docker-compose up -d
docker-composeを使い、データコンテナ、データベースコンテナ、アプリケーションコンテナを立ち上げます。
アプリケーションコンテナは、Dockerfileを使いビルドしてから、コンテナの起動をします。
$ docker-compose up -d
※アプリケーションコンテナをビルドするのに時間がかかります。
1-3. 動作確認
http://{IPアドレス}:5000/hello
にアクセスします。
IPアドレスは環境によって異なるかもしれません。私の環境では、Dockerのデフォルトで"192.168.99.100"です。
Flaskのデフォルトのポート番号は5000番です。
MySQLに登録したデータをそのまま表示しています。
テンプレートエンジンにJinja2を利用しています!
2. Dockerfile
Dockerfileを使いアプリケーションコンテナをビルドします。
2-1. Dockerfile全体
# Pythonは公式イメージ
FROM python:3.5.2
# オリジナルはJoshua Conner氏
# MAINTAINER Joshua Conner <joshua.conner@gmail.com>
MAINTAINER Ryosuke Kamei <sr2smail@gmail.com>
# 各ライブラリインストール
# Pythonがパッケージ依存するものもインストール
# Pythonプロフェッショナルプログラミング第2版P9より
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y vim \
sudo \
python3-dev \
zlib1g-dev \
libsqlite3-dev \
libreadline6-dev \
libgdbm-dev \
libbz2-dev \
tk-dev
# ユーザ作成
RUN groupadd web
RUN useradd -d /home/python -m python
# pipでインストール
# virtualenv Pythonの仮想環境構築コマンド
# flake8 コーディングスタイル/シンタックスのチェック
# ipython Pythonのインタラクティブモード拡張
# Flask Pytrhonの軽量フレームワーク
RUN pip install virtualenv \
ipython \
flake8 \
Flask
# MySQLドライバ"mysql-connector-python"をインストール
# pipのを使うとうまくいかない。
# git cloneしてビルド、インストール
RUN git clone https://github.com/mysql/mysql-connector-python.git
WORKDIR mysql-connector-python
RUN python ./setup.py build
RUN python ./setup.py install
# ユーザを変更
USER python
# vim の設定ファイル
ADD ./vim/.vimrc /home/python/
WORKDIR /home/python
RUN mkdir /home/python/.vim
RUN mkdir /home/python/.vim/ftplugin
ADD ./vim/python.vim /home/python/.vim/ftplugin/
RUN mkdir /home/python/.vim/bundle
RUN git clone https://github.com/Shougo/neobundle.vim /home/python/.vim/bundle/neobundle.vim
# Flaskの場合
# ポートを解放(Flaskのデフォルトのポート番号:5000)
EXPOSE 5000
# サーバ起動
ENTRYPOINT ["/usr/local/bin/python", "/home/python/flask_sample.py"]
# フレームワークを指定しない時や、サーバにログインしてから実行したい場合
# ENTRYPOINT ["/usr/bin/tail", "-f", "/dev/null"]
2-2. 元のイメージを指定 FROM
元となるイメージは公式イメージのpython:3.5.2です。
FROM python:3.5.2
2-3. 作成者情報 MAINTAINER
誰が作ったかを記載します。筆者の情報です。
MAINTAINER Ryosuke Kamei <sr2smail@gmail.com>
2-4. 必要なライブラリのインストール
ライブラリをインストールする前に、既存ライブラリをアッデート・アップグレードします。インストールする前のおまじないと思ってください。
その後、必要なライブラリをインストールします。
vimやsudoもよく使うのでインストールします。
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y vim \
sudo \
python3-dev \
zlib1g-dev \
libsqlite3-dev \
libreadline6-dev \
libgdbm-dev \
libbz2-dev \
tk-dev
2-5. サーバのユーザを作成
サーバのユーザを作成します。
ユーザ名は"python"にしています。ここはお好みで変えてください。
変更する場合、後述のフォルダ名なども変更する必要があります。
RUN groupadd web
RUN useradd -d /home/python -m python
2-6. Python開発で必要なライブラリをpipでインストール
Pythonのパッケージマネージャpipで必要なライブラリをインストールします。
- virtualenv Pythonの仮想環境構築コマンド
- flake8 コーディングスタイル/シンタックスのチェック
- ipython Pythonのインタラクティブモード拡張
- Flask Pythonの軽量フレームワーク
RUN pip install virtualenv \
ipython \
flake8 \
Flask
MySQLと接続するドライバは"mysql-connector-python"を利用します。
pipでインストールできるはずが、上手くいかない(2016年9月23日現在)ので、gitクローンして、ビルドし、インストールします。
RUN git clone https://github.com/mysql/mysql-connector-python.git
WORKDIR mysql-connector-python
RUN python ./setup.py build
RUN python ./setup.py install
2-7. vimの設定ファイル
vimを使いPythonのファイルを操作する際に、便利な設定をしておきます。
深くは説明しません。
ADD ./vim/.vimrc /home/python/
WORKDIR /home/python
RUN mkdir /home/python/.vim
RUN mkdir /home/python/.vim/ftplugin
ADD ./vim/python.vim /home/python/.vim/ftplugin/
RUN mkdir /home/python/.vim/bundle
RUN git clone https://github.com/Shougo/neobundle.vim /home/python/.vim/bundle/neobundle.vim
2-8. Flaskのサンプルファイルを起動
Flaskのデフォルトのポートは"5000"なので開放します。
サンプルファイルを起動します。
サンプルのファイル"flask_sample.py"は3.で説明する"docker-compose.yml"ファイルで同期を取っています。
このファイルを実行すると、サーバが起動するので、"docker-compose up -d"実行後に、即動作を確認できます!
EXPOSE 5000
ENTRYPOINT ["/usr/local/bin/python", "/home/python/flask_sample.py"]
3. docker-compose.yml
3-1. docker-compose.yml全体
data:
container_name: python-flask-data
image: busybox
stdin_open: true
tty: false
volumes:
- ./docker/mysql:/etc/mysql/conf.d:ro
- ./app:/home/python
command: /bin/sh
mysql:
container_name: python-flask-db
image: mysql
volumes:
- ./initdb.d:/docker-entrypoint-initdb.d
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_USER: python
MYSQL_PASSWORD: python
MYSQL_DATABASE: sample
ports:
- "3306:3306"
volumes_from:
- data
application:
container_name: python-flask-app
build: .
# image: pythonbottle_application
tty: false
volumes_from:
- data
ports:
- "5000:5000"
links:
- mysql:python-flask-db
3-2. データコンテナ
データを永続化するためにデータコンテナを用意します。
データベースコンテナを削除しても中身は残るので、分けると便利です。
container_nameでコンテナ名指定します。任意です。
イメージは、busyboxを使っています。
container_name: python-flask-data
image: busybox
ボリュームで、mysqlの設定ファイル指定します。
conf.dに日本語設定があり、自動的に適用されます。
コンテナ上の"/home/python"フォルダと、ローカルの"app"フォルダを同期しています。この設定をすることによりローカルで編集した内容をコンテナに反映します。
この設定をすることで、コンテナにファイルをアップロードすることなく、単純に保存をするだけで、サーバに設定を反映することができるので便利です!
volumes:
- ./docker/mysql:/etc/mysql/conf.d:ro
- ./app:/home/python
MySQLの日本語設定ファイルです。
このファイルの内容が自動設定されます。
[mysqld]
innodb_strict_mode
innodb_file_format = Barracuda
innodb_file_per_table
innodb_large_prefix = 1
character-set-server=utf8mb4
skip-character-set-client-handshake
max_allowed_packet = 32m
skip-networking = 0
[client]
default-character-set=utf8mb4
3-3. データベースコンテナ
コンテナ名は"python-flask-db"
イメージは公式の"mysql"
を使います。
container_name: python-flask-db
image: mysql
初期データを指定します。
テーブル作成のCREATE文と、データ登録するINSERT文を"/docker-entrypoint-initdb.d"に置きます。
データベース構築時に、自動的に実行されるので、初期値が入ります。
volumes:
- ./initdb.d:/docker-entrypoint-initdb.d
USE sample;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `users` (`id`, `name`) VALUES (1, 'pyhons');
下記の環境変数を設定すると、ルートパスワードやユーザ設定、データベースを構築することができます。
MYSQL_ROOT_PASSWORD ルートのパスワード
MYSQL_USER データベースのユーザ名
MYSQL_PASSWORD データベースのパスワード
MYSQL_DATABASE データベース
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_USER: python
MYSQL_PASSWORD: python
MYSQL_DATABASE: sample
ポートを開放します。MySQLは"3306"です。
ports:
- "3306:3306"
データコンテナから、全てのボリュームをマウントします。
volumes_from:
- data
3-4. アプリケーションコンテナ
コンテナ名任意です。
イメージは、dockerfileからビルドしています。
container_name: python-flask-db
build: .
データコンテナから、全てのボリュームをマウントします。
volumes_from:
- data
ポートを開放します。Flaskは"5000"です。
ports:
- "5000:5000"
データベースコンテナにリンクを張ります。
links:
- mysql:python-flask-db
4. Flask(mysql-connector-python)
4-1. flaskのサンプルファイル
# ライブラリをインポート
from flask import Flask, render_template, request, redirect, url_for
# MySQLドライバはmysql.connectorを使う
import mysql.connector
# Dockerを使う場合で、初期設定の場合hostは"192.168.99.100"
# MySQLのユーザやパスワード、データベースはdocker-compose.ymlで設定したもの
connector = mysql.connector.connect(
user='python',
password='python',
host='192.168.99.100',
database='sample')
cursor = connector.cursor()
cursor.execute("select * from users")
disp = ""
for row in cursor.fetchall():
disp = "ID:" + str(row[0]) + " 名前:" + row[1]
cursor.close
connector.close
# Flaskはインスタンスを生成する
app = Flask(__name__)
# デバッグを可能とする
app.config.update({'DEBUG': True })
# ここからウェブアプリケーション用のルーティングを記述
# index にアクセスしたときの処理
@app.route('/hello')
def hello():
# return "Flask DBから取得 "+disp
# Jinjaを使う
title = "ようこそ"
message = "DBから取得 "+disp
# index.html をレンダリングする
return render_template('index.html', message=message, title=title)
if __name__ == '__main__':
app.run(host='0.0.0.0')
4-2. MySQLとの接続
アプリケーションコンテナをビルドするときに、mysql.connectorをインストールしているので、importすれば使えます。
import mysql.connector
データベースの初期設定をします。
user, password, databaseはdocker-composeで設定したものが入ります。
hostは、DockerでアサインされたIPアドレスを入力します。
筆者の環境の場合は、"192.168.99.100"でした。
# MySQLのユーザやパスワード、データベースはdocker-compose.ymlで設定したもの
connector = mysql.connector.connect(
user='python',
password='python',
host='192.168.99.100',
database='sample')
コネクションを開きます。
cursor = connector.cursor()
SELECT文を実行します。
cursor.execute("select * from users")
データを取得します。
disp = ""
for row in cursor.fetchall():
disp = "ID:" + str(row[0]) + " 名前:" + row[1]
後処理をします。
cursor.close
connector.close
4-3. Flask
ライブラリをインポート
from flask import Flask
app = Flask(__name__)
app.config.update({'DEBUG': True })
http://{IPアドレス}:5000/hello
でアクセスできるようにルーティングします。
@app.route('/hello')
データベースから取得した値を、テンプレートにアサインします。
render_templateでテンプレートファイルを指定し、第2引数以降にテンプレートに渡す値を指定します。
def hello():
# return "Flask DBから取得 "+disp
# Jinjaを使う
title = "ようこそ"
message = "DBから取得 "+disp
# index.html をレンダリングする
return render_template('index.html', message=message, title=title)
Dockerの場合、host='0.0.0.0'を明示的に設定します。
if __name__ == '__main__':
app.run(host='0.0.0.0')
5. Jinja2 テンプレートエンジン
5-1. index.html
{% extends "layout.html" %}
{% block content %}
<h3>Jinja2</h3>
<p>
{% if message %}
{{ message }}
{% else %}
特に何もありません。
{% endif %}
</p>
{% endblock %}
5-2. extends
HTMLの共通部分を読み込みます。
ヘッダー部分や、CSSファイル、jQueryファイルなど、共通で利用する部分を読み込みます。
{% extends "layout.html" %}
5-3. layout.html
layout.htmlは次の通りです。
CSSにbootstrapを使っているので、bootstrapのサンプルをカスタマイズしています。
<!DOCTYPE html>
<!-- http://getbootstrap.com/getting-started/ をカスタマイズ -->
<!-- 全画面共通部分 -->
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- タイトルが入る。タイトルがない場合はBootstrap 101 Templateと表示(仮) -->
{% if title %}
<title>{{ title }}</title>
{% else %}
<title>Bootstrap 101 Template</title>
{% endif %}
<!-- Bootstrap -->
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- ここに本体が入る -->
{% block content %}{% endblock %}
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/static/js/bootstrap.min.js"></script>
</body>
</html>
5-4. block
index.htmlのblock部分に埋め込むHTMLを
{% block content %}
から
{% endblock %}
に埋め込みます。
{% block content %}
<h3>Jinja2</h3>
<p>
{% if message %}
{{ message }}
{% else %}
特に何もありません。
{% endif %}
</p>
{% endblock %}
5-5. if文
if文は次のように書きます。
elseやここにはありませんが、elseifも書けます。
{% if message %}
{{ message }}
{% else %}
特に何もありません。
{% endif %}
6. ローカルでファイル操作し、コンテナに即時反映
このdocker-composeで起動すると、ローカルの"app"フォルダと、コンテナの"/home/python"が同期されます。
このことにより、ローカルからコンテナにファイルアップロードすることなく、保存するだけで、プログラムを反映することができて、非常に効率的です。
サイトマップ
Raspberry Pi 3 にDockerを乗せてPython+MySQL環境を構築!
RaspberryPi3(ラズパイ)にDockerをインストール
RaspberryPi3(ラズパイ)にDockerでPython+bottle+MySQL環境構築する!【簡単構築編】
RaspberryPi3(ラズパイ)にDockerでPython+bottle+MySQL環境構築する!【試行錯誤編】
テスト駆動開発を重点においた規則
コーディング規則「優しいコードを書こう」(FuelPHP)
命名規則「3ヶ月後の自分自身に優しく、チームに優しく、まだ見ぬメンバーに優しく」
開発しやすい環境構築(Docker+PHP)
Dockerを利用しApacheにPHP環境 + Eclipseを連携
Dockerを利用したFuelPHP開発環境構築
Docker利用したFuelPHP開発環境の初期設定とscaffoldを利用してCRUDスケルトン作成
FuelPHPのデータベースマイグレーション