Apache HTTP Server

世界で最も使用されてきた実績豊富なWebサーバー。オールマイティーな機能、豊富なモジュール対応、PHP等のスクリプト言語をデフォルトサポート。

アプリケーションサーバーWebサーバーApacheオープンソースモジュールPHP実績

アプリケーションサーバー

Apache HTTP Server

概要

Apache HTTP Server(httpd)は、世界で最も使用されてきた実績豊富なWebサーバーです。オールマイティーな機能と豊富なモジュール対応、PHP等のスクリプト言語をデフォルトサポートしています。長年の実績を持つWebサーバーとして、現在もNginxと二強を形成しており、NginxとApacheの組み合わせ構成が一般的です。平均的なパフォーマンスながら多機能で、Nginxより重いという特徴があります。

詳細

Apache HTTP Serverは1995年にリリースされ、インターネットの発展と共に成長してきた最も歴史のあるWebサーバーの一つです。Apache Software Foundationによって開発・維持され、オープンソースWebサーバーの代表格として、数多くのWebサイトで使用されています。モジュラーアーキテクチャにより、必要に応じて機能を追加・削除でき、柔軟性の高いサーバー構築が可能です。

主要な技術的特徴

  • モジュラーアーキテクチャ: 動的なモジュール追加・削除
  • バーチャルホスト: 複数サイトの効率的なホスティング
  • 認証・認可: 豊富な認証メカニズム
  • SSL/TLS サポート: 強力な暗号化機能
  • リライト機能: URL操作とリダイレクト
  • 豊富な設定オプション: 詳細なカスタマイズが可能

用途

  • 静的Webサイトホスティング
  • 動的Webアプリケーション(PHP、Perl、Python)
  • リバースプロキシ・ロードバランサー
  • SSL/TLS終端
  • コンテンツ管理システム(CMS)
  • レガシーアプリケーション

メリット・デメリット

メリット

  • 豊富な機能: オールインワンのWebサーバーソリューション
  • 安定性: 長年の運用実績による高い安定性
  • モジュール豊富: 膨大な数のサードパーティモジュール
  • 詳細な設定: きめ細かい制御が可能
  • ドキュメント充実: 豊富な技術情報とコミュニティサポート
  • 標準サポート: 多くのLinuxディストリビューションで標準

デメリット

  • パフォーマンス: Nginxと比較して低いパフォーマンス
  • メモリ使用量: プロセス・スレッドベースによる高いメモリ消費
  • 設定複雑性: 多機能ゆえの設定の複雑さ
  • C10K問題: 大量同時接続の処理に制限
  • 起動時間: 多くのモジュール読み込みによる長い起動時間

インストール・基本設定

前提条件

# システム要件確認
uname -a
cat /etc/os-release
free -h
df -h

インストール方法

Ubuntu/Debian

# パッケージ更新
sudo apt update
sudo apt upgrade

# Apache インストール
sudo apt install apache2

# 追加モジュール
sudo apt install apache2-utils
sudo apt install libapache2-mod-php
sudo apt install libapache2-mod-ssl

CentOS/RHEL

# パッケージ更新
sudo yum update
# または
sudo dnf update

# Apache インストール
sudo yum install httpd
# または
sudo dnf install httpd

# 追加パッケージ
sudo yum install httpd-tools mod_ssl

ソースコンパイル

# 依存関係のインストール
# Ubuntu/Debian
sudo apt-get install build-essential libpcre3-dev libssl-dev zlib1g-dev

# CentOS/RHEL
sudo yum groupinstall "Development Tools"
sudo yum install pcre-devel openssl-devel zlib-devel

# Apache ソースダウンロード
wget https://downloads.apache.org/httpd/httpd-2.4.58.tar.gz
tar -xzf httpd-2.4.58.tar.gz
cd httpd-2.4.58

# 設定とコンパイル
./configure \
    --prefix=/etc/apache2 \
    --enable-mods-shared=all \
    --enable-ssl \
    --enable-rewrite \
    --enable-headers \
    --enable-expires \
    --enable-deflate \
    --enable-proxy \
    --enable-proxy-http \
    --enable-proxy-balancer \
    --with-ssl \
    --with-pcre

