Contents
1. AWS アカウント作成と無料枠の確認
AWS の Free Tier は 12 ヶ月間 有効ですが、対象インスタンスタイプはサービスやリージョンごとに変わります。本章では最新情報を踏まえて正しいリソースを選択し、課金リスクを回避するポイントを解説します。
1-1. Free Tier の対象サービス(2026年4月時点)
AWS の公式ドキュメント[^1] によると、Free Tier が提供している EC2 と RDS のインスタンスタイプは次の通りです。
| サービス | リージョン共通の無料枠対象インスタンスタイプ | 月間上限 |
|---|---|---|
| EC2 | t3.micro(x86_64)t4g.micro(ARM)※2025 年以降は t4g.micro が追加対象となりますが、リージョンによっては未対応 |
750 時間 |
| RDS | db.t3.micro(PostgreSQL, MySQL, MariaDB 等)※エンジンやリージョンにより上限が変動する可能性があります |
750 時間 |
注: 上記は執筆時点の情報です。実際に利用を開始する前に、AWS Free Tier の最新ページで対象インスタンスタイプと上限を必ず再確認してください。
1-2. IAM ユーザーと最小権限ロールの設定
Free Tier 対象リソースだけにアクセスさせることで、予期しない課金を防げます。以下は EC2、RDS、S3 に限定したカスタムポリシー例です。
1-2‑a. カスタムポリシー(JSON)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
{ "Version": "2012-10-17", "Statement": [ { "Sid": "EC2ReadOnlyAndControl", "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:StartInstances", "ec2:StopInstances" ], "Resource": "*" }, { "Sid": "RDSConnect", "Effect": "Allow", "Action": [ "rds-db:connect" ], "Resource": "arn:aws:rds-db:*:<account-id>:dbuser:*/${aws:username}" }, { "Sid": "S3AccessForStaticMedia", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": [ "arn:aws:s3:::my-django-static/*", "arn:aws:s3:::my-django-media/*" ] }, { "Sid": "ACMExportCertificate", "Effect": "Allow", "Action": [ "acm:ExportCertificate" ], "Resource": "arn:aws:acm:*:<account-id>:certificate/*" } ] } |
rds-db:connectは IAM DB 認証 用に必要な最小権限です。acm:ExportCertificateは EC2 上で ACM 証明書を PEM 形式へエクスポートする際だけ付与し、ロールは限定的に使用します(後述)。
1-2‑b. ロール作成手順(CLI)
|
1 2 3 4 5 6 7 8 9 |
aws iam create-role \ --role-name FreeTierDeployRole \ --assume-role-policy-document file://trust-policy.json # EC2 が Assume できるように設定 aws iam put-role-policy \ --role-name FreeTierDeployRole \ --policy-name FreeTierMinimalPolicy \ --policy-document file://free-tier-minimal-policy.json |
ベストプラクティス:ロールは EC2 インスタンスプロファイル としてアタッチし、不要になったらすぐにデタッチ・削除してください。
2. EC2 と RDS の構築手順とパッケージインストール
この章では無料枠対象の t3.micro(x86)または t4g.micro(ARM) を使用した EC2 インスタンスと、RDS PostgreSQL db.t3.micro の作成方法を解説します。続いて Amazon Linux 2023 で推奨されるパッケージマネージャ dnf による環境構築手順も示します。
2-1. インスタンス選定と起動
Free Tier の対象インスタンスタイプはリージョンに依存するため、コンソールで「Free tier eligible」フィルタを必ず有効にしてください。
| 項目 | 推奨設定 |
|---|---|
| AMI | Amazon Linux 2023 (AL2023) |
| インスタンスタイプ | t3.micro(x86) または t4g.micro(ARM) |
| VPC | デフォルト VPC、パブリックサブネット |
| キーペア | 作成後に .pem を安全に保管 |
ポイント:インスタンス起動時に「自動的に無料枠対象か」を確認できるチェックボックスがあります。必ず有効化してください。
2-2. セキュリティグループ設定
| ポート | プロトコル | 許可元 |
|---|---|---|
| 22 | TCP | 自宅・オフィスの固定 IP(CIDR) |
| 80 | TCP | 0.0.0.0/0 (HTTP、リダイレクト用) |
| 443 | TCP | 0.0.0.0/0 (HTTPS) |
- SSH は IP 制限 を必ず行い、不要になったらルール削除します。
- HTTP/HTTPS は後段の ALB または Nginx が受ける想定で全世界に開放していますが、内部通信だけにしたい場合は VPC の CIDR に絞っても構いません。
2-3. RDS PostgreSQL 作成とパラメータ調整
- コンソール → RDS → 「データベース作成」→「PostgreSQL」を選択
- DB インスタンスクラス:
db.t3.micro(Free Tier) - ストレージ:20 GiB まで自動スケーリング有効化(上限は無料枠を超えないようにモニタリング)
- パラメータグループで
max_connectionsを100に設定し、同時接続数の不足によるエラーを防止
注意:リージョンによっては PostgreSQL のバージョン制限があるため、Free Tier でサポートされている最新版(例: 15.x)かを確認してください。
2-4. 必要パッケージのインストール(dnf 推奨)
Amazon Linux 2023 は dnf が標準です。yum コマンドは互換レイヤーとして残っていますが、最新情報に合わせて dnf を使用します。
|
1 2 3 4 5 6 7 8 9 10 11 |
# EC2 に SSH 接続後の手順例 sudo dnf -y upgrade # セキュリティアップデートを適用 sudo dnf install -y \ python3-pip \ git \ nginx \ postgresql # PostgreSQL クライアント(psql) # 仮想環境とパッケージ管理 python3 -m pip install --upgrade pip pip3 install virtualenv |
TIP:
dnfは自動的に依存関係を解決し、トランザクションが失敗した場合はロールバックします。yumと比べて安全性が高い点がメリットです。
3. ACM 証明書の取得・EC2 での利用
HTTPS 化はセキュリティの最低ラインです。本章では AWS Certificate Manager (ACM) の無料証明書を取得し、EC2 上の Nginx に直接組み込む手順と、エクスポート時に必要な IAM 権限・安全対策について解説します。
3-1. 証明書リクエスト(DNS 検証が推奨)
- ACM コンソール → 「証明書のリクエスト」
- パブリック証明書 を選択し、対象ドメイン例
www.example.comを入力 - 検証方法は「DNS(Route 53)」を選び、表示された CNAME レコードを Route 53 のホストゾーンに作成
ポイント:DNS 検証は自動更新が可能で、手動の HTTP/HTTPS 検証より管理負荷が低くなります。
3-2. 証明書エクスポートと IAM 権限
EC2 が直接 PEM 形式の証明書を扱うには acm:ExportCertificate 権限が必要です。以下は 最小権限ロール の例です(先ほどのカスタムポリシーに含めました)。
|
1 2 3 4 5 6 7 8 9 |
{ "Sid": "ACMExportCertificate", "Effect": "Allow", "Action": [ "acm:ExportCertificate" ], "Resource": "arn:aws:acm:*:<account-id>:certificate/*" } |
エクスポート手順(CLI)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# 証明書 ARN を取得 CERT_ARN=$(aws acm list-certificates \ --query "CertificateSummaryList[?DomainName=='www.example.com'].CertificateArn" \ --output text) # PEM 形式でエクスポート(パスフレーズは任意) aws acm export-certificate \ --certificate-arn $CERT_ARN \ --passphrase fileb://<(openssl rand -base64 32) \ --output text > /tmp/acm_export.txt # 出力例: Certificate, CertificateChain, PrivateKey を分割 awk '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/' /tmp/acm_export.txt > /etc/ssl/certs/acm_cert.pem awk '/-----BEGIN PRIVATE KEY-----/,/-----END PRIVATE KEY-----/' /tmp/acm_export.txt > /etc/ssl/private/acm_key.pem |
セキュリティ注意
- エクスポートしたプライベートキーは root 権限でのみ読み取り可能 にし、chmod 600を設定してください。
- ロールに付与するacm:ExportCertificateは EC2 プロファイルのみに限定し、他のリソースへは付与しないこと。
- キーのローテーションは ACM の再発行と同時に実施し、古い PEM ファイルは即座に削除します。
3-3. Nginx での証明書設定
取得した acm_cert.pem と acm_key.pem を Nginx 設定に組み込みます(次章「Gunicorn と Nginx の設定」で具体例を示します)。
4. Django アプリの取得・環境変数管理・S3 設定
このセクションでは GitHub に保存したコードを EC2 にデプロイし、機密情報は .env ファイルで安全に扱う方法と、静的/メディアファイルを Amazon S3 へオフロードする手順を解説します。
4-1. GitHub リポジトリ作成と .env 管理(django‑environ)
- GitHub 上で新規リポジトリを作成し、
.gitignoreに*.envとvenv/を追加。 - ローカルでプロジェクトをクローン後、プロジェクト直下に .env ファイルを作成します(例は日本リージョン用)。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# .env – 例 DEBUG=False SECRET_KEY=YOUR_SECRET_KEY_HERE DB_NAME=mydb DB_USER=myuser DB_PASSWORD=SuperSecretPassword! DB_HOST=<RDSエンドポイント> AWS_ACCESS_KEY_ID=AKIAxxxxxxxxxxxx AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxx S3_BUCKET_STATIC=my-django-static S3_BUCKET_MEDIA=my-django-media |
ベストプラクティス:
.envは絶対にリポジトリにコミットせず、GitHub Secrets にも保存しない。EC2 起動時のユーザーデータか、SSM パラメータストアで注入する方法も検討してください。
settings.py への組み込み
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import environ, os BASE_DIR = Path(__file__).resolve().parent.parent env = environ.Env() environ.Env.read_env(os.path.join(BASE_DIR, ".env")) DEBUG = env.bool("DEBUG") SECRET_KEY = env.str("SECRET_KEY") DATABASES = { "default": env.db(), } # S3 設定(django‑storages 用) AWS_ACCESS_KEY_ID = env.str("AWS_ACCESS_KEY_ID") AWS_SECRET_ACCESS_KEY = env.str("AWS_SECRET_ACCESS_KEY") AWS_STORAGE_BUCKET_NAME = env.str("S3_BUCKET_STATIC") # static 用 AWS_MEDIA_BUCKET_NAME = env.str("S3_BUCKET_MEDIA") # media 用 AWS_S3_REGION_NAME = "ap-northeast-1" AWS_S3_SIGNATURE_VERSION = "s3v4" |
4-2. S3 バケット作成とポリシー設定
| 項目 | 推奨値 |
|---|---|
| バケット名 | my-django-static、my-django-media(リージョン横断で一意) |
| パブリックアクセス | 静的ファイルは公開、メディアは必要に応じてプライベート設定 |
CORS 設定例
|
1 2 3 4 5 6 7 8 9 |
<CORSConfiguration> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <!-- 必要ならドメイン制限 --> <AllowedMethod>GET</AllowedMethod> <AllowedHeader>*</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration> |
バケットポリシー(静的ファイルの公開読み取り)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::my-django-static/*"] } ] } |
注意:メディアファイルはプライベートにしたい場合、
aws s3api put-object-acl --acl privateを利用し、Django 側で署名付き URL(generate_presigned_url)を返す実装が必要です。
4-3. django‑storages の設定
|
1 2 3 4 5 6 7 8 9 10 |
# settings.py 続き DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" STATICFILES_STORAGE = "storages.backends.s3boto3.S3StaticStorage" AWS_S3_CUSTOM_DOMAIN_STATIC = f"{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com" STATIC_URL = f"https://{AWS_S3_CUSTOM_DOMAIN_STATIC}/static/" AWS_S3_CUSTOM_DOMAIN_MEDIA = f"{AWS_MEDIA_BUCKET_NAME}.s3.amazonaws.com" MEDIA_URL = f"https://{AWS_S3_CUSTOM_DOMAIN_MEDIA}/media/" |
requirements.txt に以下を必ず追加してください。
|
1 2 3 4 5 6 7 |
Django>=5.0,<6 gunicorn django-environ boto3 django-storages==1.14 psycopg2-binary |
5. Gunicorn と Nginx の設定、HTTPS 化
本章では systemd による Gunicorn デーモン化と、Nginx がリバースプロキシとして機能する構成を示します。前節で取得した ACM 証明書(PEM)を使用し、HTTPS 通信を実現します。
5-1. systemd 用 Gunicorn サービス
/etc/systemd/system/gunicorn.service に配置する内容です。環境変数は .env を読み込むように設定しています。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
[Unit] Description=gunicorn daemon for Django project After=network.target [Service] User=ec2-user Group=nginx WorkingDirectory=/home/ec2-user/django-aws-demo EnvironmentFile=/home/ec2-user/django-aws-demo/.env ExecStart=/home/ec2-user/django-aws-demo/venv/bin/gunicorn \ --workers 3 \ --bind unix:/run/gunicorn.sock myproject.wsgi:application # 再起動ポリシー Restart=on-failure KillSignal=SIGQUIT TimeoutSec=30 PrivateTmp=true [Install] WantedBy=multi-user.target |
|
1 2 3 4 |
sudo systemctl daemon-reload sudo systemctl enable --now gunicorn sudo systemctl status gunicorn # 正常に起動しているか確認 |
5-2. Nginx のリバースプロキシ設定(HTTPS)
/etc/nginx/conf.d/django.conf に以下を書き込みます。証明書は前章でエクスポートした PEM ファイルを使用します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
upstream django { server unix:/run/gunicorn.sock fail_timeout=0; } server { listen 80; server_name www.example.com; # HTTP → HTTPS リダイレクト return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name www.example.com; # 証明書パス(先ほど /etc/ssl/... に配置) ssl_certificate /etc/ssl/certs/acm_cert.pem; ssl_certificate_key /etc/ssl/private/acm_key.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; # 静的・メディアファイルは S3 から直接配信する想定のため、ここではパスなし location / { 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_pass http://django; } } |
|
1 2 |
sudo nginx -t && sudo systemctl restart nginx |
ポイント:
ssl_certificateとssl_certificate_keyのパーミッションはそれぞれ644、600が推奨です。
5-3. HTTPS 動作確認
|
1 2 3 |
curl -I https://www.example.com # HTTP/2 200 OK が返ってくれば成功 |
6. CI/CD と運用・監視ベストプラクティス
自動化と可観測性は本番環境の信頼性を支える重要要素です。ここでは GitHub Actions によるデプロイパイプライン、CloudWatch Logs エージェント でのログ集約、そして Auto Scaling と最小権限ロール設計について解説します。
6-1. GitHub Actions デプロイワークフロー
以下は /.github/workflows/deploy.yml のサンプルです。GitHub Secrets に登録した情報だけを使用し、EC2 側の IAM ロールで必要権限(S3 読み取り・ACM エクスポート)を付与しています。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
name: Deploy Django to EC2 on: push: branches: [ main ] jobs: build-deploy: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install dependencies & run tests run: | python -m pip install --upgrade pip pip install -r requirements.txt pytest # テストがあれば実行 - name: Package project run: zip -r app.zip . -x "*.git*" "venv/*" - name: Transfer package via SCP uses: appleboy/scp-action@v0.1.7 with: host: ${{ secrets.EC2_HOST }} username: ec2-user key: ${{ secrets.EC2_SSH_KEY }} source: "app.zip" target: "/home/ec2-user/" - name: Remote deployment commands uses: appleboy/ssh-action@v0.1.10 with: host: ${{ secrets.EC2_HOST }} username: ec2-user key: ${{ secrets.EC2_SSH_KEY }} script: | unzip -o app.zip -d django-aws-demo cd django-aws-demo source venv/bin/activate pip install -r requirements.txt python manage.py migrate --noinput python manage.py collectstatic --noinput sudo systemctl restart gunicorn |
セキュリティ:
EC2_SSH_KEYは Read‑only の IAM ロールで管理し、GitHub 上に平文で保存しないこと。
6-2. CloudWatch エージェントでログ・メトリクス転送
|
1 2 3 4 5 6 |
# EC2 にインストール(dnf 推奨) sudo dnf install -y amazon-cloudwatch-agent # 設定ウィザード起動 sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard |
設定例(/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
{ "logs": { "logs_collected": { "files": { "collect_list": [ { "file_path": "/var/log/nginx/access.log", "log_group_name": "/aws/ec2/nginx-access", "log_stream_name": "{instance_id}" }, { "file_path": "/var/log/nginx/error.log", "log_group_name": "/aws/ec2/nginx-error", "log_stream_name": "{instance_id}" }, { "file_path": "/var/log/messages", "log_group_name": "/aws/ec2/system-messages", "log_stream_name": "{instance_id}" } ] } } }, "metrics": { "append_dimensions": { "InstanceId": "${aws:InstanceId}" }, "metrics_collected": { "cpu": { "measurement": ["usage_idle", "usage_user"], "period": 60 }, "mem": { "measurement": ["mem_used_percent"], "period": 60 } } } } |
|
1 2 3 |
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \ -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s |
6-3. Auto Scaling と最小権限ロール設計
Free Tier の上限を超えない範囲で Auto Scaling Group を構築すれば、トラフィック増加時に自動で t3.micro(または t4g.micro)インスタンスが追加されます。
Launch Template 例
| パラメータ | 設定 |
|---|---|
| AMI | Amazon Linux 2023 (AL2023) |
| Instance Type | t3.micro(Free Tier 対応) |
| IAM Role | AutoScalingEC2Role(最小権限) |
| User Data | dnf による基本パッケージインストール + アプリコード取得 |
Auto Scaling 用 IAM ロール(最小権限)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
{ "Version": "2012-10-17", "Statement": [ { "Sid": "EC2ReadWriteForASG", "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:CreateTags" ], "Resource": "*" }, { "Sid": "CloudWatchMetricsPublish", "Effect": "Allow", "Action": [ "cloudwatch:PutMetricData" ], "Resource": "*" }, { "Sid": "S3StaticRead", "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": [ "arn:aws:s3:::my-django-static/*", "arn:aws:s3:::my-django-media/*" ] } ] } |
ポイント:
AutoScalingEC2Roleは EC2 インスタンスプロファイルにのみ付与し、他のサービス(例: RDS)へのアクセスは別途ロールで管理します。
おわりに
- 本ガイドは AWS Free Tier の最新情報(2026 年 4 月時点) に基づき、最小限のコストで Django アプリを本番環境へデプロイする流れを示しました。
- 各ステップで使用したリソースや権限は 「最小権限」 の原則に従って設計していますが、実際の運用要件に合わせてポリシーは適宜調整してください。
- 定期的な無料枠残量確認(AWS Billing ダッシュボード)と 証明書・キーのローテーション を忘れずに行うことで、予期せぬ課金やセキュリティインシデントを回避できます。
次のアクション
1. AWS コンソールで Free Tier の対象インスタンスタイプと上限を最終確認。
2. 本記事の手順どおりに IAM ロール・ポリシーを作成し、EC2 に適用。
3. CI/CD パイプラインを有効化してコード変更を自動デプロイ。
これで 「無料枠だけでスケーラブルな Django アプリ」 が完成です。ぜひ本番環境に適用し、実際のトラフィックでその効果をご確認ください。
参考リンク
| 項目 | URL |
|---|---|
| AWS Free Tier(公式) | https://aws.amazon.com/jp/free/ |
| Amazon Linux 2023 ドキュメント | https://docs.aws.amazon.com/linux/al2023/ug/ |
| ACM 証明書エクスポート (CLI) | https://docs.aws.amazon.com/acm/latest/userguide/export-certificate.html |
| RDS IAM DB 認証 | https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html |
| CloudWatch エージェント設定ガイド | https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent.html |