コンテナ - Nginx
概要
Nginxは、高性能なWebサーバおよびリバースプロキシサーバである。
Dockerコンテナとして実行することにより、開発環境や本番環境で簡単に導入できる。
静的ファイルの高速配信、リバースプロキシ、ロードバランサー等の様々な用途に適している。
Nginxコンテナの主な機能を以下に示す。
- HTTPサーバ機能
- デフォルト : 80番ポート
- HTTPSサーバ機能
- デフォルト : 443番ポート
- 静的ファイルの高速配信
- リバースプロキシ機能
- ロードバランサー機能
- キャッシュ機能
Containerfile
Containerfileを作成する。
FROM nginx:latest
COPY ./html/ /usr/share/nginx/html/
COPY ./nginx.conf /etc/nginx/nginx.conf
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
コンテナイメージをビルドする。
podman build -t nginx:custom -f Containerfile .
ビルドしたイメージからコンテナを実行する。
podman run -d \ --name nginx \ -p 0.0.0.0:8080:80 \ -v ./html:/usr/share/nginx/html/ \ nginx:custom
Compose
Composeファイルを作成する。
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "0.0.0.0:8080:80" # HTTP用(すべてのIPでリッスン)
- "0.0.0.0:8443:443" # HTTPS用(すべてのIPでリッスン)
volumes:
- ./html:/usr/share/nginx/html/
- ./nginx-conf:/etc/nginx/conf.d/
restart: unless-stopped
volumes:
nginx-data:
Composeファイルを実行して、コンテナを作成および実行する。
podman-compose up -d # または podman-compose -f <Composeファイル名> up -d
アクセス方法
コンテナが起動した後、以下に示すURLでアクセスできる。
- HTTP
- HTTPS
デフォルトページの確認
コンテナ起動後、Webブラウザでアクセスすると Welcome to nginx! というメッセージが表示される。
カスタムHTMLの配置
ホスト側のディレクトリ (例 : ./html) にHTMLファイルを配置することにより、独自のコンテンツを表示できる。
mkdir -p html echo "<h1>Hello from Nginx Container</h1>" > html/index.html
設定ファイルのカスタマイズ
Nginxの設定ファイルをカスタマイズする場合は、nginx.confやサイト設定ファイルをホスト側に配置する。
設定ファイルのコピー
実行中のコンテナから設定ファイルをコピーする。
podman cp nginx:/etc/nginx/nginx.conf ./nginx-conf/nginx.conf
サイト設定の追加
カスタム設定ファイルを作成する例を以下に示す。
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 404 /404.html;
location = /404.html {
internal;
}
}
設定の反映
設定ファイルを編集後、コンテナを再起動する。
podman restart nginx
または、設定の構文チェックとリロードを行う。
podman exec nginx nginx -t podman exec nginx nginx -s reload
仮想ホストの設定
複数のサイトを1つのNginxコンテナで運用する場合、server ブロックを複数定義する。
仮想ホスト設定ファイルの作成
各サイト用の設定ファイルを作成する。
- site1.confファイル
server {
listen 80;
server_name example.com www.example.com;
root /usr/share/nginx/html/example.com;
index index.html index.htm;
access_log /var/log/nginx/example.com-access.log;
error_log /var/log/nginx/example.com-error.log;
location / {
try_files $uri $uri/ =404;
}
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
- site2.confファイル
server {
listen 80;
server_name test.local;
root /usr/share/nginx/html/test.local;
index index.html index.htm;
access_log /var/log/nginx/test.local-access.log;
error_log /var/log/nginx/test.local-error.log;
location / {
try_files $uri $uri/ =404;
}
}
Composeファイルでの設定例
仮想ホストを使用する場合のCompose設定を以下に示す。
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "0.0.0.0:8080:80"
volumes:
- ./sites/example.com:/usr/share/nginx/html/example.com
- ./sites/test.local:/usr/share/nginx/html/test.local
- ./conf.d:/etc/nginx/conf.d
- nginx-logs:/var/log/nginx
restart: unless-stopped
volumes:
nginx-logs:
SSL / TLS設定
HTTPS通信を有効化するための設定を行う。
SSL証明書の準備
自己署名証明書を作成する例を以下に示す。
mkdir -p ./ssl openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout ./ssl/server.key \ -out ./ssl/server.crt \ -subj "/C=JP/ST=Tokyo/L=Tokyo/O=MyCompany/CN=localhost"
SSL設定ファイルの作成
HTTPS用のserver設定を作成する。
server {
listen 443 ssl http2;
server_name localhost;
root /usr/share/nginx/html;
index index.html index.htm;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
access_log /var/log/nginx/ssl-access.log;
error_log /var/log/nginx/ssl-error.log;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80;
server_name localhost;
return 301 https://$server_name$request_uri;
}
SSL有効化のCompose設定
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "0.0.0.0:8080:80"
- "0.0.0.0:8443:443"
volumes:
- ./html:/usr/share/nginx/html
- ./ssl:/etc/nginx/ssl
- ./conf.d:/etc/nginx/conf.d
restart: unless-stopped
Let's Encryptの使用
本番環境で無料SSL証明書を使用する場合の設定例を示す。
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "0.0.0.0:80:80"
- "0.0.0.0:443:443"
volumes:
- ./html:/usr/share/nginx/html
- ./conf.d:/etc/nginx/conf.d
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
restart: unless-stopped
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- certbot-etc:/etc/letsencrypt
- certbot-var:/var/lib/letsencrypt
- ./html:/usr/share/nginx/html
command: certonly --webroot --webroot-path=/usr/share/nginx/html --email admin@example.com --agree-tos --no-eff-email -d example.com -d www.example.com
volumes:
certbot-etc:
certbot-var:
リバースプロキシの設定
Nginxをリバースプロキシとして使用する詳細な設定例を以下に示す。
基本的なリバースプロキシ設定
server {
listen 80;
server_name proxy.example.com;
location / {
proxy_pass http://backend: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;
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
}
}
WebSocketプロキシの設定
WebSocketアプリケーション用のプロキシ設定を以下に示す。
server {
listen 80;
server_name ws.example.com;
location / {
proxy_pass http://websocket-backend:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_read_timeout 86400;
}
}
パスベースルーティング
異なるパスを異なるバックエンドにルーティングする設定を以下に示す。
server {
listen 80;
server_name app.example.com;
location /api/ {
proxy_pass http://api-backend:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /admin/ {
proxy_pass http://admin-backend:4000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
proxy_pass http://frontend:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
ロードバランサーの設定
複数のバックエンドサーバに負荷分散する設定を以下に示す。
ラウンドロビン方式
デフォルトの負荷分散方式 (ラウンドロビン) の設定を以下に示す。
upstream backend_servers {
server backend1:8000;
server backend2:8000;
server backend3:8000;
}
server {
listen 80;
server_name lb.example.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
重み付きロードバランシング
サーバごとに重みを設定する例を以下に示す。
upstream backend_servers {
server backend1:8000 weight=3;
server backend2:8000 weight=2;
server backend3:8000 weight=1;
}
server {
listen 80;
server_name lb.example.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
}
}
IPハッシュ方式
クライアントIPに基づいて同じサーバに振り分ける設定を以下に示す。
upstream backend_servers {
ip_hash;
server backend1:8000;
server backend2:8000;
server backend3:8000;
}
server {
listen 80;
server_name lb.example.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
}
}
ヘルスチェックの設定
バックエンドサーバの状態を監視する設定を以下に示す。
upstream backend_servers {
server backend1:8000 max_fails=3 fail_timeout=30s;
server backend2:8000 max_fails=3 fail_timeout=30s;
server backend3:8000 backup;
}
server {
listen 80;
server_name lb.example.com;
location / {
proxy_pass http://backend_servers;
proxy_next_upstream error timeout http_500 http_502 http_503;
proxy_connect_timeout 5s;
proxy_read_timeout 10s;
}
}
PHP-FPMとの連携
NginxコンテナでPHPアプリケーションを動作させる場合、PHP-FPMと連携する設定例を示す。
Composeファイルでの連携設定
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "0.0.0.0:8080:80"
volumes:
- ./html:/usr/share/nginx/html
- ./conf.d:/etc/nginx/conf.d
depends_on:
- php-fpm
restart: unless-stopped
php-fpm:
image: php:8.2-fpm
container_name: php-fpm
volumes:
- ./html:/usr/share/nginx/html
restart: unless-stopped
Nginx側のPHP設定
PHP-FPMと連携するため、serverセクションの設定を以下に示す。
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
}
location ~ /\.ht {
deny all;
}
}
WordPressの設定例
WordPressを運用する場合の最適化された設定を以下に示す。
server {
listen 80;
server_name wordpress.example.com;
root /usr/share/nginx/html;
index index.php;
client_max_body_size 100M;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
log_not_found off;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
log_not_found off;
access_log off;
}
location ~ /\.ht {
deny all;
}
}
キャッシュの設定
Nginxのキャッシュ機能を使用してパフォーマンスを向上させる設定を示す。
プロキシキャッシュの設定
リバースプロキシでのキャッシュ設定を以下に示す。
- nginx.confに追加する設定
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
server_name cache.example.com;
location / {
proxy_cache my_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://backend:8000;
proxy_set_header Host $host;
}
}
}
FastCGIキャッシュの設定
PHP-FPM用のキャッシュ設定を以下に示す。
http {
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=php_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
server_name php-cache.example.com;
root /usr/share/nginx/html;
index index.php;
set $skip_cache 0;
if ($request_method = POST) {
set $skip_cache 1;
}
if ($query_string != "") {
set $skip_cache 1;
}
location ~ \.php$ {
fastcgi_cache php_cache;
fastcgi_cache_valid 200 60m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-FastCGI-Cache $upstream_cache_status;
fastcgi_pass php-fpm:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
}
静的ファイルのキャッシュ設定
ブラウザキャッシュを最適化する設定を以下に示す。
location ~* \.(jpg|jpeg|png|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location ~* \.(css|js)$ {
expires 1M;
add_header Cache-Control "public";
}
location ~* \.(woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
圧縮の設定
Gzip圧縮を有効化してデータ転送量を削減する設定を示す。
Gzip圧縮の基本設定
nginx.confファイル、または、サイト設定ファイルに以下を追加する。
http {
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
gzip_disable "msie6";
gzip_min_length 256;
}
Brotli圧縮の設定
高効率なBrotli圧縮を使用することができる。
http {
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
}
レート制限の設定
DDoS攻撃やブルートフォース攻撃を防ぐためのレート制限設定を示す。
リクエストレート制限
http {
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
listen 80;
server_name ratelimit.example.com;
location / {
limit_req zone=mylimit burst=20 nodelay;
proxy_pass http://backend:8000;
}
location /api/ {
limit_req zone=mylimit burst=5 nodelay;
proxy_pass http://api-backend:3000/;
}
}
}
接続数制限
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
listen 80;
server_name connlimit.example.com;
location /download/ {
limit_conn addr 1;
limit_rate 500k;
root /usr/share/nginx/html;
}
}
}
ログの管理
Nginxのアクセスログとエラーログを管理する方法を示す。
ログの確認
コンテナ内のログをリアルタイムで確認する。
# アクセスログ podman exec nginx tail -f /var/log/nginx/access.log # エラーログ podman exec nginx tail -f /var/log/nginx/error.log
または、podman logsコマンドでコンテナログを確認する。
podman logs -f nginx
カスタムログフォーマット
詳細なログフォーマットを定義する例を以下に示す。
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format detailed '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" rt=$request_time '
'uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"';
access_log /var/log/nginx/access.log detailed;
}
ログのローテーション
ログファイルをホスト側で管理する場合の設定を以下に示す。
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "0.0.0.0:8080:80"
volumes:
- ./html:/usr/share/nginx/html
- ./logs:/var/log/nginx
restart: unless-stopped
logrotateを使用したログローテーション設定を作成する。
- /etc/logrotate.d/nginx ファイルの例
/path/to/logs/*.log { daily rotate 14 compress delaycompress notifempty create 0640 nginx nginx sharedscripts postrotate podman exec nginx nginx -s reopen endscript }
条件付きロギング
特定の条件でログを記録しないように設定する例を以下に示す。
map $request_uri $loggable {
~^/health$ 0;
~^/metrics$ 0;
default 1;
}
server {
listen 80;
access_log /var/log/nginx/access.log combined if=$loggable;
location /health {
return 200 "OK\n";
add_header Content-Type text/plain;
}
}
パフォーマンスチューニング
Nginxのパフォーマンスを最適化するための設定を示す。
ワーカープロセスの最適化
nginx.confファイルにおいて、以下に示す設定を行う。
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 100;
reset_timedout_connection on;
client_body_timeout 10;
send_timeout 10;
}
バッファサイズの最適化
http {
client_body_buffer_size 128k;
client_max_body_size 10m;
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
output_buffers 1 32k;
postpone_output 1460;
}
ファイルディスクリプタキャッシュ
http {
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}
セキュリティ設定
Nginxのセキュリティを強化するための設定を示す。
サーバ情報の非表示
レスポンスヘッダからNginxのバージョン情報を削除する。
http {
server_tokens off;
}
セキュリティヘッダの追加
セキュリティ関連のHTTPヘッダを追加する。
server {
listen 80;
server_name secure.example.com;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
Basic認証の設定
特定のディレクトリにBasic認証を設定する。
パスワードファイルを作成する。
podman exec -it nginx sh apk add apache2-utils htpasswd -c /etc/nginx/.htpasswd <ユーザ名>
Nginx設定ファイルに認証を追加する。
location /admin {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://admin-backend:4000;
}
IPアドレスによるアクセス制限
特定のIPアドレスからのみアクセスを許可する設定を以下に示す。
location /admin {
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
proxy_pass http://admin-backend:4000;
}
機密ファイルへのアクセス制限
特定のファイルやディレクトリへのアクセスを制限する。
location ~ /\.(?!well-known) {
deny all;
}
location ~* \.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$ {
deny all;
}
トラブルシューティング
コンテナが起動しない
設定ファイルの構文エラーを確認する。
podman logs nginx podman exec nginx nginx -t
ポート番号の競合
他のサービスとポート番号が競合している場合、別のポートを使用する。
podman run -d --name nginx -p 0.0.0.0:8081:80 nginx:latest
502 Bad Gateway エラー
プロキシ設定でバックエンドサーバへの接続を確認する。
# バックエンドサーバの稼働確認 podman exec nginx curl http://backend:8000 # Nginxのエラーログを確認 podman exec nginx tail -f /var/log/nginx/error.log
413 Request Entity Too Large エラー
アップロードファイルサイズの上限を増やす。
http {
client_max_body_size 100M;
}
パーミッションエラー
ボリュームマウントしたディレクトリのパーミッションを確認する。
chmod -R 755 ./html chown -R 101:101 ./html
タイムアウトエラー
プロキシタイムアウト設定を調整する。
location / {
proxy_pass http://backend:8000;
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
ファイヤーウォールの設定
同一ネットワーク上の外部PCからアクセスする場合は、ファイヤーウォールのポート開放を行う。
Linux
# Firewalldを使用している場合 sudo firewall-cmd --permanent --add-port=8080/tcp sudo firewall-cmd --permanent --add-port=8443/tcp sudo firewall-cmd --reload # UFWを使用している場合 sudo ufw allow 8080/tcp sudo ufw allow 8443/tcp
Windows 11
PowerShellを管理者権限で起動して、以下に示すコマンドを実行する。
HTTPポートの受信ルールを追加する。
New-NetFirewallRule -DisplayName "Nginx HTTP" -Direction Inbound -Protocol TCP -LocalPort <ポート番号 例: 8080> -Action Allow
HTTPSポートの受信ルールを追加する。
New-NetFirewallRule -DisplayName "Nginx HTTPS" -Direction Inbound -Protocol TCP -LocalPort <ポート番号 例: 8443> -Action Allow
正常にポート開放が行われているかどうかを確認する場合、別PCからPowerShellを起動して、以下のコマンドを実行する。
Test-NetConnection -ComputerName <Windows PCのIPアドレス> -Port <ポート番号 例: 8080> Test-NetConnection -ComputerName <Windows PCのIPアドレス> -Port <ポート番号 例: 8443>
ファイアウォールルールを削除する場合は、以下に示すコマンドを実行する。
# HTTPポートのルール削除 Remove-NetFirewallRule -DisplayName "Nginx HTTP" -ErrorAction SilentlyContinue # HTTPSポートのルール削除 Remove-NetFirewallRule -DisplayName "Nginx HTTPS" -ErrorAction SilentlyContinue
Windows 10
PowerShellを管理者権限で起動して、以下に示すコマンドを実行する。
HTTPポートの受信ルールを追加する。
New-NetFirewallRule -DisplayName "Nginx HTTP" -Direction Inbound -Protocol TCP -LocalPort <ポート番号 例: 8080> -Action Allow
HTTPSポートの受信ルールを追加する。
New-NetFirewallRule -DisplayName "Nginx HTTPS" -Direction Inbound -Protocol TCP -LocalPort <ポート番号 例: 8443> -Action Allow
正常にポート開放が行われているかどうかを確認する場合、別PCからPowerShellを起動して、以下のコマンドを実行する。
Test-NetConnection -ComputerName <Windows PCのIPアドレス> -Port <ポート番号 例: 8080> Test-NetConnection -ComputerName <Windows PCのIPアドレス> -Port <ポート番号 例: 8443>
ファイアウォールルールを削除する場合は、以下に示すコマンドを実行する。
# HTTPポートのルール削除 Remove-NetFirewallRule -DisplayName "Nginx HTTP" -ErrorAction SilentlyContinue # HTTPSポートのルール削除 Remove-NetFirewallRule -DisplayName "Nginx HTTPS" -ErrorAction SilentlyContinue