make && sudo make install

基本設定

メイン設定ファイル(httpd.conf/apache2.conf)

# /etc/apache2/apache2.conf または /etc/httpd/conf/httpd.conf

# サーバールート設定
ServerRoot "/etc/apache2"
PidFile ${APACHE_PID_FILE}

# タイムアウト設定
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

# プロセス・スレッド設定(MPM prefork)
<IfModule mpm_prefork_module>
    StartServers          8
    MinSpareServers       5
    MaxSpareServers      20
    ServerLimit         256
    MaxRequestWorkers   256
    MaxConnectionsPerChild  0
</IfModule>

# プロセス・スレッド設定(MPM worker)
<IfModule mpm_worker_module>
    StartServers          3
    MinSpareThreads      75
    MaxSpareThreads     250
    ThreadsPerChild      25
    MaxRequestWorkers   400
    MaxConnectionsPerChild  0
</IfModule>

# プロセス・スレッド設定(MPM event)
<IfModule mpm_event_module>
    StartServers          3
    MinSpareThreads      75
    MaxSpareThreads     250
    ThreadsPerChild      25
    MaxRequestWorkers   400
    MaxConnectionsPerChild  0
</IfModule>

# 基本的なディレクトリ設定
<Directory />
    Options FollowSymLinks
    AllowOverride None
    Require all denied
</Directory>

<Directory "/var/www/">
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

# ログ設定
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
CustomLog ${APACHE_LOG_DIR}/access.log combined

# セキュリティ設定
ServerTokens Prod
ServerSignature Off

# デフォルト文字コード
AddDefaultCharset UTF-8

# ファイル形式設定
<IfModule mod_mime.c>
    TypesConfig /etc/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
    AddType application/x-bzip2 .bz2
</IfModule>

# モジュール読み込み
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule headers_module modules/mod_headers.so
LoadModule expires_module modules/mod_expires.so
LoadModule deflate_module modules/mod_deflate.so

# インクルード設定
IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf

バーチャルホスト設定

# /etc/apache2/sites-available/example.com.conf

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com/public_html
    
    # ログ設定
    ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
    CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined
    
    # ディレクトリ設定
    <Directory "/var/www/example.com/public_html">
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # セキュリティヘッダー
    <IfModule mod_headers.c>
        Header always set X-Frame-Options "SAMEORIGIN"
        Header always set X-Content-Type-Options "nosniff"
        Header always set X-XSS-Protection "1; mode=block"
        Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    </IfModule>
    
    # 圧縮設定
    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/plain
        AddOutputFilterByType DEFLATE text/html
        AddOutputFilterByType DEFLATE text/xml
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE application/xml
        AddOutputFilterByType DEFLATE application/xhtml+xml
        AddOutputFilterByType DEFLATE application/rss+xml
        AddOutputFilterByType DEFLATE application/javascript
        AddOutputFilterByType DEFLATE application/x-javascript
    </IfModule>
    
    # キャッシュ設定
    <IfModule mod_expires.c>
        ExpiresActive On
        ExpiresByType image/jpg "access plus 1 month"
        ExpiresByType image/jpeg "access plus 1 month"
        ExpiresByType image/gif "access plus 1 month"
        ExpiresByType image/png "access plus 1 month"
        ExpiresByType text/css "access plus 1 month"
        ExpiresByType application/pdf "access plus 1 month"
        ExpiresByType text/javascript "access plus 1 month"
        ExpiresByType application/javascript "access plus 1 month"
        ExpiresByType application/x-javascript "access plus 1 month"
        ExpiresByType application/x-shockwave-flash "access plus 1 month"
        ExpiresByType image/x-icon "access plus 1 year"
        ExpiresDefault "access plus 2 days"
    </IfModule>
</VirtualHost>

.htaccess設定例

# /var/www/example.com/public_html/.htaccess

# URL リライト
RewriteEngine On

# HTTPS リダイレクト
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# WWW リダイレクト
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

# 綺麗なURL
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]

# セキュリティ設定
<Files .htaccess>
    Require all denied
</Files>

<Files ~ "^\.">
    Require all denied
