神戸学院大学 経営学部 林坂ゼミ

Docker 入門トップページ

« 戻る 次へ »

Docker 入門

さまざまな Web サーバを Docker Compose で構築する

nginx のリバースプロキシ,および複数の Apache コンテナの組合せで /site-a/ と /site-b/ を運用する

前のページでは1個の apache コンテナ上で複数のバーチャルホストを構築しました.このため,例えば site-a のバーチャルホストにおいてトラブルが起こったり設定を変更するなどしてコンテナが停止したり再起動している間は,site-b やトップページも Web サービスが停止することに注意してください.ここでは apache のバーチャルホストではなく,複数の apache コンテナを起動して全体としては同様のサービスを設定します.これにより,たとえ site-a のコンテナ停止や再起動中であっても site-b やトップページはサービス提供を継続することができるようになります.なお,このページのサンプルコードは GitHub の web05NginxApache フォルダで公開しています.

web-205

まず,例によって任意の新規ディレクトリを作成し,その中に次の構成でディレクトリとファイルを設置します.なお,ログファイルは実行時に自動的に生成されるのでディレクトリと .gitignore だけを作成します.

% tree -a -F ⏎
./
├── apache/
│   └── conf/
│       ├── httpd7000.conf
│       ├── httpd8000.conf
│       └── httpd9000.conf
├── docker-compose.yml
├── nginx/
│   └── conf.d/
│       └── default.conf
├── Readme.md
└── web/
    ├── html7000/
    │   └── index.html
    ├── html8000/
    │   └── index.html
    ├── html9000/
    │   └── index.html
    └── logs/
        ├── apache7000/
        │   ├── .gitignore
        │   ├── access_log
        │   └── error_log
        ├── apache8000/
        │   ├── .gitignore
        │   ├── access_log
        │   └── error_log
        ├── apache9000/
        │   ├── .gitignore
        │   ├── access_log
        │   └── error_log
        └── nginx/
            ├── .gitignore
            ├── access.log
            └── error.log

14 directories, 21 files

全体の設計図である docker-compose.yml は次の内容にします.ここで apache コンテナを起動するサービスが3個定義されていることに注意してください.また,apache/conf/ ディレクトリに httpd7000.conf, httpd8000.conf, httpd9000.conf という3種類の設定ファイルがありますが,これらをコンテナの httpd.conf という名称でボリュームとして設定していることにも注意してください.

docker-compose.yml
services:
  apache5-7000:
    image: httpd:latest
    container_name: apache5-7000
    expose:
      - "7000:7000"
    volumes:
      - ./apache/conf/httpd7000.conf:/usr/local/apache2/conf/httpd.conf
      - ./web/html7000:/usr/local/apache2/htdocs7000/
      - ./web/logs/apache7000:/usr/local/apache2/logs/

  apache5-8000:
    image: httpd:latest
    container_name: apache5-8000
    expose:
      - "8000:8000"
    volumes:
      - ./apache/conf/httpd8000.conf:/usr/local/apache2/conf/httpd.conf
      - ./web/html8000:/usr/local/apache2/htdocs8000/
      - ./web/logs/apache8000:/usr/local/apache2/logs/

  apache5-9000:
    image: httpd:latest
    container_name: apache5-9000
    expose:
      - "9000:9000"
    volumes:
      - ./apache/conf/httpd9000.conf:/usr/local/apache2/conf/httpd.conf
      - ./web/html9000:/usr/local/apache2/htdocs9000/
      - ./web/logs/apache9000:/usr/local/apache2/logs/

  nginx:
    image: nginx:latest
    container_name: nginx5
    ports:
      - "80:80"
    depends_on:
      - apache5-7000
      - apache5-8000
      - apache5-9000
    volumes:
      - ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
      - ./web/logs/nginx:/var/log/nginx

次は nginx のリバースプロキシを設定します.具体的には,http://localhost/site-a/ 以下のリクエストは 8000 番ポートを通じて apache5-8000 サービスへ転送し,http://localhost/site-b/ 以下のリクエストは 9000 番ポートを通じて apache5-9000 サービスへ転送します.さらに,それ以外の URI へのリクエストは 7000 番ポートを通じて apache5-7000 サービスへ転送します.

