先に知っておくべきこと
・SSHの概念、簡単なコマンド
・IPアドレスの基礎
・Linuxの基礎
・Djangoフレームワークの基礎
準備するもの
・レンタルサーバーにSSHで入れる状態、若しくは
・自宅のゴミPCにUbuntuサーバーが入った状態
今日の課題
今日は自分で作ったDjangoアプリをデプロイする作業を行います。いつもLinuxを使っていない方には混乱する作業が多いと思います。
もし難しいと思ったらLinuxをインストールしてみてターミナル(コマンドライン)をいじってみたりSSHで接続してプログラムをインストールする練習をしてみてください。
SSHでサーバーに入る
SSHはセキュアセルといってコマンドラインからネットワークを通して他のサーバー等に接続するテクノロジーの事です。
まずは、SSHクライアントでサーバーに入り込みましょう。
別の記事で詳しく説明しますが、サーバー側でOpenSSH等でサーバーを設定してポートを開けておきます。
私の場合は、MobaXtermという無料のSSHクライアントを使います。
MobaXtermはこちらはから、インストーラかポータブルのアプリをダウンロードできます。
https://mobaxterm.mobatek.net/
で、セッション開始!
Host側(サーバー側)にアクセスしたいIPアドレスを入力し、usernameにサーバーで作成したユーザーネームを入力します。レンタルサーバーでOSを作成した際にrootのPWを設定した場合はusernameはrootになります。
SSHでログイン出来たら
では、SSHでログインできたらちょっとコーヒー休憩。ここでサーバーの中に入り込めたという事ですね。
では、Ubuntuの設定を行い、Djangoのデプロイに必要なdependency(デペンデンスィー:必要なライブラリ等)をインストールしていきます。
sudo apt update
OSのアップデートが終わりました。
では、Python3が入っていることを確かめましょう。
python3 --version
このサーバーにpythonの3.9.7が入っていることが確認できました。
※python2でもできますが、2020年の1月に公式サポートが終了したのでバージョン3をお勧めします。
では次。
Ubuntuユーザーの作成
もし、Ubuntuでユーザーを作成していない場合は新しくubuntuにユーザーを追加しましょう。
すでにroot以外のUbuntuユーザーがある場合は飛ばしてください。
sudo adduser ユーザー名 sudo adduser dan usermod -aG sudo ユーザー名(ユーザーにsudo権限を与える) usermod -aG sudo dan sudo adduser dan www-data