</Files>

# MIME タイプ
AddType application/x-httpd-php .php
AddType text/css .css
AddType application/javascript .js

# エラードキュメント
ErrorDocument 404 /error/404.html
ErrorDocument 500 /error/500.html

# ディレクトリブラウジング無効
Options -Indexes

# ファイルアップロード制限
LimitRequestBody 10485760

# ブラウザキャッシュ
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/jpg "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
</IfModule>

SSL/TLS設定

SSL モジュールの有効化

# Ubuntu/Debian
sudo a2enmod ssl
sudo a2enmod rewrite
sudo a2enmod headers

# CentOS/RHEL - 設定ファイルで LoadModule を確認
LoadModule ssl_module modules/mod_ssl.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule headers_module modules/mod_headers.so

SSL バーチャルホスト設定

# /etc/apache2/sites-available/example.com-ssl.conf

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com/public_html
    
    # SSL 設定
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/example.com.crt
    SSLCertificateKeyFile /etc/ssl/private/example.com.key
    SSLCertificateChainFile /etc/ssl/certs/intermediate.crt
    
    # SSL プロトコル設定
    SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
    SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
    SSLHonorCipherOrder off
    SSLSessionTickets off
    
    # HSTS ヘッダー
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    
    # OCSP Stapling
    SSLUseStapling On
    SSLStaplingResponderTimeout 5
    SSLStaplingReturnResponderErrors off
    SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)
    
    # ログ設定
    ErrorLog ${APACHE_LOG_DIR}/example.com_ssl_error.log
    CustomLog ${APACHE_LOG_DIR}/example.com_ssl_access.log combined
    
    # その他の設定は HTTP バーチャルホストと同様
    <Directory "/var/www/example.com/public_html">
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
</IfModule>

# HTTP から HTTPS へのリダイレクト
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    RewriteEngine On
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>

Let's Encrypt 設定

# Certbot インストール
# Ubuntu/Debian
sudo apt install certbot python3-certbot-apache

# CentOS/RHEL
sudo yum install certbot python3-certbot-apache

# 証明書取得
sudo certbot --apache -d example.com -d www.example.com

# 自動更新設定
sudo crontab -e
# 以下を追加
0 12 * * * /usr/bin/certbot renew --quiet

パフォーマンス最適化

MPM(Multi-Processing Module)選択

# MPM Event(推奨)
<IfModule mpm_event_module>
    StartServers             3
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      400
    MaxConnectionsPerChild   0
    ListenBacklog          511
    ThreadStackSize      8388608
</IfModule>

# MPM Worker
<IfModule mpm_worker_module>
    StartServers             3
    MaxRequestWorkers      400
    MinSpareThreads         25
    MaxSpareThreads         75
    ThreadsPerChild         25
    MaxConnectionsPerChild   0
</IfModule>

# MPM Prefork(PHP使用時)
<IfModule mpm_prefork_module>
    StartServers             8
    MinSpareServers          5
    MaxSpareServers         20
    ServerLimit            256
    MaxRequestWorkers      256
    MaxConnectionsPerChild   0
</IfModule>

キャッシュ設定

# mod_cache 設定
<IfModule mod_cache.c>
    CacheQuickHandler off
    CacheLock on
    CacheLockPath /tmp/mod_cache-lock
    CacheLockMaxAge 5
    CacheIgnoreHeaders Set-Cookie
</IfModule>

# Disk Cache
<IfModule mod_cache_disk.c>
    CacheRoot /var/cache/apache2/mod_cache_disk
    CacheEnable disk /
    CacheDirLevels 2
    CacheDirLength 1
    CacheMaxFileSize 1000000
    CacheDefaultExpire 3600
</IfModule>

# Memory Cache
<IfModule mod_cache_socache.c>
    CacheEnable socache /
    CacheSocache shmcb
    CacheSocacheMaxSize 512000
</IfModule>

圧縮最適化

