🚀

DjangoをAWS EC2にデプロイする方法

2024/05/17に公開

YouTube でゼロから開発するプログラミング動画チュートリアル「フルスタックチャンネル」を発信中の「はる」と申します。

フルスタックチャンネル

Django を AWS EC2 にデプロイする方法を簡単に紹介します。

Docker を使用せずに、Django を EC2 にデプロイする方法になります。

GitHub Actions を使用して、自動デプロイも行います。

構成

Django と PostgreSQL を使用して、EC2 にデプロイします。

必要に応じて、S3 や SES を使用してください。

IAM 作成

IAM でユーザーを作成します。

FullAccess でポリシーを許可していますが、必要な権限だけ設定するようにしてください。

S3 バケット作成

必要に応じて S3 を作成します。

VPC 作成

VPC を作成します。

アベイラビリティーゾーン数は必要に応じて変更してください。

セキュリティグループ作成

セキュリティグループを作成します。

インバウンドルールで下記のポートをあけます

  • SSH
  • HTTP
  • HTTPS
  • PostgreSQL

EC2 インスタンス作成

先ほど作成した VPC とセキュリティグループを連携します。

サブネットは public1-ap-northeast-1a を指定

Ubuntu Server 22.04

インスタンス:t2.micro

RDS 作成

PostgreSQL を使用します。

先ほど作成した EC2 と連携します。

インスタンス:t3.micro

SES 作成

必要に応じて SES を作成します。

Django プロジェクト作成

Django プロジェクトを作成して、GitHub にアップロードしておきます。

SSH 接続

EC2 を作成したときに作成した xxx.pem を使用して SSH 接続します。

ssh -i "~/.ssh/xxxxx.pem" ubuntu@ec2-xxxxx.ap-northeast-1.compute.amazonaws.com

Python アップグレード

pyenv を使用して python のバージョンを3.11.8に上げます。

git clone https://github.com/pyenv/pyenv.git ~/.pyenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
exec "$SHELL"
sudo apt update
sudo apt install -y build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev curl libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
pyenv install -l | less
pyenv install 3.11.8
pyenv versions
pyenv global 3.11.8
python -V

Redis インストール

必要であれば Redis をインストールします。

sudo apt install redis-server
sudo nano /etc/redis/redis.conf

supervised を systemd に変更します。

. . .

# If you run Redis from upstart or systemd, Redis can interact with your
# supervision tree. Options:
#   supervised no      - no supervision interaction
#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode
#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
#   supervised auto    - detect upstart or systemd method based on
#                        UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready."
#       They do not enable continuous liveness pings back to your supervisor.
supervised systemd

. . .
sudo systemctl restart redis.service
sudo systemctl status redis
redis-cli
ping

リポジトリクローン

GitHub からリポジトリをクローンします。

sudo apt install nginx python3-pip python3-dev python3-venv libpq-dev
sudo -H pip3 install --upgrade pip
git clone https://github.com/xxx/xxxxxx.git
cd xxxxxx

Github の remote 先を変更

Github Actions から git pull するためには、origin をgit@github.comにする必要があります。

git remote -v
origin  https://github.com/xxx/xxxxxx.git

git remote set-url origin git@github.com:xxx/xxxxxx.git

環境変数作成

.envファイルを作成します。

データーベースは RDS の接続先情報を設定します。

必要に応じて変更してください。

nano .env
POSTGRES_NAME=xxxx
POSTGRES_USER=xxxx
POSTGRES_PASSWORD=xxxx
POSTGRES_HOST=xxxx.ap-northeast-1.rds.amazonaws.com

SECRET_KEY=xxx
DEBUG=False

AWS_ACCESS_KEY_ID=xxxx
AWS_SECRET_ACCESS_KEY=xxxx
AWS_STORAGE_BUCKET_NAME=xxxx

仮想環境構築

仮想環境を構築して、ライブラリインストール、静的ファイル収集、マイグレートを行います。

