LoginSignup
7
8

More than 3 years have passed since last update.

[イメージ図付]Nginx+gunicorn+FlaskをDocker化[後編]

Last updated at Posted at 2020-02-08

本記事の概要

Flaskアプリケーションを立ち上げる手順や関連する設定について記載します。
本記事の内容は、ローカルにてWebサーバおよびAppサーバをDockerコンテナで起動するケースとなります。
前編はプロセスをそれぞれdockerコマンドで起動する、後編はdocker-composeで一括起動するといった内容を扱います。

前提

  • 前編記事の続きとしての記載となります。

全体像

Flask_Nginx_unicorn_diagramdrawio-Step3-docker-compose.png

最終的な成果物

ソースコード

Githubリポジトリを参照ください。

簡易解説

前編にて、Webサーバ、Appサーバをそれぞれコンテナで起動するようDockerfileを作成しました。これらのコンテナ起動を(起動コマンドという点での)コストを下げるために、docker-composeコマンド1つで2コンテナ起動するようにします。
主な変更点は以下です。

  • docker-compose設定ファイル追加
  • nginx設定ファイルの接続先修正

docker-compose.ymlファイル

今回のケースにおいて、コンテナ間の関係、コンテナ・ホスト間の関係として以下のことを指定する必要があります。

  • Appサーバ
    • Webサーバと同一ネットワークに属している
  • Webサーバ
    • コンテナのポートをホストの特定ポートとでポートフォワーディングする
    • Appサーバと同一ネットワークに属している
    • Appサーバの起動後である必要がある
docker-compose.yml
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サーバコンテナへと変更する必要があります。

nginx.conf
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;
            }
        }
}

起動/コンテナ削除

  • 起動
Terminal
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でコンテナを停止できる。

  • コンテナ削除
Terminal
docker-compose -f deployment/docker-compose/docker-compose.yml down

--rmi allオプションを追加することで、もととなったイメージもすべて削除される。

About docker-compose

便利になる点

大雑把に2点記載すると、以下のようになります。

  1. 複数のコンテナを1コマンドで起動・停止することができるようになる
  2. コンテナ同士の関係性等を設定ファイルで明記することができる

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の方が手軽に利用することができます。

7
8
1

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
7
8