docker触ってみたかったので最小構成のflaskアプリケーションをローカル(mac)で作成して,
docker-composeして,
vagrant上のubuntuに投げてみた.
content
- ローカルでflask applicationを作成する
- 準備
- app.py
- uWSGI用のconf.iniを書く
- Nginx用のnginx.confを書く
- Dockerfileを書く
- docker-composeする
- 走らせてみる
- Vagrantで立ち上げたUbuntuに持っていく
- Docker hubでimageを共有
ローカルでflask applicationを作成する
とりあえず簡単なアプリを作っていきま.
準備
$ mkdir Project && cd Project
$ mkdir flask_app && mkdir nginx
$ python -m venv env && source env/bin/activate
(env)$ pip install flask uwsgi
(env)$ pip freeze > flask_app/requirements.txt
(env)$ touch flask_app/app.py flask_app/conf.ini nginx/nginx.conf
(env)$ tree .
.
├── env
├── flask_app
│ ├── app.py
│ ├── requirements.txt
│ └── conf.ini
└── nginx
└── nginx.conf
ディレクトリ構成はこんな感じ.
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return "<h1>Hello from Flask</h1>"
if __name__ == "__main__":
app.run()
一応確認で,
(env)$ cd flask_app
(env)$ python app.py
サーバーを立てて, ローカルホスト にアクセスして,
Hello from Flask
が表示されていることを確認.
uWSGI用のconf.iniを書く
本筋とそれるのでこの辺はざっくり.
[uwsgi]
; module: app.py -> app
module = app:app
processes = 4
threads = 2
master = true
; socket
socket = :8080
chmod-socket = 660
; LOG
logto = ./app.log
vacuum = true
die-on-term = true
走らせるアプリを指定しつつ, ソケットの吐き出し先に8080ポートを指定しておく.
Nginx用のnginx.confを書く
server {
listen 80;
location / {
include uwsgi_params;
uwsgi_pass flask_app:8080;
}
}
よくあるやつ.
uwsgi用のconf.iniでソケットの吐き出し先を8080にしているので, flask_app(コンテナ名)の8080を読みに行くように書く.
Dockerfileを書く
Dockerでは,
- FROM で 元となるイメージ
- RUN でコンテナ作成時の実行コマンド
- CMD でコンテナ起動時の実行コマンド
を書いていく.
各コンテナ毎にDockerfileが必要なので, 今回は
flask_appディレクトリと, nginxディレクトリにそれぞれDockerfileを用意する
flask_app/Dockerfile
FROM python:3.7.2-stretch
WORKDIR /flask_app
COPY . /flask_app
RUN pip install -r requirements.txt
CMD ["uwsgi", "--ini", "conf.ini"]
- 元イメージをPython3.7.2
- WORKDIRではコンテナ内の作業パスを指定
- COPYの項目では, (Dockerfileから見た)カレントディレクトリのファイルをそのままコンテナの/flask_appにコピー
- コンテナ作成時にrequirements.txtにある必要なモジュールを取得
- 起動コマンドは uwsgi –ini conf.ini
nginx/Dockerfile
FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/
nginxのデフォルトの設定ファイルを削除し, 自分で書いたnginx.confを設置する.
docker-composeする
今回はコンテナが2つあるので, これらを連携するべくdocker-composeを利用する.
(env)$ cd /path/to/Project
(env)$ touch docker-compose.yml
docker-compose.yml
version: "3.7"
services:
flask_app:
build: ./flask_app
container_name: flask_app
restart: always
expose:
- 8080
nginx:
build: ./nginx
container_name: nginx
restart: always
ports:
- "80:80"
- (外部から)80へのアクセスを, nginxのport80へ繋ぐ (ports: 80:80, 左がホスト, 右がnginx)
- nginxがport80をlistenして, flask_appコンテナの8080を読みに行く
- flask_appコンテナでは8080ポートを開放(expose)して, uwsgiのconf.iniによりソケットを8080に吐き出す
という流れがちゃんと行えるようにdocker-compose.ymlを書く.
走らせてみる
(env)$ docker-compose build --up
ローカルホスト にアクセスすると, flask_appのページが表示される.
Vagrantで立ち上げたUbuntuに持っていく
Dockerの魅力はローカルで作ったイメージをそのまま実環境に持っていけることだと理解しているので(そうだよね?),
とりあえずVagrantでUbuntuを立ち上げて移植してみる
とりあGithubで共有(割愛)
1. VagrantでUbuntuを立ち上げる
Vagrantが未導入なら以下の2つをいれる(普通にec2とかgce使ってもいいけど).
特に設定はないので, インストールだけすればおけ.
$ mkdir Vag && cd Vag
$ vagrant box add trusty64 https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box
$ vagrant init trusty64
# Vagrantfile -> config.vm.network "private_network"のコメントアウトを解除して, ipをメモっておく. 今回は 192.168.33.10
$ vagrant up
$ vagrant ssh
ubuntuに接続された.
2. dockerとdocker-composeのインストール
まずは, dockerとdocker-composeをインストール
$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
でインストールが完了.
$ sudo docker -V
$ sudo docker-compose
でインストールが正常にできているか確認.
※自分の場合はお試しでdocker runとかいじってたらバージョンの関係でエラーを吐かれたので,
$ sudo apt-get remove docker-ce && sudo apt-get install -y docker-ce=18.06.1~ce~3-0~ubuntu
をして解消した.
3. docker-composeでアプリケーションの起動
まずは, git clone等でローカルで作ったファイル等を取ってくる.
その上で,
$ cd <dirname>
$ sudo docker-compose up --build
で, 192.168.33.10 にアクセスしてみるとflask_applicationのページに繋がった!
すげぇ!
ctrl-cで閉じれるけど, 実環境だとデーモン化したいはずなので
$ sudo docker-compose up -d
でデーモン化し, 終了は
$ sudo docker ps # CONTAINER IDを把握
$ sudo docker kill <CONTAINER ID>
とするか, めんどければ
$ docker ps -aq | xargs rm -f
としてコンテナ全部消し去ってもOK.
Docker hubでimageを共有
先程の例では,
ローカル環境で作成したアプリをDockerfile毎共有することで実環境(というかVagrant)上でもスムーズにアプリを起動したが,
imageを共有できるDocker hubもあるとのことなのでそちらも試してみる
まずは, Docker Hub でアカウントを作成して,
$ docker login # 必要な情報を入力
Login Succeeded
Docker Hubにpushするイメージは,
<username>/hogeでなきゃいけないらしいので, docker-compose.ymlを修正してイメージ名を指定しておく.
version: "3.7"
services:
flask_app:
build: ./flask_app
image: <username>/flask_app
container_name: flask_app
restart: always
environment:
- APP_NAME=MyFlaskApp
expose:
- 8080
nginx:
build: ./nginx
image: <username>/nginx
container_name: nginx
restart: always
ports:
- "80:80"
image名を書き換えたので, 再Buildしてpushする.
(env)$ docker-compose build
(env)$ docker push <usename>/flask_app
(env)$ docker push <usename>/nginx
これでpushできた.
Docker Hub に行くと, リポジトリが追加されているはず.
Vagrantに移動して,
$ sudo docker pull <username>/flask_app
$ sudo docker pull <username>/nginx
でイメージを取得できた.
$ sudo docker run -d <username>/flask_app
$ sudo docker run -d <username>/nginx
で無事起動できた.
けど, アクセスできない.
コンテナ名がdocker-compose.ymlに書いた内容と異なるので, 設定が反映できてないっぽい.
引き数で指定して再実行してみる.
$ sudo docker run -d --expose=8080 --restart=always --name flask_app <username>/flask_app
$ sudo docker run -d -p=80:80 --restart=always --name nginx <username>/nginx
またダメ.
おとなしくdocker-compose.ymlを準備したら上手く行った.
という感じで, どちらにせよdocker-compose.ymlを共有する必要があるくさいので, サーバーにdockerいれて起動ってするならGithubリポジトリを共有してしまったほうが良い気がする(というかdocker hubでどうこうするメリットが浮かばない)