Djangoデプロイメント完全ガイド
Djangoデプロイメント完全ガイド
Section titled “Djangoデプロイメント完全ガイド”Djangoアプリケーションのデプロイメントを、実務で使える実装例とともに詳しく解説します。
1. デプロイメントとは
Section titled “1. デプロイメントとは”デプロイメントの準備
Section titled “デプロイメントの準備”本番環境へのデプロイメントには、開発環境とは異なる設定と手順が必要です。
デプロイメントの流れ ├─ 環境の準備 ├─ 設定の最適化 ├─ 静的ファイルの収集 ├─ データベースのマイグレーション └─ サーバーの起動2. 本番環境の設定
Section titled “2. 本番環境の設定”設定ファイルの分割
Section titled “設定ファイルの分割”from .base import *from decouple import config
DEBUG = FalseALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=lambda v: [s.strip() for s in v.split(',')])
# セキュリティ設定SECURE_SSL_REDIRECT = TrueSESSION_COOKIE_SECURE = TrueCSRF_COOKIE_SECURE = TrueSECURE_BROWSER_XSS_FILTER = TrueSECURE_CONTENT_TYPE_NOSNIFF = TrueX_FRAME_OPTIONS = 'DENY'
# データベース設定DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': config('DB_NAME'), 'USER': config('DB_USER'), 'PASSWORD': config('DB_PASSWORD'), 'HOST': config('DB_HOST'), 'PORT': config('DB_PORT', default='5432'), 'CONN_MAX_AGE': 600, }}
# 静的ファイルの設定STATIC_ROOT = '/var/www/myproject/staticfiles'STATIC_URL = '/static/'STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
# メディアファイルの設定MEDIA_ROOT = '/var/www/myproject/media'MEDIA_URL = '/media/'
# ロギング設定LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'file': { 'level': 'ERROR', 'class': 'logging.FileHandler', 'filename': '/var/log/django/error.log', }, }, 'loggers': { 'django': { 'handlers': ['file'], 'level': 'ERROR', 'propagate': True, }, },}3. Gunicornの設定
Section titled “3. Gunicornの設定”Gunicornのインストール
Section titled “Gunicornのインストール”pip install gunicornGunicornの起動
Section titled “Gunicornの起動”# 基本的な起動gunicorn myproject.wsgi:application
# ワーカー数を指定gunicorn myproject.wsgi:application --workers 4
# バインディングアドレスを指定gunicorn myproject.wsgi:application --bind 0.0.0.0:8000
# 設定ファイルを使用gunicorn myproject.wsgi:application --config gunicorn_config.pyGunicornの設定ファイル
Section titled “Gunicornの設定ファイル”bind = "0.0.0.0:8000"workers = 4worker_class = "sync"worker_connections = 1000timeout = 30keepalive = 2max_requests = 1000max_requests_jitter = 50preload_app = Truesystemdサービスとして設定
Section titled “systemdサービスとして設定”[Unit]Description=gunicorn daemonAfter=network.target
[Service]User=www-dataGroup=www-dataWorkingDirectory=/var/www/myprojectExecStart=/var/www/myproject/venv/bin/gunicorn \ --config /var/www/myproject/gunicorn_config.py \ myproject.wsgi:applicationRestart=always
[Install]WantedBy=multi-user.target# サービスの起動sudo systemctl start gunicornsudo systemctl enable gunicorn
# サービスの状態確認sudo systemctl status gunicorn4. Nginxの設定
Section titled “4. Nginxの設定”Nginxの設定例
Section titled “Nginxの設定例”upstream django { server 127.0.0.1:8000;}
server { listen 80; server_name example.com www.example.com;
# リダイレクト(HTTPS) return 301 https://$server_name$request_uri;}
server { listen 443 ssl http2; server_name example.com www.example.com;
# SSL証明書 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# セキュリティヘッダー add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "DENY" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always;
# 静的ファイル location /static/ { alias /var/www/myproject/staticfiles/; expires 30d; add_header Cache-Control "public, immutable"; }
# メディアファイル location /media/ { alias /var/www/myproject/media/; expires 7d; add_header Cache-Control "public"; }
# Djangoアプリケーション location / { proxy_pass http://django; 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_redirect off; }}Nginxの有効化
Section titled “Nginxの有効化”# シンボリックリンクの作成sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled/
# 設定のテストsudo nginx -t
# Nginxの再起動sudo systemctl restart nginx5. 静的ファイルの収集
Section titled “5. 静的ファイルの収集”collectstaticの実行
Section titled “collectstaticの実行”# 静的ファイルの収集python manage.py collectstatic --noinput
# 本番環境での実行DJANGO_SETTINGS_MODULE=myproject.settings.production python manage.py collectstatic --noinputWhiteNoiseの使用
Section titled “WhiteNoiseの使用”pip install whitenoiseMIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', # WhiteNoiseを追加 # ...]
# 静的ファイルの設定STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'6. データベースのマイグレーション
Section titled “6. データベースのマイグレーション”マイグレーションの実行
Section titled “マイグレーションの実行”# マイグレーションの実行python manage.py migrate
# 本番環境での実行DJANGO_SETTINGS_MODULE=myproject.settings.production python manage.py migrateバックアップの取得
Section titled “バックアップの取得”# PostgreSQLのバックアップpg_dump -U myuser -d mydb > backup.sql
# リストアpsql -U myuser -d mydb < backup.sql7. Dockerを使用したデプロイメント
Section titled “7. Dockerを使用したデプロイメント”Dockerfile
Section titled “Dockerfile”# DockerfileFROM python:3.11-slim
WORKDIR /app
# システムの依存関係をインストールRUN apt-get update && apt-get install -y \ postgresql-client \ && rm -rf /var/lib/apt/lists/*
# Pythonの依存関係をインストールCOPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txt
# アプリケーションコードをコピーCOPY . .
# 静的ファイルの収集RUN python manage.py collectstatic --noinput
# Gunicornの起動CMD ["gunicorn", "--bind", "0.0.0.0:8000", "myproject.wsgi:application"]docker-compose.yml
Section titled “docker-compose.yml”version: '3.8'
services: db: image: postgres:15 environment: POSTGRES_DB: mydb POSTGRES_USER: myuser POSTGRES_PASSWORD: mypassword volumes: - postgres_data:/var/lib/postgresql/data
web: build: . command: gunicorn myproject.wsgi:application --bind 0.0.0.0:8000 volumes: - .:/app - static_volume:/app/staticfiles - media_volume:/app/media ports: - "8000:8000" depends_on: - db environment: - DJANGO_SETTINGS_MODULE=myproject.settings.production
nginx: image: nginx:alpine volumes: - ./nginx.conf:/etc/nginx/nginx.conf - static_volume:/app/staticfiles - media_volume:/app/media ports: - "80:80" - "443:443" depends_on: - web
volumes: postgres_data: static_volume: media_volume:8. CI/CDパイプライン
Section titled “8. CI/CDパイプライン”GitHub Actionsの例
Section titled “GitHub Actionsの例”name: Deploy
on: push: branches: [main]
jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Install dependencies run: | pip install -r requirements/dev.txt - name: Run tests run: | python manage.py test
deploy: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Deploy to server uses: appleboy/ssh-action@master with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} key: ${{ secrets.SSH_KEY }} script: | cd /var/www/myproject git pull source venv/bin/activate pip install -r requirements/prod.txt python manage.py collectstatic --noinput python manage.py migrate sudo systemctl restart gunicorn sudo systemctl restart nginx9. 実務でのベストプラクティス
Section titled “9. 実務でのベストプラクティス”パターン1: 環境変数の管理
Section titled “パターン1: 環境変数の管理”SECRET_KEY=your-secret-key-hereDEBUG=FalseALLOWED_HOSTS=example.com,www.example.comDB_NAME=mydbDB_USER=myuserDB_PASSWORD=mypasswordDB_HOST=localhostDB_PORT=5432パターン2: ログの管理
Section titled “パターン2: ログの管理”LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '{levelname} {asctime} {module} {message}', 'style': '{', }, }, 'handlers': { 'file': { 'level': 'ERROR', 'class': 'logging.handlers.RotatingFileHandler', 'filename': '/var/log/django/error.log', 'maxBytes': 1024 * 1024 * 5, # 5MB 'backupCount': 5, 'formatter': 'verbose', }, 'console': { 'level': 'INFO', 'class': 'logging.StreamHandler', 'formatter': 'verbose', }, }, 'loggers': { 'django': { 'handlers': ['file', 'console'], 'level': 'ERROR', 'propagate': True, }, 'myapp': { 'handlers': ['file', 'console'], 'level': 'INFO', 'propagate': False, }, },}10. よくある問題と解決策
Section titled “10. よくある問題と解決策”問題1: 静的ファイルが表示されない
Section titled “問題1: 静的ファイルが表示されない”原因:
collectstaticが実行されていないSTATIC_ROOTが正しく設定されていない
解決策:
# 静的ファイルの収集python manage.py collectstatic --noinput
# 権限の確認ls -la /var/www/myproject/staticfiles/問題2: データベース接続エラー
Section titled “問題2: データベース接続エラー”原因:
- データベースの設定が間違っている
- データベースサーバーが起動していない
解決策:
# データベース接続のテストpython manage.py dbshell
# データベースの状態確認sudo systemctl status postgresqlこれで、Djangoのデプロイメントの基礎知識と実務での使い方を理解できるようになりました。