バックエンドのデプロイ
バックエンドサーバ側
CertbotによるSSL証明書の発行
既に、サーバ側で下記のドメインの設定が完了していることを前提とします。
recsys-full.recsyslab.org
rsl@*:$ less /etc/nginx/sites-enabled/default
rsl@*:$ sudo certbot --nginx -d recsys-full.recsyslab.org
rsl@*:$ sudo certbot renew --dry-run
rsl@*:$ less /etc/nginx/sites-enabled/recsys_full
Nginx の設定
rsl@*:$ ls /etc/nginx/sites-available/
rsl@*:$ less /etc/nginx/sites-available/default
rsl@*:$ sudo vi /etc/nginx/sites-available/recsys_full
/etc/nginx/sites-available/recsys_full
/etc/nginx/sites-available/defaultを参考に下記のように作成する。
server {
server_name recsys-full.recsyslab.org; # managed by Certbot
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/recsys-full.recsyslab.org/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/recsys-full.recsyslab.org/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
root /usr/share/nginx/html;
# --- Static (collectstatic の出力先) ---
# Django settings.py の STATIC_ROOT と一致させること
location /static/ {
alias /home/rsl/dev/recsys-full/src/backend/static/;
access_log off;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
# --- Media (MEDIA_ROOT) ---
# Django settings.py の MEDIA_ROOT と一致させること
location /media/ {
alias /home/rsl/dev/recsys-full/src/backend/media/;
access_log off;
expires 30d;
add_header Cache-Control "public, max-age=2592000";
}
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X_Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8000;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
# index.html等はファイル名の指定なしで実行
index index.html index.htm index.nginx-debian.html;
}
rsl@*:$
ls /etc/nginx/sites-available/
less /etc/nginx/sites-available/recsys_full
ls -al /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/recsys_full /etc/nginx/sites-enabled/
sudo unlink /etc/nginx/sites-enabled/default
ls -al /etc/nginx/sites-enabled/
cd ~/dev/recsys-full/src/backend/
rsl@*:backend$ source ~/venv/recsys_full/bin/activate
(recsys_full) rsl@*:backend$ python manage.py collectstatic
(recsys_full) rsl@*:backend$ ls static/
(recsys_full) rsl@*:backend$ deactivate
rsl@*:backend$ namei -l /home/rsl/dev/recsys-full/src/backend/static/rest_framework/css/bootstrap.min.css
f: /home/rsl/dev/recsys-full/src/backend/static/rest_framework/css/bootstrap.min.css
drwxr-xr-x root root /
drwxr-xr-x root root home
drwxr-x--- rsl rsl rsl
drwxrwxr-x rsl rsl dev
drwxrwxr-x rsl rsl recsys-full
drwxrwxr-x rsl rsl src
drwxrwxr-x rsl rsl backend
drwxrwxr-x rsl rsl static
drwxrwxr-x rsl rsl rest_framework
drwxrwxr-x rsl rsl css
-rw-r--r-- rsl rsl bootstrap.min.css
rsl@*:backend$ sudo chmod o+rx /home/rsl/
rsl@*:backend$ namei -l /home/rsl/dev/recsys-full/src/backend/static/rest_framework/css/bootstrap.min.css
f: /home/rsl/dev/recsys-full/src/backend/static/rest_framework/css/bootstrap.min.css
drwxr-xr-x root root /
drwxr-xr-x root root home
drwxr-xr-x rsl rsl rsl
drwxrwxr-x rsl rsl dev
drwxrwxr-x rsl rsl recsys-full
drwxrwxr-x rsl rsl src
drwxrwxr-x rsl rsl backend
drwxrwxr-x rsl rsl static
drwxrwxr-x rsl rsl rest_framework
drwxrwxr-x rsl rsl css
-rw-r--r-- rsl rsl bootstrap.min.css
rsl@*:backend$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
rsl@*:backend$ sudo systemctl reload nginx
rsl@*:backend$ curl -I https://recsys-full.recsyslab.org/static/rest_framework/css/bootstrap.min.css
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Tue, 01 Sep 2026 13:11:19 GMT
Content-Type: text/css
Content-Length: 121457
Last-Modified: Fri, 14 Aug 2026 09:14:35 GMT
Connection: keep-alive
ETag: "6a7edc7b-1da71"
Expires: Thu, 01 Oct 2026 13:11:19 GMT
Cache-Control: max-age=2592000
Cache-Control: public, max-age=2592000
Accept-Ranges: bytes
Nginx の起動
rsl@*:$ sudo systemctl start nginx.service
rsl@*:$ systemctl status nginx.service
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Tue 2026-09-01 06:43:37 JST; 15h ago
Docs: man:nginx(8)
Process: 2312957 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 2312964 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 2326395 ExecReload=/usr/sbin/nginx -g daemon on; master_process on; -s reload (code=exited, status=0/SUCCESS)
Main PID: 2312972 (nginx)
Tasks: 3 (limit: 1060)
Memory: 4.6M (peak: 7.3M)
CPU: 793ms
CGroup: /system.slice/nginx.service
├─2312972 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
├─2326397 "nginx: worker process"
└─2326398 "nginx: worker process"
Gunicorn の起動
(recsys_full) rsl@*:backend$
pkill gunicorn
gunicorn --bind 127.0.0.1:8000 config.wsgi:application -D
ps ax | grep gunicorn
2326434 ? Sl 0:00 /home/rsl/venv/recsys_full/bin/python3.12 /home/rsl/venv/recsys_full/bin/gunicorn --bind 127.0.0.1:8000 config.wsgi:application -D
2326435 ? S 0:00 /home/rsl/venv/recsys_full/bin/python3.12 /home/rsl/venv/recsys_full/bin/gunicorn --bind 127.0.0.1:8000 config.wsgi:application -D
2326438 pts/0 S+ 0:00 grep --color=auto gunicorn
Web サーバの動作確認
ブラウザで下記URLにアクセスし、Django REST framework が表示されれば、正常に稼働しています。
ログの確認
サーバにエラーが発生した場合などは、下記コマンドでログを確認できます。
rsl@*:backend$ less logs/django.log
実行確認
Contentフォームに、例えば下記のデータを入力し、POSTボタンをクリックしてください。
{
"email": "foo@example.com",
"password": "secret123"
}
データベースで登録されていることを確認してください。
recsys_full=# SELECT * FROM t_users;
更新後の再デプロイ
クライアント側
リポジトリのプッシュ
$
cd ~/dev/recsys-full/
git add *
git add .*
git commit -m "redeploy"
git push
git status
バックエンドサーバ側
リポジトリのプル
rsl@*:$
cd ~/dev/recsys-full/
git pull
git status
マイグレーションの実行
(recsys_full) rsl@*:backend$
python manage.py makemigrations accounts
python manage.py makemigrations online
python manage.py migrate
Nginx の再読込と Gunicorn の再起動
(recsys_full) rsl@*:backend$
sudo systemctl reload nginx
pkill gunicorn
gunicorn --bind 127.0.0.1:8000 config.wsgi:application -D
ps ax | grep gunicorn
ログの確認
rsl@*:backend$ less logs/django.log
参考
-
[Django で gunicorn と Nginx を使う(Nginx その 3) Snow Tree in June](https://snowtree-injune.com/2020/11/07/nginx-part3-dj015/)