使用比较流行的 Nginx + Gunicorn 的方式将 Django 开发的博客部署到自己的服务器,让别人能够通过域名访问你的博客。
环境说明
服务器: 阿里云 ECS 服务器 操作系统: Ubuntu 16.04 x86_64
用户创建
通常我们是以 root 用户登录的,而在 root 下部署代码并不安全,最好是建一个新用户用于部署。
- 修改主机名
root@iZ8vbgxrlnet6jyi1l5crcZ:~# vim /etc/hostname localhost
- 重启生效
root@iZ8vbgxrlnet6jyi1l5crcZ:~# init 6
- 创建用户
root@localhost:~# useradd -m -s /bin/bash allenli
- 将新创建的用户加入超级权限组
root@localhost:~# usermod -a -G sudo allenli
- 为新用户设置密码
root@localhost:~# passwd allenli
- 切换到创建的新用户
root@localhost:~# su - allenli
安装 Python3.6
- 添加 python3.6 安装包并安装
allenli@localhost:~$ sudo apt-get install software-properties-common -y
- 修改系统默认 python 版本为 3.6
allenli@localhost:~$ sudo add-apt-repository ppa:jonathonf/python-3.6 -y allenli@localhost:~$ sudo apt-get update -y allenli@localhost:~$ sudo apt-get install python3.6 -y allenli@localhost:~$ cd /usr/bin/ allenli@localhost:~$ sudo rm python allenli@localhost:~$ sudo ln -s /usr/bin/python3.6m python allenli@localhost:/usr/bin$ python Python 3.6.5 (default, May 3 2018, 10:08:28) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>>
- 安装并升级 pip 版本
allenli@localhost:~$ sudo apt install python3-pip -y allenli@localhost:~$ pip -V pip 8.1.1 from /usr/lib/python3/dist-packages (python 3.6) allenli@localhost:~$ sudo pip install --upgrade pip allenli@localhost:~$ pip3 -V pip 18.0 from /usr/local/lib/python3.6/dist-packages/pip (python 3.6) allenli@localhost:~$ pip3 list Package Version ------------------- ---------------------- chardet 2.3.0 command-not-found 0.3 language-selector 0.1 pip 18.0 pycurl 7.43.0 pygobject 3.20.0 python-apt 1.1.0b1+ubuntu0.16.4.1 requests 2.9.1 setuptools 20.7.0 six 1.10.0 ssh-import-id 5.5 ufw 0.35 unattended-upgrades 0.1 urllib3 1.13.1 wheel 0.29.0
创建虚拟环境
- 安装虚拟环境包
allenli@localhost:~$ pip3 install virtualenv allenli@localhost:~$ pip3 install virtualenvwrapper # 用于管理虚拟环境
- 创建虚拟环境目录
allenli@localhost:~$ mkdir virtualenv
- 查看安装位置
allenli@localhost:~$ which virtualenvwrapper.sh /usr/local/bin/virtualenvwrapper.sh
- 添加至环境变量
allenli@localhost:~$ vim .bashrc export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python export WORKON_HOME=/home/allenli/virtualenv source /usr/local/bin/virtualenvwrapper.sh allenli@localhost:~$ source .bashrc
- 创建虚拟环境
allenli@localhost:~$ mkvirtualenv opcoder (opcoder) allenli@localhost:~$ workon opcoder
- 查看虚拟环境安装目录
(opcoder) allenli@localhost:~/virtualenv/opcoder/bin$ pwd /home/allenli/virtualenv/opcoder/bin
- 删除虚拟环境
allenli@localhost:~$ rmvirtualenv opcoder
- 退出虚拟环境
(opcoder) allenli@localhost:~$ deactivate
- 进入虚拟环境
allenli@localhost:~$ workon opcoder
- 查看虚拟环境中安装的 python 包
(opcoder) allenli@localhost:~$ pip list
安装 MySQL 数据库
安装数据库
- 更新系统
allenli@localhost:~$ sudo apt-get update
- 安装 MySQL
allenli@localhost:~$ sudo apt-get install mysql-server mysql-client
- 检查是否安装成功
allenli@localhost:~$ sudo netstat -tap | grep mysql
配置数据库连接
- 本地连接
allenli@localhost:~$ sudo mysql -uroot -ppassword
- 远程连接
# 1. MySQL 默认是只允许本地主机访问 127.0.0.1,并关闭了远程连接,所以安装之后需打开远程连接,并修改配置允许其他 ip 访问: allenli@localhost:~$ sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf 找到 bind-address = 127.0.0.1 这一行, 并注释 # 2. 重启 mysql 服务: allenli@localhost:~$ sudo service mysql restart allenli@localhost:~$ sudo service mysql status # 3. 重新登录 MySQL 数据库: allenli@localhost:~$ sudo mysql -uroot -ppassword mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec) mysql> use mysql; # 4. 将 host 设置为 % 表示任何 ip 都能连接 mysql: mysql> update user set host='%' where user='root' and host='localhost'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 # 5. 刷新权限表,使配置生效: mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) # 6. 阿里云的服务器设置了安全组规则来限制 ecs 服务器的 ip,端口访问策略。因此需要修改: 登录阿里云 => 控制台 => 云服务器ECS => 网络和安全 => 安全组 => 配置规则 => 添加安全组规则
创建 Django 项目
- 虚拟环境下安装依赖包
(opcoder) allenli@localhost:~$ pip install Django==2.0.6 (opcoder) allenli@localhost:~$ pip install PyMySQL==0.8.1
- 新建 Django Project
(opcoder) allenli@localhost:~$ django-admin.py startproject opcoder
- 查看文件目录
(opcoder) allenli@localhost:~/opcoder$ tree . ├── manage.py └── opcoder ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py 1 directory, 5 files
- 创建数据库 如果项目使用的是 MySQL 数据库的话,在项目运行之前需要先创建数据库:
allenli@localhost:~$ sudo mysql -uroot -ppassword mysql> CREATE DATABASE opcoder DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; Query OK, 1 row affected (0.00 sec)
说明: 因为需用到 emoji 表情, 所以字符集指定为 utf8mb4。
- 配置 Django 数据库连接
# 配置数据库连接 (opcoder) allenli@localhost:~$ vim opcoder/opcoder/settings.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'opcoder', 'USER': 'root', 'PASSWORD': 'password', 'HOST': '127.0.0.1', 'PORT': 3306, 'OPTIONS': {'charset': 'utf8mb4', } } }
# 更改默认数据库连接为 Mysql (opcoder) allenli@localhost:~$ vim opcoder/opcoder/__init__.py import pymysql pymysql.install_as_MySQLdb()
- 生成数据库
(opcoder) allenli@localhost:~$ cd opcoder/ (opcoder) allenli@localhost:~/opcoder$ python manage.py makemigrations (opcoder) allenli@localhost:~/opcoder$ python manage.py migrate
- 创建超级管理员身份
(opcoder) allenli@localhost:~/opcoder$ python manage.py createsuperuser
- 配置 HOSTS
默认使用
http://ip:8000
方式访问,如果要支持域名访问,需进行配置:
(opcoder) allenli@localhost:~$ vim opcoder/opcoder/settings.py ALLOWED_HOSTS = ['47.92.145.59', '127.0.0.1', 'localhost', '.opcoder.cn']
- 启动项目
(opcoder) allenli@localhost:~/opcoder$ python manage.py runserver 0.0.0.0:8000
说明: 1. 47.92.145.59 为阿里云 ECS 服务器 IP 地址, 添加后可以使用 http://47.92.145.59:8000/ 方式访问 2. runserver 0.0.0.0:8000 表示开启 django dev server,不限制访问 ip 3. 需要确认阿里云 ECS 服务器是否已开通 8000 端口,如果未开通,可以按照如下操作开通: 登录阿里云 => 控制台 => 云服务器ECS => 网络和安全 => 安全组 => 配置规则 => 添加安全组规则
部署 Nginx
Nginx 是用来处理静态文件请求的。比如当我们访问一个博客文章详情页面时,服务器会接收到下面两种请求:
- 显示文章的详情信息,这些信息通常保存在数据库里,因此需要调用数据库获取数据
- 图片、css、js 等存在服务器某个文件夹下的静态文件。
对于前一种请求,博客文章的数据需要借助 Django 从数据库中获取,Nginx 处理不了,它就会把这个请求转发给 Django,让 Django 去处理。
而对于后一种静态文件的请求,只需要去这些静态文件所在的文件夹获取,Nginx 就会代为处理,不再麻烦 Django,用 Django 去获取静态文件是很耗时的,但 Nginx 可以很高效地处理,这就是我们要使用 Nginx 的原因。
安装 Nginx
- 安装Nginx
allenli@localhost:~$ sudo apt-get install nginx
- 启动Nginx
allenli@localhost:~$ sudo service nginx start
- 在浏览器中输入域名或 ip 检查是否安装成功
收集静态文件
Django 项目中会有一些 CSS、JavaScript 等静态文件,为了能够方便地让 Nginx 处理这些静态文件的请求,我们把项目中的全部静态文件收集到一个统一的目录下。
- 在 django 的 setting 文件中,添加下面一行内容:
(opcoder) allenli@localhost:~$ vim opcoder/opcoder/settings.py STATIC_ROOT = os.path.join(BASE_DIR, 'static') # 设置静态文件路径
- 收集静态文件
(opcoder) allenli@localhost:~/opcoder$ python manage.py collectstatic
说明: 如果打开网站,发现 CSS 、JS 无法正常加载,可以重新收集静态文件。
配置 Nginx
配置 Nginx 来处理用户请求。
- 创建一个 Nginx 配置文件
allenli@localhost:~$ mkdir -p /home/allenli/opcoder/logs allenli@localhost:~$ sudo vim /etc/nginx/sites-available/mynginx server { # 字符集 、端口 、域名 charset utf-8; listen 80; server_name www.opcoder.cn; # 日志 access_log /home/allenli/opcoder/logs/nginx.access.log; error_log /home/allenli/opcoder/logs/nginx.error.log; # 不记录访问不到 favicon.ico 的报错日志 location = /favicon.ico { access_log off; log_not_found off; } # static 和 media 的地址(与settings文件中保持一致) location /static/ { root /home/allenli/opcoder; } location /media/ { root /home/allenli/opcoder; } # gunicorn 中生成的文件的地址 location / { include proxy_params; proxy_pass http://unix:/home/allenli/opcoder/opcoder.sock; } } server { listen 80; server_name opcoder.cn; rewrite ^(.*) http://www.opcoder.cn$1 permanent; }
说明: 1. 第一个 server 是主要的配置,第二个 server 是实现 301 跳转,即让不带 www 的域名跳转到带有 www 的域名上面 2. /home/allenli/opcoder为Django 项目的主文件夹 3. roxy_pass 后面使用了 unix 套接字,其作用是防止端口冲突。
连接 Nginx 配置
上面的配置检查好之后,使用下面的命令来将这个配置跟 Nginx 建立连接。
- 建立连接
allenli@localhost:~$ sudo ln -s /etc/nginx/sites-available/mynginx /etc/nginx/sites-enabled
- 检查 Nginx 的运行情况
allenli@localhost:~$ sudo nginx -t allenli@localhost:~$ sudo systemctl status nginx
- 重启 Nginx
allenli@localhost:~$ sudo systemctl restart nginx
说明: 如果修改了 Nginx 的配置文件,那么需要依次执行下面两条语句去重启服务:
~$ sudo nginx -t ~$ sudo systemctl restart nginx
部署 Gunicorn
- gunicorn是一个python Wsgi http server,能够与各种wsgi web框架协作
- gunicorn 在你的 Web 服务器和 Django 之间作为中间服务器使用
- Gunicorn 一般用来管理多个进程,有进程挂了Gunicorn 可以把它拉起来,防止服务器长时间停止服务,还可以动态调整 worker 的数量,请求多的时候增加 worker 的数量,请求少的时候减少。
安装和配置 Gunicorn
- 在虚拟环境中安装 Gunicorn
(opcoder) allenli@localhost:~$ pip install gunicorn
- 创建项目的 Gunicorn 配置文件(退出虚拟环境)
(opcoder) allenli@localhost:~$ deactivate allenli@localhost:~$ sudo vim /etc/systemd/system/gunicorn_opcoder.service [Unit] Description=gunicorn daemon After=network.target [Service] User=allenli WorkingDirectory=/home/allenli/opcoder ExecStart=/home/allenli/virtualenv/opcoder/bin/gunicorn --access-logfile - --workers 2 --bind unix:/home/allenli/opcoder/opcoder.sock opcoder.wsgi:application [Install] WantedBy=multi-user.target 说明: 1. User 表示当前用户名 2. WorkingDirectory 表示项目地址 3. ExecStart 表示虚拟环境中 gunicorn 的目录 4. workers 2 表示2个进程,可以自己更改 5. unix 表示生成一个 sock 文件的地址 6. opcoder.wsgi 表示项目中 wsgi.py 的地址
启动配置文件
- 启动服务
allenli@localhost:~$ sudo systemctl start gunicorn_opcoder
- 加入开机启动
allenli@localhost:~$ sudo systemctl enable gunicorn_opcoder
- 检查服务状态
allenli@localhost:~$ sudo systemctl status gunicorn_opcoder
- 检查项目的跟目录下面,是否会多一个 opcoder.sock 文件
说明: 1. 后续如果对 gunicorn 配置文件做了修改,那么应该先使用这个命令之后重启 allenli@localhost:~$ sudo systemctl daemon-reload 2. 然后再使用重启命令 sudo systemctl restart gunicorn_opcoder
注: 如果对生产环境 Django 代码进行变更,发现未生效,可以重启 gunicorn 服务。
代码迁移
将测试环境代码部署至生产环境后,部分代码需要进行相应的修改。
文件上传URL
将测试库代码部署至生产环境后,若发现用户头像不能显示,需进行如下配置。
- urls.py
from django.conf.urls.static import static from django.conf import settings ... urlpatterns = [ url(r'admin/', admin.site.urls), ..., ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) # 加入这个才能显示media文件
全局404和500页面配置
- 修改settings文件,将DEBUG模式设置为False
# settings.py DEBUG = False
- 创建全局404和500处理函数
# users/views.py from django.shortcuts import render_to_response def page_not_found(request): ''' 全局404处理函数 ''' return render_to_response('404.html') def page_error(request): ''' 全局500处理函数 ''' return render_to_response('500.html')
访问页面
经过上述一系列操作后, 我们就可以正常访问页面了。 www.opcoder.cn
参考资料
http://www.tendcode.com/article/set-up-django-with-nginx-and-gunicorn/
https://www.cnblogs.com/justbreaking/p/7110447.html
原创文章,转载请注明出处:http://www.opcoder.cn/article/1/