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

Docker 入門トップページ

« 戻る 次へ »

Docker 入門

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

Apache のバーチャルホストを起動する

通常の Web サービスは HTTP では TCP 80 番ポート,HTTPS では 433 番ポートというウエルノウンポート番号を使って提供されます.ここでは,80 番ポート以外にも 8000 番ポートと 9000 番ポートという3つの異なるポートで異なるサービスを提供することを考えます.具体的には Apache のバーチャルホストという機能を利用して,http://localhost:80/ と http://localhost:8000/ および http://localhost:9000/ とで3つのサービスを提供する例を作成します.なお,このページのサンプルコードは GitHub の web03Apache フォルダで公開しています.

web-203

まず,任意の名前の新規ディレクトリを作成し,次の通りいくつかのディレクトリとファイルを設置します.(web/logs/access_log は後の作業で自動的に作成されます.)ここで,3つの Web サービスのコンテンツはディレクトリ (html80, html8000, html9000) に分けて設置していることに注意してください.

% tree -a -F ⏎
./
├── apache/
│   └── conf/
│       └── httpd.conf
├── docker-compose.yml
├── Readme.md
└── web/
    ├── html80/
    │   └── index.html
    ├── html8000/
    │   └── index.html
    ├── html9000/
    │   └── index.html
    └── logs/
        ├── .gitignore
        ├── access_log
        └── error_log

8 directories, 9 files

全体の設計図である docker-compose.yml を準備します.次の通り,5行目から8行目で3種類のポートを利用していることに注意してください.また,3つの Web サービスそれぞれのコンテンツを格納するためのボリュームも定義していることに注意してください.

docker-compose.yml
services:
  apache:
    image: httpd:latest
    container_name: apache3
    ports:
      - "80:80"
      - "8000:8000"
      - "9000:9000"
    volumes:
      - ./apache/conf/httpd.conf:/usr/local/apache2/conf/httpd.conf
      - ./web/html80:/usr/local/apache2/htdocs80/
      - ./web/html8000:/usr/local/apache2/htdocs8000/
      - ./web/html9000:/usr/local/apache2/htdocs9000/
      - ./web/logs:/usr/local/apache2/logs/

Apache の設定ファイル (apache/conf/httpd.conf) は次の内容にします.具体的には,4〜6行目において3つのポートを受け付けるようにし,3つのバーチャルホストの設定を 115 行目以降に記述します.さらに,アクセスログのフォーマットは標準では69行目の内容ですが,これではどのバーチャルホストのログであるかが残されないため,この行をコメントアウトし,70行目のように %{local}p を追加して,ポート番号がアクセスログに残るように設定します.

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

#Listen 12.34.56.78:80
Listen 80
Listen 8000
Listen 9000

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 \"%{Referer}i\" \"%{User-Agent}i\" %{local}p" 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 *:80>
    DocumentRoot "/usr/local/apache2/htdocs80"
    <Directory "/usr/local/apache2/htdocs80">
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>

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


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

Web ページのコンテンツは任意の内容で良いですが,どのバーチャルホストのコンテンツであるかが明確になるようにしておくと良いでしょう.たとえば 80 番ポート用のコンテンツは次のようにします.

web/html80/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>
    Apache Port #80 です.
  </p>
  <p>
    このサイトはApacheのバーチャルホストを使って,3つの異なるポートでサービスを提供しています.
  </p>
  <h2>リンク</h2>
  <ul>
    <li><a href="http://localhost:80/">#80 ポート</a>(このページ)</li>
    <li><a href="http://localhost:8000/">#8000 ポート</a></li>
    <li><a href="http://localhost:9000/">#9000 ポート</a></li>
  </ul>
</body>
</html>

同様に8000番ポート用と9000番ポート用のコンテンツも準備します.

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>
    Apache Port #8000 です.
  </p>
  <p>
    このサイトはApacheのバーチャルホストを使って,3つの異なるポートでサービスを提供しています.
  </p>
  <h2>リンク</h2>
  <ul>
    <li><a href="http://localhost:80/">#80 ポート</a></li>
    <li><a href="http://localhost:8000/">#8000 ポート</a>(このページ)</li>
    <li><a href="http://localhost:9000/">#9000 ポート</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>
    Apache Port #9000 です.
  </p>
  <p>
    このサイトはApacheのバーチャルホストを使って,3つの異なるポートでサービスを提供しています.
  </p>
  <h2>リンク</h2>
  <ul>
    <li><a href="http://localhost:80/">#80 ポート</a></li>
    <li><a href="http://localhost:8000/">#8000 ポート</a></li>
    <li><a href="http://localhost:9000/">#9000 ポート</a>(このページ)</li>
  </ul>
</body>
</html>

ログファイルは実行時に自動的に作成されますが,Git のリポジトリにログファイル自体がコミットされないように .gitignore ファイルを準備します.

web/logs/.gitignore
*

すべてのファイルが準備できたらコンテナを起動します.前のページで apache イメージのダウンロードができているので今回はすぐにコンテナが起動するはずです.

% docker compose up -d ⏎
[+] Running 2/2
 ✔ Network web03apache_default  Created                                     0.0s
 ✔ Container apache3            Started                                     0.1s
%

コンテナの起動状態を確認します.見にくいですが,3つのポートに接続できるようになっていることが確認できます.

% docker container ls ⏎
CONTAINER ID   IMAGE          COMMAND              CREATED          STATUS          PORTS                                                                                                                           NAMES
64017aecb609   httpd:latest   "httpd-foreground"   14 seconds ago   Up 14 seconds   0.0.0.0:80->80/tcp, [::]:80->80/tcp, 0.0.0.0:8000->8000/tcp, [::]:8000->8000/tcp, 0.0.0.0:9000->9000/tcp, [::]:9000->9000/tcp   apache3
%

コンテナの起動が確認できたので Web ブラウザで http://localhost:80/ や http://localhost/ に接続します.このとき,標準が80番ポートであることから同じ結果になるはずです.

docker-2025-web-03

さらに,http://localhost:8000/ や http://localhost:9000/ にアクセスします.ポート番号を変えれば別のサービスに接続できることに注意してください.

docker-2025-web-04
docker-2025-web-05

最後に docker compose stop でコンテナを終了(あるいは docker compose down でコンテナを終了して廃棄)します.

% docker compose stop ⏎
[+] Stopping 1/1
 ✔ Container apache3  Stopped                                               1.3s
% docker container ls -a ⏎
CONTAINER ID   IMAGE          COMMAND              CREATED         STATUS                     PORTS     NAMES
64017aecb609   httpd:latest   "httpd-foreground"   2 minutes ago   Exited (0) 5 seconds ago             apache3
%

なお,アクセスログはすべてのバーチャルホストのログが一つのログファイルにまとめられています.各行にどのポートのログであるかが残されていことに注意してください.

web/logs/access_log
192.168.65.1 - - [21/Sep/2025:00:32:20 +0000] "GET / HTTP/1.1" 200 664 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36" 8000
192.168.65.1 - - [21/Sep/2025:00:32:20 +0000] "GET /favicon.ico HTTP/1.1" 404 196 "http://localhost:8000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36" 8000
192.168.65.1 - - [21/Sep/2025:00:32:27 +0000] "GET / HTTP/1.1" 200 664 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36" 9000
192.168.65.1 - - [21/Sep/2025:00:32:27 +0000] "GET /favicon.ico HTTP/1.1" 404 196 "http://localhost:9000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36" 9000
192.168.65.1 - - [21/Sep/2025:00:32:32 +0000] "GET / HTTP/1.1" 200 662 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36" 80