勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

ホスト側Nginx & Apacheコンテナ環境にてWeb公開用ディレクトリ構造について

Podmanコンテナ環境の各種ディレクトリを整理したい。docker-compose.yml等のPodman関連ファイルやmpm_prefork.conf等の設定ファイルは「/opt/podman」ディレクトリにまとめたが、web公開領域部分の設定に難儀した。この辺りの整理方法をメモ。

 

ディレクトリ構造

以下のようなディレクトリ構造にしたい。

/var/www/html/podman/  # コンテナ側からマウントするディレクトリ
├── sub.test.com          # サブドメイン
│   └── public              # サブドメインの公開ディレクトリ
└── test.com                # メインドメイン
    ├── public               # メインドメインの公開ディレクトリ
    │   └── wordpress    # wordpress
    └── vendor              # composer関連
        └── composer

publicディレクトリをWeb公開用とし、vendor等composer関連のファイルは見えない形。

サブドメイン・別ドメインが増えた場合は/var/www/html/podman以下にディレクトリを作成する想定。また、ホスト側で何らかを表示させたい場合は普通に「/var/www/html」を使用する。

尚、docker-compose.yml等のPodman関連ファイルやmpm_prefork.conf等の設定ファイルは前述の通り「/opt/podman」にまとめる。

 

対応方法

ディレクトリ作成と権限設定

前述の通りディレクトリを作成し、公開用ファイルはpublic内に設置しておく。

また、以下で権限設定しておく。権限設定についての詳細は過去記事参照。

# コンテナ側の所有者・グループを設定
chown -R ftp_user:33 /var/www/html/podman

# 所有者・グループのパーミッションを設定
find /var/www/html/podman -type d -exec chmod 775 {} +
find /var/www/html/podman -type f -exec chmod 664 {} +

# 新規ファイル・フォルダ作成時にグループ権限を引き継ぐ(SGID)設定
find /var/www/html/podman -type d -exec chmod g+s {} +

Nginx設定(/etc/nginx/conf.d/custom.conf)

サブドメイン側はSSL未導入の想定。Let's Encryptで追加導入すればcustom.confにも自動で追記してくれる。

# =========================================================
# IPアドレス直接指定・未定義ドメインのアクセスを拒否
# =========================================================
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    server_name _;

    # SSL証明書の設定
    ssl_certificate     /etc/letsencrypt/live/test.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/test.com/privkey.pem;

    # レスポンスは何も返さずに接続を拒否
    return 444;
}


# =========================================================
# HTTP -> HTTPSリダイレクト
# =========================================================
server {
    listen 80;
    listen [::]:80;
    server_name test.com www.test.com;

    # すべてHTTPSへ301リダイレクト
    return 301 https://test.com$request_uri;
}

# =========================================================
# 3. wwwあり -> wwwなしへリダイレクト
# =========================================================
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.test.com;

    # SSL証明書の設定
    ssl_certificate     /etc/letsencrypt/live/test.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/test.com/privkey.pem;

    # wwwなしへ301リダイレクト
    return 301 https://test.com$request_uri;
}