# mod_deflate 詳細設定
<IfModule mod_deflate.c>
    # 圧縮レベル設定
    DeflateCompressionLevel 6
    
    # 圧縮対象
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
    AddOutputFilterByType DEFLATE image/svg+xml
    
    # 圧縮除外(小さなファイル、画像など)
    SetEnvIfNoCase Request_URI \
        \.(?:gif|jpe?g|png|zip|gz|bz2)$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI \
        \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
    
    # 古いブラウザ対応
    BrowserMatch ^Mozilla/4 gzip-only-text/html
    BrowserMatch ^Mozilla/4\.0[678] no-gzip
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
</IfModule>

リバースプロキシ・ロードバランシング

プロキシモジュール設定

# モジュール有効化
# Ubuntu/Debian
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests

# CentOS/RHEL - 設定ファイルで確認
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so

ロードバランサー設定

# ロードバランサー設定
<Proxy balancer://mycluster>
    BalancerMember http://192.168.1.10:8080 route=1
    BalancerMember http://192.168.1.11:8080 route=2
    BalancerMember http://192.168.1.12:8080 route=3 status=+H
    ProxySet lbmethod=byrequests
</Proxy>

<VirtualHost *:80>
    ServerName loadbalancer.example.com
    
    # ロードバランサーへのプロキシ
    ProxyPreserveHost On
    ProxyPass /balancer-manager !
    ProxyPass / balancer://mycluster/
    ProxyPassReverse / balancer://mycluster/
    
    # バランサー管理画面
    <Location "/balancer-manager">
        SetHandler balancer-manager
        Require ip 192.168.1
        Require ip 127.0.0.1
    </Location>
    
    # ヘルスチェック
    ProxyPass /health !
    <Location "/health">
        SetHandler server-status
        Require local
    </Location>
</VirtualHost>

リバースプロキシ設定

<VirtualHost *:80>
    ServerName api.example.com
    
    # リバースプロキシ設定
    ProxyPreserveHost On
    ProxyRequests Off
    
    # バックエンドアプリケーション
    ProxyPass /api/ http://backend.local:3000/
    ProxyPassReverse /api/ http://backend.local:3000/
    
    # 静的ファイルは直接配信
    ProxyPass /static/ !
    ProxyPass /images/ !
    
    # WebSocket サポート
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*) ws://backend.local:3000/$1 [P,L]
    
    # ヘッダー設定
    ProxyPassReverse / http://backend.local:3000/
    ProxyPassReverseAdjust On
    
    <Proxy *>
        Require all granted
    </Proxy>
</VirtualHost>

セキュリティ設定

基本セキュリティ

# セキュリティ設定
ServerTokens Prod
ServerSignature Off

# 不要なメソッド無効化
<LimitExcept GET POST HEAD>
    Require all denied
</LimitExcept>

# 機密ファイル保護
<FilesMatch "^\.">
    Require all denied
</FilesMatch>

<FilesMatch "\.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$">
    Require all denied
</FilesMatch>

# ディレクトリトラバーサル防止
RewriteEngine On
RewriteCond %{THE_REQUEST} \s[^?]*\/{2,} [NC]
RewriteRule ^.*$ - [F,L]

# セキュリティヘッダー
<IfModule mod_headers.c>
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
    Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>

認証・認可設定

# Basic 認証
<Directory "/var/www/admin">
    AuthType Basic
    AuthName "Admin Area"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Directory>

# IP制限
<Directory "/var/www/private">
    <RequireAll>
        Require ip 192.168.1
        Require ip 10.0.0
        Require local
    </RequireAll>
</Directory>

# 時間制限
<Directory "/var/www/timebasedaccess">
    <RequireAll>
        Require expr %{TIME_HOUR} >= 09
        Require expr %{TIME_HOUR} <= 17
        Require expr %{TIME_WDAY} >= 1
        Require expr %{TIME_WDAY} <= 5
    </RequireAll>
</Directory>

攻撃対策

# DDoS 対策
<IfModule mod_evasive24.c>
    DOSHashTableSize    2048
    DOSPageCount        2
    DOSPageInterval     1
    DOSSiteCount        50
    DOSSiteInterval     1
    DOSBlockingPeriod   600
    DOSLogDir           /var/log/apache2/evasive
</IfModule>