python -m venv venv
source venv/bin/activate
pip3 install --upgrade pip setuptools
pip3 install -r requirements.txt
python manage.py collectstatic
python manage.py migrate
python maange.py createsuperuser

nginx 内に static ファイルを設定する場合は、sudo コマンドで実行します。

sudo pip3 install django
sudo python manage.py collectstatic

Nginx 設定

Nginx の設定を行って、画面を表示します。

sudo nano /etc/nginx/sites-available/project-xxx

client_max_body_size を設定することによって、大容量のファイルも受け取れるようになります。

staticファイルの場所は、プロジェクトの設定によって変わります。

server {
    listen 80;
    server_name xx.xxx.xxx.xxx;
    client_max_body_size 10g;

    # nginx内にstaticファイルを設定する場合
    location /static {
        alias /usr/share/nginx/html/static;
    }

    location /media {
        alias /usr/share/nginx/html/media;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

ショートカットリンクを作成して、連携します。

sudo ln -s /etc/nginx/sites-available/project-xxx /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

nginx の設定は必要があれば変更してください。

sudo nano /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        client_max_body_size 10g;
sudo nginx -t
sudo systemctl restart nginx

この時点で、EC2 の IP アドレスにアクセスして、502 Bad Gateway が表示されることを確認します。

runserver で確認

Django を起動して、画面を確認します。

python manage.py runserver 0.0.0.0:8000

gnicorn で確認

gunicorn を使用して、Django を起動して、画面を確認します。

gunicorn --bind 127.0.0.1:8000 mysite.wsgi:application

systemcmd 作成

system コマンドを作成して、リスタートしやすくします。

sudo nano /etc/systemd/system/project-xxx.service
[Unit]
Description=gunicorn
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/project-xxxx
ExecStart=/home/ubuntu/project-xxxx/venv/bin/gunicorn --access-logfile - --workers 3 --bind 127.0.0.1:8000 mysite.wsgi:application

[Install]
WantedBy=multi-user.target

動作コマンド

sudo systemctl start project-xxx
sudo systemctl restart project-xxx
sudo systemctl stop project-xxx

Celery サービス作成

必要であれば Celery を使用して、非同期処理を行います。

celery の system コマンドを作成します。

sudo nano /etc/systemd/system/celery.service
[Unit]
Description=Celery Service
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/project-xxx

PermissionsStartOnly=true
ExecStartPre=/bin/mkdir -p /var/log/celery
ExecStartPre=/bin/chown ubuntu:ubuntu /var/log/celery
ExecStartPre=/bin/chmod 755 /var/log/celery

ExecStartPre=/bin/mkdir -p /var/run/celery
ExecStartPre=/bin/chown ubuntu:ubuntu /var/run/celery
ExecStartPre=/bin/chmod 755 /var/run/celery

ExecStart=/home/ubuntu/project-xxx/venv/bin/celery -A config worker -l info --pidfile=/var/run/celery/%n.pid --logfile=/var/log/celery/%n.log --concurrency=4
ExecStop=/home/ubuntu/project-xxx/venv/bin/celery multi stopwait worker -A config --pidfile=/var/run/celery/%n.pid
ExecReload=/home/ubuntu/project-xxx/venv/bin/celery -A config worker -l info --pidfile=/var/run/celery/%n.pid --logfile=/var/log/celery/%n.log --concurrency=4

Restart=on-failure
IgnoreSIGPIPE=no
KillMode=process
GuessMainPID=no
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

ログなどのフォルダ作成します。

sudo mkdir /var/log/celery
sudo chown -R ubuntu:ubuntu /var/log/celery
sudo chmod -R 755 /var/log/celery

sudo mkdir /var/run/celery
sudo chown -R ubuntu:ubuntu /var/run/celery
sudo chmod -R 755 /var/run/celery

動作コマンドです。

sudo systemctl start celery
sudo systemctl restart celery
sudo systemctl stop celery

コマンド

手動でコードを変更した場合は、project-xxx と celery のリスタートが必要になります。

sudo systemctl restart project-xxx
sudo systemctl restart celery

cat /var/log/celery/celery.service.log
cat /var/run/celery/celery.service.pid

SSH 公開鍵作成

Github Actions からデプロイをするために、ssh 公開鍵を作成します。

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

# 公開鍵を登録
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

Deploy keys

Github の Settings の Deploy keys に id_rsa.pub の公開鍵を登録します。

Github Actions 環境変数

Github の Secret and variables の Actions に環境変数を追加します。

HOST_PROD ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com
USERNAME_PROD ubuntu
SSH_KEY_PROD  id_rsaの中身
AWS_ACCESS_KEY_ID xxx
AWS_SECRET_ACCESS_KEY xxx

GitHub Actions

Github Actions から git pull して、リスタートまでを自動的に実行します。

name: Deploy to EC2

on:
  push:
    branches:
      - release/production

jobs:
  build-and-deploy:
    name: Build and Deploy to EC2
    runs-on: ubuntu-22.04

    steps:
    - name: Checkout to the branch
      uses: actions/checkout@v2

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-1

    - name: Deploy to EC2
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOST_PROD }}
        username: ${{ secrets.USERNAME_PROD }}
        key: ${{ secrets.SSH_KEY_PROD }}
        script: |
          echo "Starting deployment process..."
          cd /home/ubuntu/project-xxx
          echo "Changed directory to project-xxx."
          git pull
          echo "Git pulled successfully."
          source venv/bin/activate
          echo "Activated virtual environment."
          pip install -r requirements.txt
          echo "Requirements installed."
          python manage.py migrate
          echo "Migrations applied."
          # nginx内にstaticファイルを設定する場合はsudoコマンドで実行
          python manage.py collectstatic --noinput
          echo "Static files collected."
          sudo systemctl restart project-xxx
          echo "Project-xxx restarted."
          sudo systemctl restart celery
          echo "Celery restarted."