# =========================================================
# コンテナへリバースプロキシ(メイン設定)
# =========================================================
server {

    # -----------------------------------------------------
    # 共通設定
    # -----------------------------------------------------

    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name test.com;

    # SSL証明書の設定
    ssl_certificate     /etc/letsencrypt/live/test.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/test.com/privkey.pem;

    # セキュリティヘッダーの設定
    add_header X-Frame-Options "SAMEORIGIN" always; 
    add_header X-Content-Type-Options "nosniff" always; 
    add_header X-XSS-Protection "1; mode=block" always; 

    # プロキシタイムアウトの設定
    proxy_connect_timeout 60s;
    proxy_send_timeout    60s;
    proxy_read_timeout    60s;

    # セキュリティ・TLS設定
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # クライアントからの最大アップロードサイズ
    client_max_body_size 20M;

    # ログ設定
    access_log /var/log/nginx/test.com.access.log;
    error_log  /var/log/nginx/test.com.error.log;

    # 公開用ディレクトリ
    root /var/www/html/podman/test.com/public;
    index index.php index.html;

    # -----------------------------------------------------
    # WordPress
    # -----------------------------------------------------

    # 優先前方一致指定
    location ^~ /wordpress/ {
        auth_basic "Input your ID and Password.";
        auth_basic_user_file /etc/nginx/.htpasswd;

        proxy_pass http://127.0.0.1:8080;
        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 ~ /(vendor|static_config|\.git) {
        deny all;
    }

    # Basic認証
    location /basic_auth/ {
        auth_basic "Input your ID and Password.";
        auth_basic_user_file /etc/nginx/.htpasswd;

        # 認証成功後にコンテナへ転送
        proxy_pass http://127.0.0.1:8080;
        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://127.0.0.1:8080;
        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;
    }
}

# =========================================================
# サブドメイン
# =========================================================
server {

    # -----------------------------------------------------
    # 共通設定
    # -----------------------------------------------------

    listen 80;
    listen [::]:80;
    server_name sub.test.com;

    # ログ設定
    access_log /var/log/nginx/sub.test.com.access.log;
    error_log  /var/log/nginx/sub.test.com.error.log;

    # 公開用ディレクトリ
    root /var/www/html/podman/sub.test.com/public; 
    index index.php index.html;

    # 通常のコンテナへのリバースプロキシ設定
    location / {
        proxy_pass http://127.0.0.1:8080;
        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;
    }
}

以下で構文チェックと再起動。

nginx -t
systemctl reload nginx

バーチャルホスト設定(/opt/podman/apache/vhost.conf)

LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so

<VirtualHost *:80>
    ServerName test.site
    ServerAlias www.test.site

    DocumentRoot /var/www/html/test.site/public

    <Directory /var/www/html/test.site/public>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

<VirtualHost *:80>
    ServerName mail.test.site
    ServerAlias www.mail.test.site

    DocumentRoot /var/www/html/mail.test.site/public

    <Directory /var/www/html/mail.test.site/public>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Docker Composeの設定ファイル(/opt/podman/docker-compose.yml)

services:

    # Webコンテナ用設定
    web:
        # コンテナ名
        container_name: web-container

        # 使用するイメージ
        image: web-server:latest

        # ホスト再起動時にコンテナを自動起動
        restart: always

        # ポートマッピング
        ports:
            - "8080:80"

        # ボリューム設定
        volumes:
            # マウントするディレクトリ
            - /var/www/html/podman:/var/www/html:Z
            # PHPとApacheの設定ファイル
            - /opt/podman/php/custom-php.ini:/usr/local/etc/php/conf.d/custom-php.ini:ro
            - /opt/podman/apache/mpm_prefork.conf:/etc/apache2/mods-available/mpm_prefork.conf:ro
            - /opt/podman/apache/vhost.conf:/etc/apache2/sites-available/000-default.conf:ro

        # 環境変数
        environment:
            # タイムゾーン
            TZ: "Asia/Tokyo"

        # ネットワーク設定
        networks:
            web-db-net:
                # IPアドレス固定
                ipv4_address: 10.89.10.2
            web-mailpit-net:

        # コンテナ配置時のリソース設定
        deploy:
            resources:
                limits:
                    # 割り当てメモリ
                    memory: 384M

        # コンテナ起動順序設定(db起動後にwebコンテナ起動)
        depends_on:
          - db

    # DBコンテナ用設定
    db:
        container_name: db-container
        image: mariadb:11.4
        restart: always
        volumes:
            # データの永続化マウント
            - /opt/podman/mariadb/data:/var/lib/mysql:Z
            # 設定ファイル
            - /opt/podman/mariadb/custom-mariadb.cnf:/etc/mysql/conf.d/custom-mariadb.cnf:ro
        environment:
            TZ: "Asia/Tokyo"
            # 各種DB接続用アカウント情報
            MARIADB_ROOT_PASSWORD: xxxxxxx
            MARIADB_DATABASE: xxxxxxx
            MARIADB_USER: xxxxxxx
            MARIADB_PASSWORD: xxxxxxx
        networks:
            web-db-net:
                ipv4_address: 10.89.10.5
        deploy:
            resources:
                limits:
                    memory: 256M

    # Mailpitコンテナ用設定
    mailpit:
        container_name: mailpit-container
        image: axllent/mailpit:latest
        # PHPで指定するポートは1025
        # ブラウザでアクセスするポートは19980
        ports:
            - "19925:1025"
            - "19980:8025"
        volumes:
            - /opt/podman/mailpit:/data:Z
            # Basic認証用
            - /opt/podman/mailpit/.htpasswd:/data/.htpasswd:ro
        environment:
            TZ: Asia/Tokyo
            MP_MAX_MESSAGES: 1000
            MP_DATABASE: /data/mailpit.db
            MP_SMTP_AUTH_ACCEPT_ANY: 1
            MP_SMTP_AUTH_ALLOW_INSECURE: 1
            MP_UI_AUTH_FILE: /data/.htpasswd
        networks:
            web-mailpit-net:
                ipv4_address: 10.89.20.5
        deploy:
            resources:
                limits:
                    memory: 32M

# ボリューム設定
volumes:
    mail-data:
        external: true

# ネットワーク設定
networks:
    web-db-net:
        driver: bridge
        ipam:
          config:
            - subnet: 10.89.10.0/24
    web-mailpit-net:
        driver: bridge
        ipam:
          config:
            - subnet: 10.89.20.0/24

以下で構文チェック -> コンテナ削除 -> コンテナ作成・起動する。

cd /opt/podman
podman compose config
podman compose down
podman compose up -d

以上で設定完了。

補足

composerでパッケージをインストールする場合

ドメインごとにインストールしたいので以下のような形で対応する。

podman exec \
    -w /var/www/html/test.site \
    web-container \
    composer require xxxxxx/xxxxxx

WordPressの特定ページ、機能が正常に動作しない場合

WordPressで以下のような症状が発生した。

  • ダッシュボードの記事投稿ページでブロックエディタだとがページが真っ白
  • ダッシュボードの特定のプラグインの設定画面が動作しない(何も表示されない)
  • フロント側でLightbox系プラグインが動作しない

ブラウザのデベロッパーツールを見るとJavaScript系のファイルが大量に403になっていた。

Nginx設定に問題があり以下の優先前方一致を指定することで403が改善され、正常に動作するようになった。

# 優先前方一致指定
location ^~ /wordpress/ {

Let's EncryptでSSL証明書を追加導入したい場合

サブドメインにもSSL証明書を導入したい場合、以下でまとめて導入しなおす。

certbot --nginx -d test.com -d www.test.com -d sub.test.com
certbot renew --dry-run

尚、別ドメインに導入したい場合は別途取り直す形がよい。

 

参考サイト

https://watashi.xyz/nginx-location/

 - Apache Nginx サーバー Podman

  関連記事

Podmanで導入したapache-phpに各種PHPモジュールを追加する方法
Podmanで導入したapache-phpに各種PHPモジュールを追加する方法

先日Podmanでapache-php8.4を導入したが、phpinfoで確認す ...

Podmanで作成したApache用コンテナにドメインを割り当て、ポート指定なしでアクセス可能にする方法
Podmanで作成したApache用コンテナにドメインを割り当て、ポート指定なしでアクセス可能にする方法

先日PodmanでWebサーバ用コンテナを作成したが、ブラウザからアクセスする際 ...

AlmaLinux8系にNginxを導入しPodmanコンテナに接続する方法
AlmaLinux8系にNginxを導入しPodmanコンテナに接続する方法

AlmaLinux8でホスト側はApacheからPodmanコンテナ環境に接続し ...

Podmanで導入したPHPの設定ファイル(php.ini)変更と高速化に関する設定方法
Podmanで導入したPHPの設定ファイル(php.ini)変更と高速化に関する設定方法

Podmanで導入したPHPの設定ファイル(php.ini)の内容を変更したい。 ...

ホスト側Nginx&コンテナ環境へのBasic認証、リダイレクト、リライト設定方法
ホスト側Nginx&コンテナ環境へのBasic認証、リダイレクト、リライト設定方法

先日コンテナのホスト側をApacheからNginxに変えたが、今度はコンテナ側へ ...