# Rate Limiting
<IfModule mod_qos.c>
    QS_SrvMaxConn 80
    QS_SrvMaxConnClose 180
    QS_SrvMaxConnPerIP 10
    QS_SrvMinDataRate 150 1200
</IfModule>

# SQL インジェクション対策
<IfModule mod_security2.c>
    SecRuleEngine On
    SecDataDir /tmp
    Include /etc/apache2/modsecurity.d/*.conf
    Include /etc/apache2/modsecurity.d/activated_rules/*.conf
</IfModule>

監視・ログ・メンテナンス

ステータス監視設定

<IfModule mod_status.c>
    <Location "/server-status">
        SetHandler server-status
        Require local
        Require ip 192.168.1
    </Location>
    
    <Location "/server-info">
        SetHandler server-info
        Require local
        Require ip 192.168.1
    </Location>
    
    ExtendedStatus On
</IfModule>

ログ設定

# カスタムログフォーマット
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %D" combined_with_time
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined_with_forwarded

# 仮想ホスト別ログ
CustomLog ${APACHE_LOG_DIR}/access.log combined
ErrorLog ${APACHE_LOG_DIR}/error.log

# ログローテーション(logrotate設定)
# /etc/logrotate.d/apache2
/var/log/apache2/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 640 root adm
    sharedscripts
    postrotate
        if /etc/init.d/apache2 status > /dev/null ; then \
            /etc/init.d/apache2 reload > /dev/null; \
        fi;
    endscript
    prerotate
        if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
            run-parts /etc/logrotate.d/httpd-prerotate; \
        fi; \
    endscript
}

メンテナンススクリプト

#!/bin/bash
# apache-maintenance.sh

LOG_DIR="/var/log/apache2"
BACKUP_DIR="/backup/apache2"
DATE=$(date +%Y%m%d_%H%M%S)

# 設定テスト
echo "Testing Apache configuration..."
if ! apache2ctl configtest; then
    echo "Configuration test failed!"
    exit 1
fi

# バックアップ作成
echo "Creating backup..."
mkdir -p $BACKUP_DIR
tar -czf $BACKUP_DIR/apache_config_$DATE.tar.gz \
    /etc/apache2 \
    /var/www

# ログ分析
echo "Analyzing logs..."
echo "Top 10 IP addresses:"
awk '{print $1}' $LOG_DIR/access.log | sort | uniq -c | sort -nr | head -10

echo "Top 10 requested URLs:"
awk '{print $7}' $LOG_DIR/access.log | sort | uniq -c | sort -nr | head -10

echo "HTTP status codes:"
awk '{print $9}' $LOG_DIR/access.log | sort | uniq -c | sort -nr

# エラーログチェック
echo "Recent errors:"
tail -20 $LOG_DIR/error.log

echo "Maintenance completed successfully"

Docker・コンテナ化

Dockerfile

FROM httpd:2.4-alpine

# 必要なパッケージインストール
RUN apk add --no-cache \
    apache2-ssl \
    apache2-mod-rewrite \
    apache2-utils

# 設定ファイルコピー
COPY ./config/httpd.conf /usr/local/apache2/conf/httpd.conf
COPY ./config/vhost.conf /usr/local/apache2/conf/extra/httpd-vhosts.conf

# SSL証明書
COPY ./ssl/ /usr/local/apache2/conf/ssl/

# Webコンテンツ
COPY ./html/ /usr/local/apache2/htdocs/

# ログディレクトリ
RUN mkdir -p /usr/local/apache2/logs

# ポート公開
EXPOSE 80 443

# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD httpd -t || exit 1

# 非rootユーザー
RUN adduser -D -s /bin/sh apache
USER apache

CMD ["httpd-foreground"]

docker-compose.yml

version: '3.8'

services:
  apache:
    build: .
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./html:/usr/local/apache2/htdocs
      - ./config:/usr/local/apache2/conf/extra
      - ./logs:/usr/local/apache2/logs
      - ./ssl:/usr/local/apache2/conf/ssl
    environment:
      - APACHE_LOG_LEVEL=warn
    restart: unless-stopped
    
  php-fpm:
    image: php:8.2-fpm-alpine
    volumes:
      - ./html:/var/www/html
    restart: unless-stopped

参考ページ