4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

django+nginx+uwsgiの環境構築

Posted at

本稿はAWS EC2環境にて以下構成でdjango、nginx、uwsgiによる開発環境を構築する際の私的メモです。

構成

名称 バージョン 用途 その他
Amazon Linux 2 OS
nginx 1.20.0 Webサーバ
uwsgi 2.0.20 APサーバ
pyenv 2.3.3 Pythonの実行環境管理ツール
python 3.8.0 プログラミング言語
pip 22.2.2 pythonライブラリパッケージ管理ツール python3.8.0付属
venv 仮想環境ツール python3.8.0付属
Mysql 8.0.30 DB

実行環境全体像(デプロイ)

browser <-> nginx <-> unix socket <-> uwsgi <-> django

Pyenv

pyenvをインストール、環境変数の設定をする

sudo su

cd /usr/local/
git clone https://github.com/yyuu/pyenv.git ./pyenv
mkdir -p ./pyenv/versions ./pyenv/shims
cd /usr/local/pyenv/plugins/
git clone https://github.com/yyuu/pyenv-virtualenv.git

echo 'export PYENV_ROOT="/usr/local/pyenv"' | sudo tee -a /etc/profile.d/pyenv.sh
echo 'export PATH="${PYENV_ROOT}/shims:${PYENV_ROOT}/bin:${PATH}"' | sudo tee -a /etc/profile.d/pyenv.sh
source /etc/profile.d/pyenv.sh

cd ~/

cp /etc/sudoers /etc/sudoers.org

PATH_LINE=$(sed -n '/Defaults    secure_path/=' /etc/sudoers)
sed -i -e "s/Defaults    secure_path/#Defaults    secure_path/g" /etc/sudoers
sed -i -e "${PATH_LINE}a Defaults    env_keep += \"PYENV_ROOT\"" /etc/sudoers
sed -i -e "${PATH_LINE}a Defaults    env_keep += \"PATH\"" /etc/sudoers

Python

pythonバージョン3.8.0をpyenvからインストール、設定する

pyenv install -v 3.8.0
pyenv global 3.8.0

ln -s /lib/python2.7/site-packages/amazon_linux_extras /usr/local/pyenv/versions/3.8.0/lib/python3.8/site-packages/

nginx

nginxをインストールする

amazon-linux-extras enable nginx1
amazon-linux-extras install -y nginx1

cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.org

# virtualhost用ディレクトリ
mkdir /etc/nginx/sites-available
mkdir /etc/nginx/sites-enabled

設定ファイルを編集する

vim /etc/nginx/nginx.conf

includeを追記

# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

再起動、自動起動設定

systemctl stop nginx
systemctl enable nginx
systemctl start nginx

Mysql

mysqlバージョン8をインストール、初期設定する

# MySQL GPGキーの有効期限切れ対応、インストール時にエラーが起きなければ必要ないです
# rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022

yum-config-manager --disable mysql57-community

# mariadb削除
yum -y remove mariadb-*
rm -rf /var/lib/mysql/

yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm -y
yum -y install --enablerepo=mysql80-community mysql-community-server
yum -y install --enablerepo=mysql80-community mysql-community-devel

cp /etc/my.cnf /etc/my.cnf.org

echo 'character-set-server=utf8' | sudo tee -a /etc/my.cnf
echo 'default_password_lifetime=0' | sudo tee -a /etc/my.cnf

systemctl stop mysqld
systemctl enable mysqld
systemctl start mysqld

初期設定

mysql_secure_installation

初期パスワード入力 /var/log/mysqld.logから抽出

Securing the MySQL server deployment.
Enter password for user root: 

新しいパスワードの入力

The existing password for the user account root has expired. Please set a new password.

New password: ******
Re-enter new password: ******

パスワード検証プラグイン
インストール済みなのでここでのパスワード入力は不要

The 'validate_password' plugin is installed on the server.
The subsequent steps will run with the existing configuration
of the plugin.
Using existing password for root.