nginx/conf.d/default.conf
server {
    listen 80;
    server_name localhost;

    location /site-a/ {
        proxy_pass http://apache5-8000:8000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /site-b/ {
        proxy_pass http://apache5-9000:9000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location / {
        proxy_pass http://apache5-7000:7000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

続いて apache の設定ファイルを3種類準備します.それぞれポート番号に関する部分が異なるのみです.

apache/conf/httpd7000.conf

ServerRoot "/usr/local/apache2"

#Listen 12.34.56.78:80
Listen 7000

LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
LoadModule filter_module modules/mod_filter.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so

<IfModule unixd_module>
User www-data
Group www-data
</IfModule>

# 'Main' server configuration

ServerAdmin you@example.com

#ServerName www.example.com:80


<Directory />
    AllowOverride none
    Require all denied
</Directory>


# DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>

<Files ".ht*">
    Require all denied
</Files>

ErrorLog "logs/error_log"

LogLevel warn

<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common

    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>

    CustomLog "logs/access_log" combined
</IfModule>

<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/"
</IfModule>

<IfModule cgid_module>
    #Scriptsock cgisock
</IfModule>

<Directory "/usr/local/apache2/cgi-bin">
    AllowOverride None
    Options None
    Require all granted
</Directory>

<IfModule headers_module>
    RequestHeader unset Proxy early
</IfModule>

<IfModule mime_module>
    TypesConfig conf/mime.types

    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
</IfModule>


<IfModule proxy_html_module>
Include conf/extra/proxy-html.conf
</IfModule>

<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

<VirtualHost *:7000>
    DocumentRoot "/usr/local/apache2/htdocs7000"
    <Directory "/usr/local/apache2/htdocs7000">
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>

apache/conf/httpd8000.conf
ServerRoot "/usr/local/apache2"

#Listen 12.34.56.78:80
Listen 8000

LoadModule mpm_event_module modules/mod_mpm_event.so

...(中略)...

<VirtualHost *:8000>
    DocumentRoot "/usr/local/apache2/htdocs8000"
    <Directory "/usr/local/apache2/htdocs8000">
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>

apache/conf/httpd9000.conf
ServerRoot "/usr/local/apache2"

#Listen 12.34.56.78:80
Listen 9000

LoadModule mpm_event_module modules/mod_mpm_event.so

...(中略)...

<VirtualHost *:9000>
    DocumentRoot "/usr/local/apache2/htdocs9000"
    <Directory "/usr/local/apache2/htdocs9000">
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>

それぞれのサイトで提供するためのコンテンツを作成します.これらは docker-compose.yml の9行目,19行目,29行目において設置するディレクトリが定義されていることに注意して作成してください.

web/html7000/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Apache</title>
</head>
<body>
  <h1>Hello Apache</h1>
  <p>
    Hello Apache
  </p>
  <p>
    このサイトはNginxのリバースプロキシと3個のApacheコンテナで構築しています.
  </p>
  <h2>リンク</h2>
  <ul>
    <li><a href="/">トップページ</a>(このページ)</li>
    <li><a href="/site-a/">Site-A</a></li>
    <li><a href="/site-b/">Site-B</a></li>
  </ul>
</body>
</html>
web/html8000/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Apache</title>
</head>
<body>
  <h1>Hello Apache</h1>
  <p>
    Hello Apache Site-A
  </p>
  <p>
    このサイトはNginxのリバースプロキシと3個のApacheコンテナで構築しています.
  </p>
  <h2>リンク</h2>
  <ul>
    <li><a href="/">トップページ</a></li>
    <li><a href="/site-a/">Site-A</a>(このページ)</li>
    <li><a href="/site-b/">Site-B</a></li>
  </ul>
</body>
</html>
web/html9000/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Apache</title>
</head>
<body>
  <h1>Hello Apache</h1>
  <p>
    Hello Apache Site-B
  </p>
  <p>
    このサイトはNginxのリバースプロキシと3個のApacheコンテナで構築しています.
  </p>
  <h2>リンク</h2>
  <ul>
    <li><a href="/">トップページ</a></li>
    <li><a href="/site-a/">Site-A</a></li>
    <li><a href="/site-b/">Site-B</a>(このページ)</li>
  </ul>
</body>
</html>

アクセスログファイルが出力されるするそれぞれのディレクトリには .gitignore を設置し,ログファイルが Git のリポジトリに登録されないようにするため * だけを指定しておきます.

web/logs/*/.gitignore
*

すべての準備ができたらコンテナを起動します.このとき,4個のコンテナ(と1つのネットワーク)が1つのコマンドで起動できていることに注意してください.

% docker compose up -d ⏎
[+] Running 5/5
 ✔ Network web05nginxapache_default  Created                      0.0s
 ✔ Container apache5-8000            Started                      0.2s
 ✔ Container apache5-7000            Started                      0.2s
 ✔ Container apache5-9000            Started                      0.2s
 ✔ Container nginx5                  Started                      0.2s
%

起動中のコンテナを一覧で確認します.

% docker container ls ⏎
CONTAINER ID   IMAGE          COMMAND                   CREATED          STATUS          PORTS                                 NAMES
f4ac3c1624a4   nginx:latest   "/docker-entrypoint.…"   17 seconds ago   Up 16 seconds   0.0.0.0:80->80/tcp, [::]:80->80/tcp   nginx5
e79a140b05d4   httpd:latest   "httpd-foreground"        17 seconds ago   Up 16 seconds   0/tcp, 80/tcp                         apache5-9000
d95be1282706   httpd:latest   "httpd-foreground"        17 seconds ago   Up 16 seconds   0/tcp, 80/tcp                         apache5-7000
c543e6e05275   httpd:latest   "httpd-foreground"        17 seconds ago   Up 16 seconds   0/tcp, 80/tcp                         apache5-8000
%

コンテナの起動が確認できたので Web ブラウザで http://localhost/ や http://localhost/site-a/ および http://localhost/site-b/ に接続します.

docker-2025-web-09
docker-2025-web-10
docker-2025-web-11

コンテナを終了して廃棄します.

% docker compose down ⏎
[+] Running 5/5
 ✔ Container nginx5                  Removed                      0.2s
 ✔ Container apache5-9000            Removed                      1.2s
 ✔ Container apache5-8000            Removed                      1.2s
 ✔ Container apache5-7000            Removed                      1.2s
 ✔ Network web05nginxapache_default  Removed                      0.2s
% docker container ls -a ⏎
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
%

ここでは nginx のリバースプロキシと3個の apache web サーバで環境を構築しました.次のページでは web サーバについて apache の代わりに nginx で構築する方法を試します.