使用uwsgi、nginx和postgresql进行Django的构建(AmazonLinux2)
系统要求
操作系统:AmazonLinux2
Python版本:3.9.2
SQLite版本:3.35.0
Django版本:4.0.5
uWSGI版本:2.0.20
Nginx版本:1.20.0
psycopg2-binary版本:2.9.3
PHP版本:8.0.18
PostgreSQL版本:14.1
目录结构
完成后的目录结构如下所示。
由于执行层级非常重要,请一边确认一边进行。
这次我们将配置放置在ec2-user的主目录中。
(部分内容已省略。)
~/
└ uwsgi-tutorial/
└ mysite
├ manage.py
├ media/
├ mysite/
│ ├ asgi.py
│ ├ __init__.py
│ ├ __pycache__/
│ ├ settings.py
│ ├ urls.py
│ └ wsgi.py
├ mysite_uwsgi.ini
├ static
│ └ admin/
└ test.py
只使用Django的方法来运行
Django已经内置了一些简单的功能,因此可以在浏览器上单独运行Django。如果要单独运行,请参考下面的文章,只需从上面复制并粘贴命令即可实现。
尝试创建Django环境并使用venv(需要Python3.3或更高版本)。
建设任务
我們將按照基於官方文件的方式進行操作。
uWSGI官方文檔
Django官方文檔
安装 Python 3.9.2
请参考本文,将文章整理在这里。使用pyenv的方法进行操作。
关于Python版本更改的方法(别名和pyenv)。
升级SQLite
在AmazonLinux2上,默认安装了sqlite3.7.17。
由于Django需要使用sqlite3.9.0或更高版本才能正常运行,因此我们需要进行升级。
由于本文最终将采用posgresql,所以可以跳过这个步骤。
本次我们将按照官方文档的指引进行操作。
$ wget https://www.sqlite.org/2021/sqlite-autoconf-3350000.tar.gz
$ tar fxvz sqlite-autoconf-3350000.tar.gz
$ cd sqlite-autoconf-3350000/
$ ./configure
$ make
$ sudo make install
$ sqlite3 --version
3.35.0 2021-03-12 15:10:09 acd63062eb06748bfe9e4886639e4f2b54ea6a496a83f10716abbaba4115500b
我会将路径添加到共享库中。
vi ~/.bashrc
#一番下に追記する
export LD_LIBRARY_PATH="/usr/local/lib"
$ source ~/.bashrc
当更改Python和SQLite的版本后,我们开始构建Django。
在uWSGI上运行Django
使用venv在虚拟环境中安装Django和uWSGI。
$ cd
$ python3 -m venv uwsgi-tutorial
$ cd uwsgi-tutorial
$ source bin/activate
安装 Django 并创建项目。
安装与 Python 版本相匹配的 Django 版本(本次为 4.0.5)。
可以使用 pip list 命令确认通过 pip 安装的版本。
$ pip install Django
$ django-admin startproject mysite
$ cd mysite
安装uWSGI并创建一个测试页面。
$ pip install uwsgi
$ vi test.py
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"] # python3
#return ["Hello World"] # python2
我将启动uWSGI并显示测试页面。
本次我将按照官方指南,使用8000端口。
$ uwsgi --http :8000 --wsgi-file test.py
我们来访问公共IP地址加端口8000,然后尝试显示测试页面。一旦确认uWSGI正在运行,我们将使用uWSGI来显示Django。
vi mysite/settings.py
#変更前
ALLOWED_HOSTS = []
#変更後
ALLOWED_HOSTS = ['パブリックIPアドレス']
# manage.pyがある階層で実行
$ uwsgi --http :8000 --module mysite.wsgi
如果再次访问http://公共IP地址:8000,能够看到Django页面的话,就表示成功了。
使用nginx来显示Django。
通过前面的操作,Web客户端<->uWSGI<->Django之间的协同已经完成。
接下来将推进Web客户端<->Web服务器<->套接字<->uWSGI<->Python之间的协同。
首先安装并启动nginx。
$ sudo amazon-linux-extras install nginx1
$ sudo systemctl start nginx.service
$ sudo systemctl enable nginx.service
我会创建一个nginx的配置文件。
$ sudo mkdir /etc/nginx/sites-available/
$ sudo vi /etc/nginx/sites-available/mysite_nginx.conf
# mysite_nginx.conf
# the upstream component nginx needs to connect to
upstream django {
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
# configuration of the server
server {
# the port your site will be served on
listen 8000;
# the domain name it will serve for
server_name パブリックIPアドレス; # substitute your machine's IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
# Django media
location /media {
alias /home/ec2-user/uwsgi-tutorial/mysite/media; # your Django project's media files - amend as required #projectのパス配下にmediaを配置します。
}
location /static {
alias /home/ec2-user/uwsgi-tutorial/mysite/static; # your Django project's static files - amend as required #projectのパス配下にstaticを配置します。
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
}
}
在/etc/nginx/sites-enabled上创建一个符号链接。
$ sudo mkdir /etc/nginx/sites-enabled/
$ sudo ln -s /etc/nginx/sites-available/mysite_nginx.conf /etc/nginx/sites-enabled/
在nginx.conf文件的末尾添加上述创建的配置文件,以便可以加载它。
$ sudo vi /etc/nginx/nginx.conf
~~~前略~~~
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
include /etc/nginx/sites-enabled/*;
}
$ sudo systemctl restart nginx.service
为了在nginx上显示Django的静态文件,需要将这些文件复制到项目内部。
首先,根据之前mysite_nginx.conf中指定的路径,在项目中创建”media”和”static”目录。
$ mkdir media
$ mkdir static
接下来,我们将在项目的settings.py文件中进行追加。
$ vi mysite/settings.py
"""
Django settings for mysite project.
Generated by 'django-admin startproject' using Django 4.0.5.
For more information on this file, see
https://docs.djangoproject.com/en/4.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.0/ref/settings/
"""
import os #追記
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
~~~中略~~~
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
STATIC_ROOT = os.path.join(BASE_DIR, "static/") #追記
在manage.py所在的文件夹中执行。
$ python manage.py collectstatic
在完成到這一步之後,我們來確認一下uWSGI和nginx的搭配,試著顯示測試頁面。
在test.py所在的目錄中執行以下命令。
$ uwsgi --socket :8001 --wsgi-file test.py
如果通过访问公共IP地址:8000能够显示测试页面,那么我们也可以检查Django的显示。我们将在manage.py所在的目录层次中执行以下命令。
$ uwsgi --socket :8001 --module mysite.wsgi
使用UNIX套接字进行连接
我将使其能够使用UNIX套接字进行连接。
我将修改mysite_nginx.conf的内容。
$ sudo vi /etc/nginx/sites-available/mysite_nginx.conf
# mysite_nginx.conf
# the upstream component nginx needs to connect to
upstream django {
server unix:/run/uwsgi/mysite.sock; # for a file socket #コメントアウトを外し、パスを入力する
#server 128.0.0.1:8001; # for a web port socket (we'll use this first) #コメントアウトする
}
# configuration of the server
server {
# the port your site will be served on
listen 8000;
# the domain name it will serve for
$ sudo systemctl restart nginx.service
创建一个目录来存放套接字文件,并更改其权限。
该目录的权限应设置为所有者为执行uWSGI的用户(本例中为ec2-user),所有组为执行Web服务器的用户组。
$ sudo mkdir /run/uwsgi
$ sudo chown ec2-user:nginx /run/uwsgi/
让我们尝试使用UNIX套接字来确认是否可以显示Django。
在具有manage.py的目录中执行以下命令。
使用–chmod-socket=666来将套接字文件的权限设置为666,并执行命令。
$ uwsgi --socket /run/uwsgi/mysite.sock --module mysite.wsgi --chmod-socket=666
使用 .ini 文件启动 uWSGI
将以前通过命令执行的操作改为创建.ini文件,并使其能够通过启动进行操作。
$ vi mysite_uwsgi.ini
# mysite_uwsgi.ini file
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = /home/ec2-user/uwsgi-tutorial/mysite
# Django's wsgi file
module = mysite.wsgi
# the virtualenv (full path)
home = /home/ec2-user/uwsgi-tutorial
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10
# the socket (use the full path to be safe
socket = /run/uwsgi/mysite.sock
# ... with appropriate permissions - may be needed
chmod-socket = 666
# clear environment on exit
vacuum = true
让我们启动并从浏览器中进行确认。
$ uwsgi --ini mysite_uwsgi.ini
如果你能到这一步,就能轻松地使用Django启动,即使退出了虚拟环境。
我们来尝试以下的操作。
$ deactivate
$ pip3 install uwsgi
$ uwsgi --ini mysite_uwsgi.ini
将PostgreSQL与Django进行整合。
进行安装和设置
为了将Python和PostgreSQL进行连接,我们将使用psycopg2来实现。
请在虚拟环境中安装psycopg2。
$ cd .. #uwsgi-tutorialがある階層へ移動
$ source bin/activate
$ pip3 install psycopg2-binary
安装完后,请用pip list进行确认。
我们将安装PHP和PostgreSQL。
$ sudo amazon-linux-extras install php8.0 postgresql14
如果使用pyenv,可能会出现以下错误。
/home/ec2-user/.pyenv/versions/3.9.2/bin/python: No module named amazon_linux_extras
通过创建符号链接,应该能够使用。
ln -s /lib/python2.7/site-packages/amazon_linux_extras ~/.pyenv/versions/3.9.2/lib/python3.9/site-packages/
我们将安装所需的工具。
$ sudo yum install postgresql-server postgresql-devel postgresql-contrib
在初始化数据库后,我们将更改配置以允许临时无需密码登录。打开配置文件,并将ident处更改为trust。
$ sudo postgresql-setup initdb
$ sudo vi /var/lib/pgsql/data/pg_hba.conf
~~~前略~~~
# "local" is for Unix domain socket connections only
local all all peer
# IPv4 local connections:
host all all 127.0.0.1/32 trust #ここを変更
# IPv6 local connections:
host all all ::1/128 trust #ここを変更
# Allow replication connections from localhost, by a user with the
~~~以下略~~~
我們將啟動系統。
$ sudo systemctl start postgresql
$ sudo systemctl enable postgresql
$ psql -h localhost -p 5432 -U postgres
如果成功启动,我们将设置数据库为django,用户名为django,密码为django。
请根据需要适当修改每个名称。
我们还会更改为Django的推荐设置。
postgres=# CREATE DATABASE django;
CREATE DATABASE
postgres=# CREATE USER django WITH PASSWORD 'django';
CREATE ROLE
postgres=# ALTER ROLE django SET client_encoding TO 'utf8';
ALTER ROLE
postgres=# ALTER ROLE django SET default_transaction_isolation TO 'read committed';
ALTER ROLE
postgres=# ALTER ROLE django SET timezone TO 'Asia/Tokyo';
ALTER ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE django TO django;
GRANT
回到命令行,并将密码认证的设置更改为新值。
打开配置文件,并将peer更改为md5。
$ sudo vi /var/lib/pgsql/data/pg_hba.conf
~~~前略~~~
# "local" is for Unix domain socket connections only
local all all md5 #ここを変更
# IPv4 local connections:
host all all 127.0.0.1/32 trust
# IPv6 local connections:
host all all ::1/128 trust
# Allow replication connections from localhost, by a user with the
$ sudo systemctl restart postgresql
到目前为止,PostgreSQL的设置已经完成了。
Django的配置
接下来,我们将进行Django的配置。
请根据需要适当更改用户名和数据库名称。
$ vi mysite/mysite/settings.py
变更之前
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
更改后
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'django',
'USER': 'django',
'PASSWORD': 'django',
'HOST': 'localhost',
'PORT': '',
}
}
一旦设置完成后,我们进行迁移操作。
$ cd mysite #manage.pyがある階層へ
$ python manage.py migrate
如果能做到这一点,协作就完成了。
我们来启动一下吧。
$ uwsgi --ini mysite_uwsgi.ini

请参考以下网站
使用venv创建Django环境(Python3.3及以上版本)
uWSGI官方文档
Django官方文档
使用pyenv构建Python执行环境
在Amazon Linux2(ec2)和CentOS7上安装最新版本的SQLite3
解决在Django 2.2启动开发服务器时出现SQLite3错误的方法
Django部署:Nginx、uWSGI
安装psycopg2并通过Python操作PostgreSQL
解决”amazon-linux-extras” → “No module named amazon_linux_extras”的方法
将PostgreSQL应用于Django