本記事の概要
Flaskアプリケーションを立ち上げる手順や関連する設定について記載します。
本記事の内容は、ローカルにてWebサーバおよびAppサーバをDockerコンテナで起動するケースとなります。
前編はプロセスをそれぞれdocker
コマンドで起動する、後編はdocker-compose
で一括起動するといった内容を扱います。
前提
- 前編記事の続きとしての記載となります。
全体像
最終的な成果物
ソースコード
Githubリポジトリを参照ください。
簡易解説
前編にて、Webサーバ、Appサーバをそれぞれコンテナで起動するようDockerfile
を作成しました。これらのコンテナ起動を(起動コマンドという点での)コストを下げるために、docker-compose
コマンド1つで2コンテナ起動するようにします。
主な変更点は以下です。
- docker-compose設定ファイル追加
-
nginx
設定ファイルの接続先修正
docker-compose.ymlファイル
今回のケースにおいて、コンテナ間の関係、コンテナ・ホスト間の関係として以下のことを指定する必要があります。
- Appサーバ
- Webサーバと同一ネットワークに属している
- Webサーバ
- コンテナのポートをホストの特定ポートとでポートフォワーディングする
- Appサーバと同一ネットワークに属している
- Appサーバの起動後である必要がある
version: "3.7" # composeファイルのバージョンを指定する
services: # このレイヤーの配下にコンテナ単位で記述を追加していく
###########ここからAppサーバの設定###########
app-server: # サービスの名前、ホスト名にもなりうる
container_name: app-server # コンテナの名前
build: # 自分で用意したDockerfileでビルドを行う場合必要なブロック
context: ../../ # docker buildするときのパスを指定、ymlファイルのあるところからの相対パス
dockerfile: deployment/dockerfiles/app-server/Dockerfile # 利用するDockerfile。contextのパスから指定
networks: # このサービスが属するネットワークの設定
my_host_network: # 後述のmy_host_networkに属する
aliases:
- uwsgi-server # my_host_network上ではこの名前で判別できるようになる
expose:
- 9876 # このポートをLISTEN状態にする
restart: always # サービス再起動ポリシー
###########ここまでAppサーバの設定###########
###########ここからWebサーバの設定###########
web-server:
container_name: web-server
build:
context: ../../
dockerfile: deployment/dockerfiles/web-server/Dockerfile
networks:
my_host_network:
aliases:
- nginx-server
ports:
- 9090:9123 # ホストPCの9090番をコンテナの9123番にポートフォワーディング
depends_on: # 依存関係を指定。web-serverの起動より前にapp-serverを起動するようになる
- app-server
restart: always
###########ここまでWebサーバの設定###########
###########ここからネットワークの設定###########
networks:
my_host_network: # 上の方のサーバ設定で使うときのエイリアス名
name: my-nginx-network # ネットワークの名前
driver: bridge # ドライバ種別、bridgeかoverlay
なお、ネットワークについては1つのホストPC上に複数のコンテナを展開するパターンのためbridge
を採用しています。ホストが複数に分かれる場合はoverlay
を採用してください。
nginx.confファイル
これまではホストPC上に(ダイレクトに)両サーバが起動していたので、リバースプロキシ先にlocalhost
と指定していました。本Stepで接続先をAppサーバコンテナへと変更する必要があります。
http {
server {
# 「uwsgi-server」はdocker-compose.ymlで設定したmy_host_networkネットワーク上のAppサーバのエイリアス名称
location / {
proxy_pass http://uwsgi-server:9876;
# before: proxy_pass http://127.0.0.1:9876;
}
location /health {
proxy_pass http://uwsgi-server:9876/health;
# before: proxy_pass http://127.0.0.1:9876/health;
}
}
}
起動/コンテナ削除
- 起動
docker-compose -f deployment/docker-compose/docker-compose.yml up
# -fオプションで設定ファイルを指定
up
でymlファイルの設定にしたがってイメージをビルド、コンテナが作成される。
build
+start
のイメージ。
また、-d
オプションを加えることでバックグランドで実行することが可能。
- 停止
フォアグラウンドで実行した場合は、Ctrl+C
、
バックグランドで実行した場合はdocker-compose -f deployment/docker-compose/docker-compose.yml stop
でコンテナを停止できる。
- コンテナ削除
docker-compose -f deployment/docker-compose/docker-compose.yml down
--rmi all
オプションを追加することで、もととなったイメージもすべて削除される。
About docker-compose
便利になる点
大雑把に2点記載すると、以下のようになります。
- 複数のコンテナを1コマンドで起動・停止することができるようになる
- コンテナ同士の関係性等を設定ファイルで明記することができる
1については、10個のコンテナを起動する必要がある場合を想定してみてください。docker run {container}
を10回入力するのはそこそこのコストですよね。ひょっとしたら1つ起動を忘れてしまうかもしれません。それがdocker-compose up
の1コマンドで完了するようになるので、起動漏れも起こらないですし、何よりラクですね。(ここだけにフォーカスすると、シェル書けばいいじゃんともなりますが)
2について、今回のStepを例にとってみます。
それぞれのコンテナについてDockerfile
での記載は出来ず、docker run
の場合は起動時オプションとして指定する必要のある起動条件がいくつかありました。
- Webサーバ
- コンテナのポートをホストの特定ポートとでポートフォワーディングする
- Appサーバと同一ネットワークに属している
- Appサーバの起動後である必要がある
- Appサーバ
- Webサーバと同一ネットワークに属している
docker-compose
を使用することで、上記の設定を1つのymlファイルに定義することができるため、コンテナ間、コンテナーホスト間の関係性も含めて構築難易度を下げることが可能になります。
とくに以下のケースで利用価値が高くなります。
- コンテナ、ホスト間でvolume共有をしたい
- network設定を行いたい
- 環境変数を多く設定したい
docker-composeはProductionで利用できるか
個人的な見解となりますが、利用しないor局所的利用 が大半かと思います。
というのも、コンテナを作成、コンテナ間の関係性を定義できれば、これを本番にのせて終わり・・・ではないためです。
本番(およびステージング)環境でサービスを展開させるためには、ここまでのStepに加えて、スケーラビリティ、ロードバランシング、ネットワーク、ランタイム
などなどといったカタカナ用語たちを考えなければなりません。docker-compose
を利用することで解決できる分野もありますが、すべてをこなすことは厳しく思えます。
オーケストレーションとして利用されるものとしては、やはりkubernetes
となるでしょう。
ただ、ローカル環境でkubernetes
クラスタを展開することがスペック的に厳しい場合や、単にアプリケーションの挙動を確認する上ではdocker-compose
の方が手軽に利用することができます。