rootからユーザーに入れ替える。
su ユーザー名 ※(rootで入っている場合はユーザーに入れ替えます。) su dan
ライブラリのインストールと設定
sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl
このコマンドで下記のライブラリがインストールされます。
python3-pipはパッケージマネージャー
python3-devはスタティックライブラリ、デベロップメントツール
Libpq-devはクライアント側からpostgresにクエリを流すツール
postgresql-contribはエクステンション
nginxはウェブサーバー
curlはClient URLの略でコマンドラインツール
本当にインストールしますか?と聞かれたらyとタイプ(yesのy)
もしくはインストールの際に最後に-yを打ちます。
PostgreSQLのデータベースを作成
Postgresのdb(データベース)を作ったことがある人ならここは簡単です。
postgresをインストールしたときに自動でpostgres というアドミン権限のユーザーが作成されます。
この権限を使って新しいデータベースとユーザーを作成します。
sudo -u postgres psql
postgres=#に現在のディレクトリが変わったことでpostgresに入れたことが確認できます。
CREATE DATABASE myproject; myprojecyはDB名
でdbを作成します。myprojectの部分はdb名になるので好きな名前でどうぞ。
【注意】
SQLのコマンドは全てセミコロン;で終わります。必ずつけ忘れないように!
エラーがでずに次に進めたらdbができたはずです。
これを確認するには\l(バックスラッシュと小文字のL)です。
これで現在のdbがList(一覧)で表示されました。
PostgreSQLのユーザーを作成
CREATE USER myprojectuser WITH PASSWORD 'password';
このコマンドでユーザーとそのパスワードを作成します。
Myprojectuserはユーザー名なのでお好きなものを。
‘Password’ の部分も自分で決めたパスワードを入力。
PostgreSQLをモディファイ(修正)
ではpostgresの接続をスムースにするためにコネクションパラメーターを変えます。
まずはエンコーディングをutf-8に変えます。
ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
次に下のコマンドでpostgresがコミット(確定)したデータのみを読み取るようにします。
ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
Djangoのタイムゾーンがデフォルト(初期設定)でUTCにセットさせているのでそれに合わせます。
ALTER ROLE myprojectuser SET timezone TO 'UTC';
Djangoのドキュメンテーションを読んで変更したい箇所があれば詳しく見てみましょう。
https://docs.djangoproject.com/en/4.0/ref/databases/#optimizing-postgresql-s-configuration
作成したユーザーにdbのアドミン権限をつける
GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
とりあえずpostgresは一旦完了なのでquitのコマンドでpostgresから抜け出しましょう。
Django用に仮想環境を作成
Djangoアプリのデプロイまでもう少しの辛抱です!
pythonではいくつか仮想環境のライブラリがありますが今回はvirtualenvを使用します。
仮想環境を使ったことがない人は詳しく理解しておいた方が良いですね。
簡単に説明すると同じサーバーで違うバージョンのライブラリを使いたいとき(例えばDjangoの3.0と4.0)に仮想環境をアクティベートして同じマシンでも同時に使用できる様になります。
また、複数人で仕事をするときもバージョンを統一してするために使います。
Pipの準備
pipはpythonパッケージマネージャーでpythonのライブラリをインストールする際に使用しますね。
-HのフラグはsudoのコマンドでユーザーのhomeディレクトリではなくrootのHOMEディレクトリにインストールするように指示します。
まずはpipを最新のものにします。
sudo -H pip3 install --upgrade pip
次にvirtualenvをインストールします。
sudo -H pip3 install virtualenv
Djangoのプロジェクトディレクトリを作成
では、どこにDjangoのプロジェクトを置くか決めましょう。
これは特に決まりはありません。
今日はhome/user名の直下にプロジェクトを置きます。理由はvar/www直下にプロジェクトを作成するとユーザーのパーミッション設定が面倒なので、すべての権限があるユーザーの為に作成されたフォルダを使いたいからです。
ここで簡単なLinuxコマンドを知っていると理解できやすいと思います。
若しくはSSHの代わりにFTPとかでサーバーに入ればUIツールでディレクトリを作成できるようになります。今日使っているSSHクライアントにはどちらのツールも入っているので是非試してください。
Linuxの基本コマンド
- pwdで現在のパス
- cd ..で一階層上に移動
- lsで現在のパスにあるファイルを一覧で表示
で、/varまで移動したら下のコマンドでディレクトリを作成します。
ルートのパスにいる場合は一階層上がり、varフォルダに入ります。

cd.. cd var/www ls
ではこのコマンドでディレクトリを作成します。
mkdir myprojectdir(myprojectdirはフォルダ名です。)
※ディレクトリ名は自分で好きなものに名前を変えてください。
で、cdコマンドで先ほど作成したディレクトリに入ります。
cd myprojectdir
仮想環境をアクティベート
下のコマンドでvirtualenvで仮想環境を作成します。envの所はディレクトリ名なので自分で好きなものを決めてください。
virtualenv env

バーチャル環境ができたら下のコマンドでアクティベートします。
source env/bin/activate

