目標
- 簡単なウェブサービスの構成を仮想環境で作成する
- ウェブサービスの構成は
- フロント: Nginx
- バックエンド: WSGI(mod_wsgi) + Flask
- 仮想環境はDockerを利用してgitを通じて他の開発者と共有できるようにする
- ホストPCのOSに依存しないPythonのデバッグ環境を実現する
- デバッグにはVSCodeのリモートデバッグを利用
このドキュメントを読んで出来る事
目標を前半と後半にわけます。このページでは前半部分を書いています。
- 前半: ← ここ
- 仮想環境のセットアップ(Hyper-V, Docker)
- Nginxコンテナ作成
- Apacheコンテナ作成
- ウェブサービスの骨組みを作成
- 後半:
- ウェブアプリ作成(Flask)
- リモートデバッグ設定
必要な環境
- Windows10 Pro
- Chocolatey (なくても良いがあると便利)
新規にインストールされるパッケージ等
- Hyper-V(有効化)
- Docker for Windows
仮想環境のセットアップ
下記サイトが詳しく書かれていて参考になりました。
参考サイト: [Win] Docker を Windows で使えるようにする
以下簡単な流れだけ書きます
Hyber-Vを有効化
-
Win
キー +S
→ Windowsの機能の有効化または無効化 - Hyper-V の項目にチェック
- 再起動(必要があれば)
Docker のインストール
- powershellアイコンを右クリックして「管理者として実行する」を選択
- 下記コマンドを入力してdockerをインストール
※Chocolateyがない場合は公式サイトからパッケージをダウンロードしてインストール
PS> choco install docker-desktop -y
Docker の設定
- インストール終了後、Widowsに再ログイン
- docker hubにアカウントを作成
- Docker Desktopを起動
- タスクバーのdockerアイコンからをShared Drivesの設定
- dockerアイコンを右クリック
- Setting
- Shared Drives
- 作業ドライブにチェック
Nginxコンテナ作成
以下作業用フォルダ: webapp-docker
PS> mkdir webapp-docker
PS> cd webapp-docker
PS> mkdir nginx
Dockerfile
ファイル作成。ファイルの中身は
FROM nginx
PS> docker build -t test_nginx nginx
PS> docker container run -p 80:80 --name test_nginx --rm test_nginx
動作確認
ブラウザで動作確認。http://localhost/
正常に動作しています。 後始末して次にすすみます。
PS> docker container stop test_nginx
Apacheコンテナ作成
Nginxの動作確認が出来たので、つぎはウェブサーバーのコンテナを作ります。後でウェブアプリも追加する予定なのでUbuntuのイメージから作っていくことにします。すでに他の人が目的に近いDockerfileを作ってくれているので、それをベースにカスタマイズしていきます。いまはapacheの動作が確認できればよいので、カスタマイズはvimとcurlのパッケージの追加のみしています。
手順をまとめると以下のようになります。
Apacheコンテナ作成手順
- ベースのDockerfileを作成
- 必要なツール群(vim, curl)をDockerfileに追記
- イメージの作成
- コンテナの起動と動作確認
- Dockerfileの微調整
PS> mkdir flask
Dockerfile
ファイルを作成。ファイルの中身は
FROM ubuntu
# Avoid warnings by switching to noninteractive
ENV DEBIAN_FRONTEND=noninteractive
# Apache
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
RUN apt-get update \
&& apt-get install -y --no-install-recommends apt-utils dialog 2>&1 \
&& apt-get install -y git iproute2 procps lsb-release \
&& apt-get install -y apache2
# others tools
RUN apt-get install -y vim curl
# Clean up
RUN apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 80
CMD ["apachectl", "-D", "FOREGROUND"]
PS> docker image build -t test_apache flask
PS> docker container run -p 80:80 --name test_apache --rm test_apache
動作確認
ブラウザで動作確認 http://localhost/
コンソールに以下のようなワーニングが出ているのでつぎのステップで微調整します。
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
コンテナ内で試行錯誤
ここで下記のようにDockerfileを修正して再ビルドしても良いのですが、
- Dockerfile 修正 ← 試行錯誤ポイント
- ビルド
- コンテナ作成
- 動作確認 ← ここまで結果がわからない
Dockerfileの修正内容が間違っていた場合、再度、1.からやり直しになり時間をロスしてしまいます。(経験済) なので下記のほうが結果的に早く終わります。(Dockerfileにvimとcurlを記述したのはこのためです) - コンテナ内で設定ファイル等を修正 ← 試行錯誤ポイント
- 動作確認 ← 結果がすぐにわかる
- Dockerfile 修正
- ビルド
- コンテナ作成
- 動作確認
PS> docker container exec -it test_apache bash
このエラーは、/etc/hosts にlocalhost以外に自分で設定したホスト名がApacheの設定ファイルに定義されていないために発生するらしいので、apacheの設定にSeverNameの定義を追加します。
参考: ubuntuにおけるapache2のAH00558エラーを解決する
root# echo ServerName $HOSTNAME > /etc/apache2/conf-available/fqdn.conf
root# a2enconf fqdn
root# apachectl graceful
Dockerfile に反映
エラーが出力されなくなったのでこの内容をDockerfileに書きます。
# 略
# others tools
RUN apt-get install -y vim curl
# ---追加---
RUN echo ServerName $HOSTNAME > /etc/apache2/conf-available/fqdn.conf \
&& a2enconf fqdn
# ---ここまで---
# Clean up
powershellで再ビルト~コンテナ起動 → 動作確認します。
PS> docker container stop test_apache
PS> docker build -t test_apache flask
エラーが出力されなくなりました
ウェブサービスの骨組みを作成
各々のコンテナで動作確認出来たので、2つのコンテナが連帯して動作するように修正していきます。
複数コンテナの起動設定
作業用フォルダwebapp-docker
にdocker-compose.yml
を作成します。ファイルの中身は
version: '3'
services:
nginx:
build:
context: ./nginx
dockerfile: Dockerfile
container_name: wbx
ports:
- 80:80
flask:
build:
context: ./flask
dockerfile: Dockerfile
container_name: wbb3
ports:
- 5000:80
動作確認
PS> docker-compose up --build
ブラウザで確認 →
リバースプロキシの設定(Nginx → Apache)
いまは別々に起動しているだけなので、特定のURLのみApacheにリダイレクトするようにNginxの設定を変更します。
PS> docker container exec -it wbx bash
root# vi /etc/nginx/conf.d/default.conf
bash: vi: command not found
Nginxのコンテナには何も入れていませんでした 。シェル上でパッケージをインストールして、設定ファイルの調整をしていきます。
root# apt update
root# apt install vim curl -y
root# vi /etc/nginx/conf.d/default.conf
ファイルの中身は
server {
listen 80;
server_name localhost;
location /app/ {
proxy_pass http://wbb3/;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
root# nginx -t
root# nginx -s reload
ブラウザで動作確認します。
- http://localhost/ ← nginx
-
http://localhost/app/ ← apache
でそれぞれのDefault Pageが表示されるまで設定ファイルを調整します。
Nginx の設定ファイルのコピーと Dockerfile の修正
PS> mkdir nginx/etc/nginx
PS> docker container cp wbx:/etc/nginx/conf.d ./nginx/etc/nginx/
FROM nginx
COPY ./etc/nginx /etc/nginx
Ctrl
+C
で起動しているコンテナを停止し、Dockerfile を再ビルドします。
PS> docker-compose up --build
ブラウザで動作確認 →
まとめ
最終的なフォルダ構成とファイル内容は以下になります。
PS> tree /F
C:.
│ docker-compose.yml
│
├─flask
│ Dockerfile
│
└─nginx
│ Dockerfile
│
└─etc
└─nginx
└─conf.d
default.conf
version: '3'
services:
nginx:
build:
context: ./nginx
dockerfile: Dockerfile
container_name: wbx
ports:
- 80:80
flask:
build:
context: ./flask
dockerfile: Dockerfile
container_name: wbb3
ports:
- 5000:80
FROM ubuntu
# Avoid warnings by switching to noninteractive
ENV DEBIAN_FRONTEND=noninteractive
# Apache
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_PID_FILE /var/run/apache2.pid
ENV APACHE_RUN_DIR /var/run/apache2
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
RUN apt-get update \
&& apt-get install -y --no-install-recommends apt-utils dialog 2>&1 \
&& apt-get install -y git iproute2 procps lsb-release \
&& apt-get install -y apache2
# others tools
RUN apt-get install -y vim curl
# Apache
RUN echo ServerName $HOSTNAME > /etc/apache2/conf-available/fqdn.conf \
&& a2enconf fqdn
# Clean up
RUN apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
EXPOSE 80
CMD ["apachectl", "-D", "FOREGROUND"]
FROM nginx
COPY ./etc/nginx /etc/nginx
server {
listen 80;
server_name localhost;
location /app/ {
proxy_pass http://wbb3/;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}