インフラ レッスン5
インフラ総合演習
本番環境を構築しよう - Linux、Nginx、Docker、監視の実践
演習の概要
この演習では、これまでに学んだ知識を総合して、本番環境に近いインフラ構成を構築します。 Linuxサーバーの初期設定からNginxリバースプロキシ、Docker Composeでのアプリケーション運用、 基本的なモニタリングまでを段階的に実装します。
構築する環境
- Ubuntu Linux サーバー
- Nginx リバースプロキシ(SSL対応)
- Docker Compose でアプリ+DB
- 基本的なログ監視とヘルスチェック
学習のゴール
- サーバーのセキュリティ初期設定ができる
- NginxでHTTPS通信を構成できる
- Docker Composeで複数サービスを管理できる
- ログ監視と自動再起動を設定できる
ステップ1: Linuxサーバーの初期設定
新しいサーバーを立てたら、まずセキュリティとユーザーの初期設定を行います。 rootユーザーでの直接ログインを禁止し、SSH鍵認証のみ許可します。
# 1. システムを最新に更新
$ sudo apt update && sudo apt upgrade -y
# 2. 作業用ユーザーを作成
$ sudo adduser deploy
$ sudo usermod -aG sudo deploy
# 3. SSH鍵を設定(ローカルマシンで実行)
$ ssh-keygen -t ed25519 -C "deploy@myserver"
$ ssh-copy-id deploy@your-server-ip
# 4. SSH設定を強化 (/etc/ssh/sshd_config)
$ sudo vi /etc/ssh/sshd_config# /etc/ssh/sshd_config の変更箇所
# rootでのSSHログインを禁止
PermitRootLogin no
# パスワード認証を無効化(鍵認証のみ)
PasswordAuthentication no
# SSHポートを変更(オプション)
Port 2222# 5. ファイアウォール設定(UFW)
$ sudo ufw allow 2222/tcp # SSH(ポート変更した場合)
$ sudo ufw allow 80/tcp # HTTP
$ sudo ufw allow 443/tcp # HTTPS
$ sudo ufw enable
$ sudo ufw status
Status: active
To Action From
-- ------ ----
2222/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
# 6. SSHサービスを再起動
$ sudo systemctl restart sshdステップ2: Nginxリバースプロキシの構成
Nginxをリバースプロキシとして設定し、バックエンドのDockerコンテナにリクエストを転送します。 SSL証明書も設定してHTTPS化します。
# Nginxのインストール
$ sudo apt install nginx -y
$ sudo systemctl enable nginx
# SSL証明書の取得
$ sudo apt install certbot python3-certbot-nginx -y
$ sudo certbot --nginx -d myapp.example.com# /etc/nginx/sites-available/myapp.conf
# HTTPはHTTPSにリダイレクト
server {
listen 80;
server_name myapp.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name myapp.example.com;
# SSL証明書(Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.example.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;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# アクセスログ・エラーログ
access_log /var/log/nginx/myapp.access.log;
error_log /var/log/nginx/myapp.error.log;
# アプリケーション(Docker コンテナ)へリバースプロキシ
location / {
proxy_pass http://127.0.0.1:3000;
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から配信
location /_next/static/ {
alias /var/www/myapp/.next/static/;
expires 365d;
add_header Cache-Control "public, immutable";
}
# ヘルスチェックエンドポイント
location /health {
proxy_pass http://127.0.0.1:3000/api/health;
access_log off;
}
}
# 設定を有効化
$ sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/
$ sudo nginx -t && sudo systemctl reload nginxステップ3: Docker Composeでアプリケーション運用
Docker Composeを使って、アプリケーションとデータベースを一括管理します。 環境変数の管理、ボリュームの永続化、ネットワーク分離を行います。
# docker-compose.yml
services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: myapp
restart: always
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgres://appuser:secretpass@db:5432/myapp
depends_on:
db:
condition: service_healthy
networks:
- app-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
db:
image: postgres:16-alpine
container_name: myapp-db
restart: always
environment:
POSTGRES_DB: myapp
POSTGRES_USER: appuser
POSTGRES_PASSWORD: secretpass
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "127.0.0.1:5432:5432" # ローカルからのみアクセス
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U appuser -d myapp"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres_data:
networks:
app-network:
driver: bridge# Dockerfile(Next.jsアプリの例)
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]
# デプロイコマンド
$ docker compose build
$ docker compose up -d
$ docker compose ps
$ docker compose logs -f appステップ4: 基本的なモニタリング
本番環境では、アプリケーションの稼働状況を監視し、問題があれば素早く検知する仕組みが必要です。 ログ監視、ヘルスチェック、ディスク使用量チェックの基本を設定します。
# ヘルスチェックスクリプト
# /opt/scripts/health-check.sh
#!/bin/bash
HEALTH_URL="http://localhost:3000/api/health"
LOG_FILE="/var/log/health-check.log"
response=$(curl -s -o /dev/null -w "%{http_code}" $HEALTH_URL)
if [ "$response" != "200" ]; then
echo "$(date): ALERT - Health check failed (HTTP $response)" >> $LOG_FILE
# Docker Compose で再起動
cd /opt/myapp && docker compose restart app
echo "$(date): App restarted" >> $LOG_FILE
else
echo "$(date): OK" >> $LOG_FILE
fi# crontabでヘルスチェックを定期実行
$ crontab -e
# 5分おきにヘルスチェック
*/5 * * * * /opt/scripts/health-check.sh
# 毎日ログをローテーション
0 0 * * * find /var/log -name "*.log" -mtime +30 -delete
# SSL証明書の自動更新(月2回)
0 3 1,15 * * certbot renew --quiet --post-hook "systemctl reload nginx"# ディスク使用量チェックスクリプト
# /opt/scripts/disk-check.sh
#!/bin/bash
THRESHOLD=80
USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$USAGE" -gt "$THRESHOLD" ]; then
echo "$(date): WARNING - Disk usage is $USAGE%"
# Docker の不要イメージを削除
docker system prune -f
fi
# リソース確認コマンド
$ df -h # ディスク使用量
$ free -h # メモリ使用量
$ docker stats # コンテナのリソース使用量
$ docker system df # Dockerのディスク使用量
$ journalctl -u nginx -f # Nginxのsystemdログ本番運用チェックリスト
本番環境を運用する前に、以下の項目を確認しましょう。
セキュリティ
- SSH鍵認証のみ、パスワード認証は無効
- ファイアウォール(UFW)で必要なポートのみ開放
- HTTPS(SSL/TLS)を有効化
- セキュリティヘッダーを設定
- 定期的なOSアップデート
可用性
- Docker restart: always で自動再起動
- ヘルスチェックの定期実行
- ログローテーションでディスク枯渇を防止
- データベースのバックアップ設定
運用
- デプロイ手順のドキュメント化
- ロールバック手順の確認
- 監視アラートの通知先設定
- 障害時の対応フローを決めておく
まとめ
- サーバーの初期設定ではSSH鍵認証とファイアウォールが最重要
- NginxリバースプロキシでHTTPS化し、セキュリティヘッダーを設定する
- Docker Composeでアプリケーションとデータベースを一括管理する
- ヘルスチェックとcronで基本的な監視と自動復旧を実現する
- 本番運用前にセキュリティ・可用性・運用のチェックリストを確認する
- インフラの知識はアプリ開発者にとっても不可欠なスキル