画像を見てわかるようにユーザー名の前に(env)がつきましたね。
これで仮想環境がアクティベートされたことがわかります。
ここからpipでインストールしたライブラリは全てこの仮想環境内のみでインストールされるのでディアクティベートしたらあとはサーバー自体には全く影響しません。
pipでDjangoプロジェクトのライブラリをインストール
pipで下記のライブラリをインストールします。
他に使っているライブラリがある場合はここで全てインストールしてしまいましょう。
もし、requirements.txt 等でライブラリを一覧で書き出している場合はそれを使ってインストールしましょう。
pip install django gunicorn psycopg2-binary
もしくは、FTP等を使って自分で使ったDjano プロジェクトを持ってきましょう。
私の使っているSSHクライアントのmobaXtermはFTPもついてくるのでそのままファイルをドラグandドロップで転送しちゃいます。
もし、WindowsのPCでvirtualenvを使ってDjangoのプロジェクトを作成している場合は下記のコマンドでrequreiments.txtの名前(一般的なので)でデペンデンスィーを書き出します。
pip freeze > requirements.txt
私の場合の requirements.txtの中身はこんな感じになります。
asgiref==3.4.1
autopep8==1.6.0
distlib==0.3.4
Django==4.0.1
django-ckeditor==6.2.0
django-cors-headers==3.11.0
django-js-asset==1.2.2
djangorestframework==3.13.1
filelock==3.4.0
platformdirs==2.4.0
psycopg2==2.9.3
pycodestyle==2.8.0
pytz==2021.3
six==1.16.0
sqlparse==0.4.2
toml==0.10.2
tzdata==2021.5
virtualenv==20.13.0
ではWindowsのPCから必要なファイルだけサーバーに上げていきます。
画像はMobaXtermのSFTPを使用しています。
SSHの方にもファイル転送の機能があるのでわざわざSFTPで接続しなくてもOKです。
requirements.txtからライブラリをインストールしたい場合はこれ。
pip install -r requirements.txt
Gunicornを入れ忘れずに。デベロップメントでは入れていないと思うので。
pip install gunicorn
Djangoプロジェクトの設定
Djangoプロジェクトを新規で作る場合
Djangoのアプリをデプロイする前に練習で新しいプロジェクトを作成したい場合はこちらです。
インストールしたDjangoから下記のコマンドでプロジェクトを作成します。
django-admin.py startproject myproject ~/myprojectdir
すでにDjangoプロジェクトを転送した人は飛ばしてください。
Settings.pyのコンフィグ設定
Djangoのプロジェクトを作成した際に自動settings.pyが作成されます。
このファイルでホスト側の設定とDBの設定を行います。
まずは、setting.pyがあるディレクトリに移動しましょう。
nano settings.py
ALLOWED_HOSTSの箇所を見つけて、下記のように変更します。
ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
ALLOWED_HOSTS = [ *] で全てのIpを許可しますが、セキュリティ上、良くないのでこれはやめましょう。
DBの設定
同じく、settings.pyの所でDATABASEの箇所を見つけて、ENGINE、ユーザー名とパスワード、ホストのIPを確認しましょう。
ちなみにこの作業はデベロップメント(開発)の際に既に接続を確認しているべきですので、windowsとmacをそれぞれ使っている人はその時からDBを接続しておきましょう。
ポートはローカルで接続する場合は空でOKです。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'project', 'USER': 'postgres', 'PASSWORD': 'password', 'HOST': '127.0.0.1', 'PORT': '5432', } }
Staticファイルの扱い
同じくsettings.pyです。
下記のようにosモジュールをインポートしてStaticファイル(CSS,JS,画像ファイル)等の保管場所を指定してあげます。
import os STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
データベースのマイグレーション
ではmanage.pyがあるディレクトリから下記のコマンドで接続したDBにDjangoのモデルで作成したテーブルの枠組みをmigration(マイグレーション:移動)します。
python3 manage.py makemigrations python3 manage.py migrate
ここでエラーがでなければ問題なくDBにテーブル(スキーマ)が作成されました。
おめでとう。
スーパーユーザーの作成
次にDjangoのアドミンパネルに入るためのスーパーユーザを作成します。
python3 manage.py createsuperuser
今回は説明の為にユーザー名:admin、パスワード:adminで作成し警告が出ましたが、本番環境ではハッキングされないものを作りましょう。
collectstaticの実行
ではmanage.pyから下記のコマンドを実行して、Staticファイルをデプロイ用に一か所にまとめます。
python3 manage.py collectstatic
ファイヤーウォールの設定
では、このDjangoプロジェクトをテストで公開するために下記のコマンドでサーバーのポートを開けます。
sudo ufw allow 8000
Djangoのテストサーバーでテスト
では下記のコマンドでDjangoにおまけでついてきたウェブサーバーで実際にpublicのネットワークから見れるか確認しましょう。
ちなみに自宅のLAN環境の場合はポートフォワーディングをして外からのアクセスを許可しないといけません。※おすすめしません。
python3 manage.py runserver 0.0.0.0:8000
やったよー。
ここまでできたらちょっとうれしいですね。
で、さっき作成したDjanogoのアドミンパネルにも入れますね。
Gunicornを使ってテスト
では、今度はgunicornを使って同じようにDjangoアプリをデプロイできるか試してみましょう。
※このproject.wsgiのprojectはDjangoのアプリ名です。settings.pyが入っているディレクトリ名ですね。
gunicorn --bind 0.0.0.0:8000 project.wsgi ※必要に応じてパスを移動(pwdで確認) gunicorn --bind 0.0.0.0:8000 Djangoのプロジェクト名.wsgi
【ちなみに】
gunicornでサーブしたDjangoプロジェクトのアドミンパネルのCSSスタイルが抜けてますよね?これはgunicornがどこのCSSを見たらいいか分かっていないからです。今は無視しておきましょう。
では、ここまでできたら、一旦テストサーバーを止めて、仮想環境もディアクティベートしましょう。
サーバーはCtrl(コントール)+Cで止められます。
Systemdソケットとサービスファイルの作成
ではここからgunicorn様にsystemd socket(ソケット)とサービスファイルを作成します。
さっき、gunicornが動くことが分かったのですが、よりコントロールのある設定をしていきます。
下記のコマンドでソケットファイルを作成します。
sudo nano /etc/systemd/system/gunicorn.socket
中身をこんな感じで書きましょう。
[Unit] Description=gunicorn socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.target
次に、systemdサービスファイルを作成します。
sudo nano /etc/systemd/system/gunicorn.service
中はこんな感じです。
UserはUbuntuのユーザー名になります。
[Unit] Description=gunicorn daemon Requires=gunicorn.socket After=network.target [Service] User=sammy(Ubuntuのユーザー名) Group=www-data WorkingDirectory=/home/sammy/myprojectdir ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \ --access-logfile - \ --workers 3 \ --bind unix:/run/gunicorn.sock \ myproject.wsgi:application(※myprojectはDjangoのプロジェクト名) [Install] WantedBy=multi-user.target
次に下のコマンドでGunicornソケットを実行します。これで自動でソケットファイルが作成されます。
sudo systemctl start gunicorn.socket
次にこれをEnable(実行:オン)にします。これで、ソケットに接続された際にsystemdが自動でgunicorn.socketを実行して処理してくれるようになります。
Gunicorn Socketファイルを確認しよう
gunicorn.socketをアクティブにします。
sudo systemctl enable gunicorn.socket
では下記のコマンドでプロセスのステータスを確認しましょう。
sudo systemctl status gunicorn.socket
Output
● gunicorn.socket – gunicorn socket
Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor prese>
Active: active (listening) since Thu 2021-12-02 19:58:48 UTC; 14s ago
Triggers: ● gunicorn.service
Listen: /run/gunicorn.sock (Stream)
Tasks: 0 (limit: 1136)
Memory: 0B
CGroup: /system.slice/gunicorn.socket
Dec 02 19:58:48 gunicorn systemd[1]: Listening on gunicorn socket.
次に、/runディレクトリ直下にgunicorn.sockファイルがあるか確認します。
file /run/gunicorn.sock
※もしここで、systemctl statusのコマンドでエラーが出るか、gunicorn.sockファイルが見つからないメッセージが出た場合はgunicornソケットが作成されていないことが原因になるかと思います。下記のコマンドでgunicornソケットのログを出しましょう。
sudo journalctl -u gunicorn.socket
次のステップに進む前に下記のファイルに問題が無いか確認してください。
/etc/systemd/system/gunicorn.socket
ソケットアクティベーションのテスト
Gunicorn.scoketユニットをスタートしただけだとgunicorn.serviceはアクティブになりません。それはソケットが接続を受けていないからです。
下記のコマンドでステータスをチェックしましょう。
sudo systemctl status gunicorn
ソケットのアクティベーションのメカニズムをテストするには、curlコマンドを使ってソケットに接続シグナルを送ります。
curl --unix-socket /run/gunicorn.sock localhost
ここでHTMLの200のレスポンスが返ってきたらOKです。
これでGunicornが開始し、Djangoのアプリをデプロイする準備ができました。
では、Gunicornのステータスをもう一度確認してみましょう。
sudo systemctl status gunicorn
修正したら下記のコマンド
sudo systemctl daemon-reload
で、gunicornのプロセスもリスタートしましょう。
sudo systemctl restart gunicorn
では、次に進む前にここまでで問題ないことを確認しましょう。
NginxのGunicornにパスするプロキシを設定する
では、gunicornも設定ができたところで、次にプロセスにnginxのトラフィックを設定してきます。
Nginxのsites-availableディレクトリに新しいサーバーブロックを作成します。
sudo nano /etc/nginx/sites-available/myproject
ではこの中に下記のようにコンフィグを書いていきます。
server { listen 80; server_name server_domain_or_IP; }
Nginxはfavicon(ファビコン:お気に入りのアイコン)とスタティックファイルを無視をするので、マニュアルで場所を教えてあげます。
server { listen 80; server_name server_domain_or_IP; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/sammy/myprojectdir; } }
最後に、location / {} ブロックで通常のproxy_paramsを含めた全てのリクエストを処理するようにします。
server { listen 80; server_name server_domain_or_IP; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/sammy/myprojectdir; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } }
このファイルができたらシンボリックリンクでsites-enabledディレクトリとリンクしてあげます。
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
では、nginxのコンフィグレーションをテストしてみましょう。
sudo nginx -t
ここでエラーがでなければ、再度nginxをリスタートします。
sudo systemctl restart nginx
では、最初に開けた8000番のポートはデベロップメント用なので閉じてあげます。
sudo ufw delete allow 8000
それから、通常のアクセスは80番と443番のポートなので HTTPとHTTPSのポートを下記のように許可します。
sudo ufw allow 'Nginx Full'
ファイヤーウォールが起動しているか確認したい場合はこれで。
ufw status sudo ufw enable rootでしか変更できない場合はいったんrootのアカウントに変更します。
これで、サーバーのIPかドメインでDjangoのアプリが見れるようになりました。
トラブルシュート
DjangoのアドミンぺージのCSSが読み込めていない。

読み込まれていないCSSをクリックします。
CSSのソースページに=アクセスできない場合、www-dataが許可(permission)がないことが理由です。
まずは下記のコマンドでエラーがあるか見てみましょう。
sudo tail -F /var/log/nginx/error.log
必要に応じて、ユーザーのグループに追加しましょう。
etc/nginx/sites-enabled# gpasswd -a www-data root etc/nginx/sites-enabled# gpasswd -a www-data ユーザー名
でサービスをリスタートして直るはずです。
sudo systemctl restart nginx sudo systemctl restart gunicorn
トラブルシューティングはプログラミングの基本です。
他人の汚い部屋をきれいにしたり、分厚い契約書を見てミスがない確認するのと同じようで、練習を重ねていけば面倒でも慣れていきます。
慣れてくると、楽しい部分が見えてくるものです。
頑張りましょう!