LoginSignup
54
54

More than 5 years have passed since last update.

とりあえずすぐ動く!Dockerを使い、Python3, Flask, MySQL開発環境を構築する!

Last updated at Posted at 2016-09-23

はじめに

「優しいIT」という理念の基、ITコンサルタントをしている亀井亮介と申します!
主な仕事は要求分析・要件定義の上流工程から、開発のマネジメントまでしていますが、プライベートでウェブシステム開発をしています!

目的

細かい説明は抜きにして、Git cloneし、"docker-compose up -d"するだけで、Python3, Flask, MySQL開発環境を構築します!
Dockerをインストールしていることが、前提となります!
「とりあえず動くところが見たい!」というせっかちな(私のような)方は、「1. 動作するまでの手順」を見てくださいね!
2章以降は、各項目の説明をしています!

Githubにファイルを上げているので、興味のある方は使ってくださいね!

目次

  1. 動作するまでの手順
  2. Dockerfile
  3. docker-compose.yml
  4. Flask(mysql-connector-python)
  5. Jinja2 テンプレートエンジン
  6. ローカルでファイル操作し、コンテナに即時反映

1. 動作するまでの手順

1-1. Git cloneする

Gitが使えることが前提です。

Gitクローン
$ git clone git@github.com:RyosukeKamei/python-flask-mysql.git
移動
$ cd python-flask-mysql

フォルダ構成は次のようになります。
フォルダ構成.png

1-2. docker-compose up -d

docker-composeを使い、データコンテナ、データベースコンテナ、アプリケーションコンテナを立ち上げます。
アプリケーションコンテナは、Dockerfileを使いビルドしてから、コンテナの起動をします。

docker-composeでビルドし、起動
$ docker-compose up -d

※アプリケーションコンテナをビルドするのに時間がかかります。

1-3. 動作確認

http://{IPアドレス}:5000/hello
にアクセスします。
IPアドレスは環境によって異なるかもしれません。私の環境では、Dockerのデフォルトで"192.168.99.100"です。
Flaskのデフォルトのポート番号は5000番です。

スクリーンショット 2016-09-23 13.40.23.png

MySQLに登録したデータをそのまま表示しています。
テンプレートエンジンにJinja2を利用しています!

2. Dockerfile

Dockerfileを使いアプリケーションコンテナをビルドします。

2-1. Dockerfile全体

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の軽量フレームワーク
virtualenv,flake8,ipython,Flaskをインストール
RUN pip install virtualenv \
                ipython \
                flake8 \
                Flask

MySQLと接続するドライバは"mysql-connector-python"を利用します。
pipでインストールできるはずが、上手くいかない(2016年9月23日現在)ので、gitクローンして、ビルドし、インストールします。

mysql-connector-pythonインストール
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のファイルを操作する際に、便利な設定をしておきます。
深くは説明しません。

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

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全体

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を使っています。

dataコンテナ
  container_name: python-flask-data
  image: busybox

ボリュームで、mysqlの設定ファイル指定します。
conf.dに日本語設定があり、自動的に適用されます。

コンテナ上の"/home/python"フォルダと、ローカルの"app"フォルダを同期しています。この設定をすることによりローカルで編集した内容をコンテナに反映します。

この設定をすることで、コンテナにファイルをアップロードすることなく、単純に保存をするだけで、サーバに設定を反映することができるので便利です!

dataコンテナ
  volumes:
    - ./docker/mysql:/etc/mysql/conf.d:ro
    - ./app:/home/python

MySQLの日本語設定ファイルです。
このファイルの内容が自動設定されます。

./docker/mysql/my.cnf
[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
/initdb.d/create_table.sql
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 データベース

MySQLの環境変数
  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のサンプルファイル

flask_sample.py
# ライブラリをインポート
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すれば使えます。

MySQLドライバはmysql.connectorを使う
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文を実行します。

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

ライブラリをインポート

Flaskをインポート
from flask import Flask
Flaskのインスタンスを生成
app = Flask(__name__)
デバッグの設定
app.config.update({'DEBUG': True })

http://{IPアドレス}:5000/hello
でアクセスできるようにルーティングします。

helloにルーティング
@app.route('/hello')

データベースから取得した値を、テンプレートにアサインします。
render_templateでテンプレートファイルを指定し、第2引数以降にテンプレートに渡す値を指定します。

helloの中身
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

/templates/index.html
{% extends "layout.html" %}
{% block content %}
    <h3>Jinja2</h3>
    <p>
        {% if message %}
            {{ message }}
        {% else %}
            特に何もありません。
        {% endif %}
    </p>
{% endblock %}

5-2. extends

HTMLの共通部分を読み込みます。
ヘッダー部分や、CSSファイル、jQueryファイルなど、共通で利用する部分を読み込みます。

/templates/index.html
{% extends "layout.html" %}

5-3. layout.html

layout.htmlは次の通りです。
CSSにbootstrapを使っているので、bootstrapのサンプルをカスタマイズしています。

/templates/layout.html
<!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
{% block content %}
    <h3>Jinja2</h3>
    <p>
        {% if message %}
            {{ message }}
        {% else %}
            特に何もありません。
        {% endif %}
    </p>
{% endblock %}

5-5. if文

if文は次のように書きます。
elseやここにはありませんが、elseifも書けます。

jinjaのif文
        {% 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のデータベースマイグレーション

54
54
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
54
54