Celery ログの場所

バックグラウンドでエラーが発生した場合は、celery のログを確認します。

cd /var/log/celery

ドメイン設定

ドメインを取得します。
EC2 の IP アドレスは静的 IP アドレスに変更します。
Route53 でドメインを管理すると、簡単に EC2 の IP アドレスと紐付けることができます。

HTTPS 化

Let's Encrypt を使用します。

sudo apt-get install letsencrypt
sudo systemctl stop nginx
sudo letsencrypt certonly --standalone -d xxxx.co.jp
sudo nano /etc/nginx/sites-available/project-xxx

nginx の設定を変更します。

server {
    listen 80;
    listen [::]:80;
    server_name xxx.co.jp;
    return 301 https://$host$request_uri;
}


server {
    listen  443 ssl;
    server_name xxx.co.jp;
    client_max_body_size 10g;

    ssl_certificate         /etc/letsencrypt/live/xxx.co.jp/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/xxx.co.jp/privkey.pem;

    # nginx内にstaticファイルを設定する場合
    location /static {
        alias /usr/share/nginx/html/static;
    }

    location /media {
        alias /usr/share/nginx/html/media;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

nginx のチェック

sudo nginx -t
sudo systemctl start nginx
sudo systemctl restart project-xxx

証明書自動発行

定期的に証明書を更新するために、cron を使用します。

sudo crontab -e
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
00 05 01 * * sudo systemctl stop nginx; sudo letsencrypt renew; sudo systemctl start nginx

ソースコード

LINE 登録すると講座のソースコードがダウンロードできます。

新着の講座がいち早く届きますので、ぜひ登録をお願いします。

LINE お友達登録
https://lin.ee/NKoTJnV

フルスタックチャンネル

講座の不明点や個人開発の疑問点など何でもご質問ください。

https://www.fullstackchannel.com/

さらに多くの知識と技術を共有し、また新しい学びの機会を提供することを楽しみにしています。

よろしくお願いします。

Discussion