Ubuntu22.04 venv仮想環境にgunicornをインストールする

## 概要
リモートのUbuntu22.04のvenv仮想環境にgunicornをインストールします。背景としては今後nginx+gunicorn+Django+DRFでAPIサーバを外部公開したくその検証のためです。

以前作成したDjango+DRFのAPIサーバのvenv仮想環境にインストールして、動作確認します。さらに、nginxとの接続ソケットとsystemdサービスを作成します。

https://qiita.com/lustm5/items/222e952ec74c7b52f867

nginxとの接続は、ソケットとHTTPがあるようですが、公式のマニュアルがあり、ネットに情報が多いソケットのほうで進めていきます。

環境
Ubuntu22.04 IP 192.168.88.15
Python 3.10.6
Django 3.2.15

## gunicornをインストール
venv仮想環境をアクティブにしてインストールします。
```
$ cd solution
solution$ source .venv_drf/bin/activate
(.venv_drf) solution$ python -m pip install gunicorn
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/cc86d5f5-ab79-fd1a-ac37-f89d187a9a57.png)

## gunicorn単体の起動確認
startuprojectで作成したconfigフォルダ内のwsgi.pyを参照させてgunicornを起動させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/2e1458f3-aa2e-4fa9-f60f-58ff30f5a2d7.png)
コマンドはこちらです。
```
(.venv_drf) solution$ gunicorn --bind 0.0.0.0:8000 config.wsgi
```
実行すると以下のようになり起動確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/c3aef90a-6629-9963-9f2e-fa40d69f52e0.png)
ブラウザからのアクセスも大丈夫でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/8b338b0f-f2ec-146a-6ef1-9210e7ac2a8d.png)
アクセスできない場合は、リモートのDjangoにアクセスするときに少しはまったときの解決方法をまとめましたので、ご参考なさってください。

https://qiita.com/lustm5/items/6bbd35e4879443fcd86d

Ctrl+Cで終了できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/fe328bf0-08ff-bf3a-ef79-2c70de9d4257.png)
deactivateで仮想環境を抜けておきます。

## nginxからアクセス可能にするためのソケット作成
[公式](https://docs.gunicorn.org/en/latest/deploy.html#systemd)と[こちら](https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-22-04)を参考に/etc/systemd/system/にファイルを作成しました。
```
$ sudo nano /etc/systemd/system/gunicorn.socket
```
```gunicorn.socket
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target
```

## systemdにサービス登録
ソケットが接続を確立したら処理を開始するようにサービス登録します。/etc/systemd/system/にファイルを作成します。
```
$ sudo nano /etc/systemd/system/gunicorn.service
```
```gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=lustm5
Group=www-data
WorkingDirectory=/home/lustm5/solution
ExecStart=/home/lustm5/solution/.venv_drf/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          config.wsgi:application

[Install]
WantedBy=multi-user.target
```
こちらはフォルダ構成です。参考になるかもしれません。configがstartappです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/b4e94a69-fbee-24e3-c433-d6204b10c317.png)

## ソケット起動・自動起動有効と確認
このコマンドを入力してソケットを起動、自動起動を有効にします。
```
$ sudo systemctl start gunicorn.socket
$ sudo systemctl enable gunicorn.socket
```
シンボリックリンクが作成されるみたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/2eecb346-5cd7-6225-c7a9-9ec65b0c8368.png)
起動していました。Listen状態でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/1f290087-b3a3-6623-472c-bc02736d0e4f.png)

## サービスの起動と確認
サービス登録したgunicorn.serviceが起動しているか確認します。
```
$ sudo systemctl status gunicorn
```
設定どおり起動していませんでした。(ソケットが接続を確立したら起動します。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/58b0208c-54a6-ab9b-9c5b-aa4e334a132c.png)
ソケットの接続を確立させてみます。
```
$ curl --unix-socket /run/gunicorn.sock localhost
```
起動しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/e0960d17-06d6-252d-a9ef-cb88bdda2c5d.png)
ここで少しハマりcode=exited status=3/notimplementedが出ました。原因はgunicorn.serviceのパスが間違っていました。

## サーバ再起動して確認
ソケットは自動起動していて、gunicorn.serviceは起動していませんでした。(設定どおり)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/da1b5461-083d-7b24-bfaa-e567ee321e02.png)
ソケットの接続を確立させると起動しました。(設定どおり)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2744334/c90489d0-dc90-90f3-831a-893699778de7.png)

## さいごに
この状態では、ブラウザからアクセスできないので、次はnginxを設定していきます。