Estimated strength of the password: 100 
Change the password for root ? ((Press y|Y for Yes, any other key for No) : n

匿名ユーザの削除

By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Success.

リモートからの root ユーザでのログイン禁止

Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Success.

test データベースの削除

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
 - Dropping test database...
Success.

すぐに権限テーブルをリロードして変更を有効にするか

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

mysql にrootユーザでログインする

mysql -u root -p

パスワードバリデーション設定無効化

UNINSTALL COMPONENT 'file://component_validate_password';

データベースを作成「django_db」

MariaDB [(none)]> CREATE DATABASE django_db CHARACTER SET utf8;

Query OK, 1 row affected (0.00 sec)

ユーザー作成、権限設定

CREATE USER 'writer'@'%' identified by '******';
CREATE USER 'writer'@'localhost' identified by '******';
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER,INDEX,REFERENCES ON *.* TO 'writer'@'%';
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,ALTER,INDEX,REFERENCES ON *.* TO 'writer'@'localhost';
# migration時に権限エラーとなったので追加
GRANT ALL PRIVILEGES ON first.* TO 'writer'@'localhost' WITH GRANT OPTION;

FLUSH PRIVILEGES;

uwsgi

uwsgiをインストールする

yes | pip install --upgrade pip
yes | pip install wheel
yes | pip install uwsgi
ln -s /usr/local/pyenv/shims/uwsgi /usr/bin/uwsgi

ドキュメントルートディレクトリ作成

mkdir -m 755 /home/web

Django

venvで仮想環境化する

cd /home/web
mkdir test && cd test
# venvの仮想環境作成
python -m venv appvenv
# 仮想環境を有効化
source appvenv/bin/activate

# djangoインストール
# pipを更新
(appvenv) pip install --upgrade pip

# 仮想環境にDjangoをインストール
(appvenv) pip install django

# 仮想環境にuWSGIをインストール
(appvenv) pip install uwsgi

# 仮想環境にmysqlclientをインストール
(appvenv) pip install mysqlclient

# django プロジェクト作成
(appvenv) django-admin startproject test_pj
# django アプリ作成
(appvenv) cd test_pj
(appvenv) django-admin startapp test_apps
(appvenv) mkdir static templates
(appvenv) mkdir templates/test_apps

Djangoの設定ファイルを編集する

vim /home/web/test/test_pj/test_pj/settings.py

変更、追記を行う

import os

ALLOWED_HOSTS = ['IPアドレスまたはドメイン']

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_db',
        'USER': 'writer',
        'PASSWORD': '******',
        'HOST': 'localhost',
        'PORT': '3306',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

USE_I18N = True

USE_L10N = True

USE_TZ = False

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

Djangoのマイグレーション等を行う

# マイグレーションを行う
(appvenv) python manage.py makemigrations
(appvenv) python manage.py migrate

管理ユーザ作成

(appvenv) python manage.py createsuperuser

ユーザー名 (leave blank to use 'root'):admin
メールアドレス: admin@sample.com
Password: ******
Password (again): ******
Superuser created successfully.

静的ファイルを下記コマンドで集める

(venvname) python manage.py collectstatic

uwsgiの設定

socketファイルとpidファイルを格納するディレクトリを作成、所有者や権限を変更する

# ディレクトリ作成
mkdir -p /var/run/uwsgi

# 所有者変更
chown nginx:nginx /var/run/uwsgi

# 権限変更
chmod +w /var/run/uwsgi

appvenv配下にuwsgiのための変数を定義するファイルuwsgi_paramsを作成する。

# 移動
cd /home/web/test/appvenv

# ファイル作成
vim uwsgi_params

下記を記載、保存

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

同じくappvenv配下にuwsgi.iniファイルを作成する

# ファイル作成
vim uwsgi.ini

下記を記載、保存

[uwsgi]
uid = nginx
gid = nginx

base-htdocs = /home/web/test
project-name = test_pj

# 作成したDjangoアプリのルートを指定する
chdir = %(base-htdocs)/%(project-name)

# loadするwsgiモジュールを指定
module = %(project-name).wsgi

# 仮想環境の場所を指定する
home = %(base-htdocs)/appvenv

master = true
processes = 2
threads = 1

# socketとpidファイルの作成場所を指定する
socket = /var/run/uwsgi/%(project-name).sock
pidfile = /var/run/uwsgi/master.pid

chmod-socket = 666
vacuum = true
thunder-lock = true
max-requests = 6000
max-requests-delta = 300

# クライアント送信元IPアドレスをログに出力するか
log-x-forwarded-for = true

# ログ
logto = /var/log/uwsgi/%(project-name).log
deamonize = /var/log/uwsgi/uwsgi-@(exec://date +%Y-%m-%d).log
log-reopen = true

# 開発用リロード設定 ファイル監視、反映のためN秒毎にuwsgiをリロードする
py-autoreload = 1

emperor mode

uwsgiで複数アプリケーションを起動できる仕組み、同一サーバで複数人が開発をする事を想定して使用する

uwsgiの自動起動設定

# ファイル作成
vim /etc/systemd/system/uwsgi.service

下記を記載、保存

# uwsgi.service
[Unit]
Description=uWSGI
After=syslog.target

[Service]
ExecStartPre=-/bin/mkdir -p /var/log/uwsgi
ExecStartPre=-/bin/chown -R nginx:nginx /var/log/uwsgi
ExecStartPre=-/bin/mkdir -p /var/run/uwsgi
ExecStartPre=-/bin/chown -R nginx:nginx /var/run/uwsgi
ExecStart=/usr/local/pyenv/shims/uwsgi --ini /etc/uwsgi/emperor.ini

Restart=always
Restart=on-failure
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all

[Install]
WantedBy=multi-user.target

シンボリックリンク

mkdir -p /etc/uwsgi/vassals
# シンボリックリンクを設定
ln -s /home/web/test/appvenv/uwsgi.ini /etc/uwsgi/vassals/test.ini

emperor mode設定

vim /etc/uwsgi/emperor.ini

下記を記載、保存

[uwsgi]
emperor = /etc/uwsgi/vassals
uid = nginx
gid = nginx
logto = /var/log/uwsgi/uwsgi.log
touch-logreopen = /var/log/uwsgi/touch-logreopen
master = true
vacuum = true
ignore-sigpipe = true
ignore-write-errors = true
disable-write-exception = true

emperor modeになっているか確認

# 設定を読み込み
systemctl daemon-reload
# 再起動、自動起動をONに
systemctl stop uwsgi
systemctl enable uwsgi
systemctl start uwsgi
# ステータスを確認
systemctl status uwsgi

# ステータスが以下になっていればOK
Status: "The Emperor is governing 1 vassals"

nginxの設定

同一サーバで複数アプリケーションを運用することを想定しているので、バーチャルホストの設定を行う

/etc/nginx/sites-available配下に設定ファイルを作成する。

vim /etc/nginx/sites-available/test

下記を記載、保存

# Djangoの設定
upstream test {
    # uwsgi.iniで設定したソケットファイルの場所を指定する。
    server unix:///var/run/uwsgi/test_pj.sock;
}

# サーバの設定
server {
    # ポート番号
    listen      80;
    # virtual hostやIPを指定
    server_name "ドメイン指定";
    charset     utf-8;

    # Djangoの静的ファイルの設定
    location /static {
        # staticディレクトリが存在する場所を指定する。開発用なのでrootで指定
        root /home/web/test/test_pj;
    }

    location / {
        uwsgi_pass test;
        # uwsgi_paramsの場所を指定する
        include /home/web/test/appvenv/uwsgi_params;
    }
}

上記で作成した設定ファイルのシンボリックリンクを/etc/nginx/sites-enabledに貼る。

# シンボリックリンクを設定
ln -s /etc/nginx/sites-available/test /etc/nginx/sites-enabled/test

再起動

systemctl stop nginx
systemctl start nginx

ブラウザでアクセス
django初期ページが表示されたのを確認

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?