使用 Django 搭建了一个网站,在部署到生产环境 Ucloud 时遇到了神坑无数,花费了4个夜晚才算是解决。这里尽可能记录部署的过程,遇到的问题,以及解决办法,希望能帮助像我一样的后端开发小白,少踩一些坑。
前提条件
- 本地可以正常运行的 Django 项目,哪怕是一个 Hello World
- Ucloud 云主机 或者其他平台的云主机
- 域名(没有也可以)
云主机服务器创建
这个没什么难度,按照第三方给的文档,一步步走下去就可以。关键是云主机创建完成之后,会有一个内网 IP,还有一个外网 IP。这两个 IP 后面做 DNS 解析要用到。我这里创建的服务器的系统是 Ubuntu 12.04。建议使用 Linux 系列的。
有一个技巧是,创建完系统,登陆时,Ubuntu 的默认登陆名是 ubuntu,密码是自己设置的。为什么之前没人告诉我呢,害我找了好久,通过客服才解决这个问题。
默认的系统中,安装的是有 ssh 的,这样就可以通过 ssh 连接到服务器。命令如下
ssh user@ip_address
user 是登陆的用户名,默认是 ubuntu。
ip_address 就是创建云主机指定的外网 ip。之后会让输入密码,就是主机设置的登陆密码。
下面就可以把这个当做本地的一台 Ubuntu 系统的电脑使用,安装必要的软件,唯一不同的是,这个是真的没有 GUI 界面。
Python 相关软件安装
Ubuntu 系统中默认安装 Python 2.7 版本,生产环境中,就使用这个版本。下面会安装 pip
apt-get update
apt-get install python-pip
基本都是傻瓜式的,不用做什么操作。
pip 安装之后,在安装 Python 开发必须使用的两个扩展 virtualenv 和 virtualenvwrapper
pip install virtualenv
默认安装在 /usr/local/bin 目录下的
安装 virtualenvwrapper 管理 vritualenv
pip install virtualenvwrapper
在 .bashrc 中添加如下代码
export VIRTUALENV_USE_DISTRIBUTE=1 # 总是使用 pip/distribute
export WORKON_HOME=$HOME/Envs # 所有虚拟环境存储的目录
if [ -e $HOME/Envs/bin/virtualenvwrapper.sh ];then
source $HOME/Envs/bin/virtualenvwrapper.sh
else if [ -e /usr/local/bin/virtualenvwrapper.sh ];then
source /usr/local/bin/virtualenvwrapper.sh
fi
fi
export PIP_VIRTUALENV_BASE=$WORKON_HOME
export PIP_RESPECT_VIRTUALENV=true
添加后执行下面命令
source .bashrc
这个时候就可以使用 virtualenvwrapper 管理 virtualenv 了。virtualenvwrapper 的常用命令,可以使用 virtualenvwrapper --help 查看。为了使用方便,我配置了几个别名
alias lsenv='lsvirtualenv'
alias mkenv='mkvirtualenv'
alias rmenv='rmvirtualenv'
上面三个命令,再加上一个 workon 基本就够用了。
如果关于 virtualenv 和 virtualenvwrapper 配置有不明白的地方,可以参考这篇文章
python 虚拟环境设置参考1
python 虚拟环境设置参考2
配置完虚拟环境之后,我们就创建一个虚拟环境
mkenv django
创建完之后,默认会切换到 django 环境中。
上传代码到服务端
平常也经常听我们服务端的开发说,发布代码,功能上线,至于怎么发布代码,如何上线却不了解。我这里使用了一个简单的方法,我的代码原本托管在 coding 上 。我就在服务器上把最新的代码拉下来,不久可以了吗,实现了曲线发布。
Ubuntu 上默认安装有 Git ,要想使用 ssh 拉取代码,还需要配置下 ssh key。不然每次输入用户名,密码绝壁要烦死。
ssh key 公钥 配置,可以参考整
下面就是找个目录,把代码拉到服务器上。
安装第三方依赖库
项目中,添加第三方依赖之后,一般都会通过 pip freeze 命令及时的更新依赖列表 requirement.txt
pip freeze -> requirement.txt
这个命令会将依赖的第三方库信息保存在requirement.txt 中。
pip install -r requirement.txt
这个命令会将 requirement.txt 上的所有第三方库全部安装。
Mysql 安装和配置
安装 Mysql 以及相关的依赖工具
apt-get install mysql-server mysql-client libmysqld-dev
Mysql 安装过程中会让设置一个秘密,这里就默认为 root
安装成功之后,登陆 Mysql,命令为
mysql -u root -p
使用 root 账号登陆 mysql
创建个新用户 imeosng
CREATE USER 'imesong'@'%' IDENTIFIED BY 'imesong'
创建一个 用户 imesong,密码为 imesong
GRANT ALL ON *.* TO 'imesong'@'%';
对 imesong 用户授权 完全的读写权限。 ON 后面的 . 表示 所有数据库,所有表 @ 后面的 % 表示所有主机,All 表示所有的权限,包括 SELECT,INSERT等。
数据库用户的创建,还请大家参考这篇文字 MySQL创建用户与授权
创建数据库
CREATE databases 11it
创建一个名称为 11it 的数据库。
使用 show databases
可以查看当前有哪些数据库
使用 use 11it
使用 11it 数据库
show tables
查看当前的数据库表
uwsgi 安装配置
uwsgi 使用 pip 安装
apt-get install uwsgi uwsgi-plugin-python
配置 uwsgi
vim /etc/uwsgi/apps-available/11it.ini
创建 11it.ini 配置文件,文件名可以自己任意修改,只有符合命名规范
文件内容如下
[uwsgi]
# Django 项目的 project name
project = mxonline
# project 的目录地址,这个目录要修改为自己的项目对应的目录
base = /home/ubuntu/coding
# 代码根目录
chdir = %(base)/%(project)
# Model 名称
module = MxOnline.wsgi
vhost = true
plugins = python
# socket 连接文件地址,这个很重要
socket = /tmp/11it.sock
master = true
vacuum = true
enable-threads = true
#开启4个进程
process = 4
#socket 文件连接的权限
chmod-socket = 666
# 虚拟环境目录
virtualenv = /home/ubuntu/Envs/11it
# 这个不知道做什么的,会在指定目录下创建一个文件,这个目录要保证有读写权限
touch-reload = %(base)/%(project)/reload
然后将 apps-available 中的配置文件 ln 到 apps-enabled 文件夹中
ln -s /etc/uwsgi/apps-available/11it.ini /etc/uwsgi/apps-enabled/
nginx 安装配置
安装 Nginx
apt-get install nginx
配置 Nginx
vim /etc/nginx/sites-available/11it
配置文件如下
server {
# 监听的端口
listen 80;
#解析的域名
server_name www.xxx.com xxx.com;
#访问日志存放路径
access_log /var/log/nginx/11it.access.log;
#错误日志存放路径
error_log /var/log/nginx/11it.error.log;
location / {
# uwsgi 连接 nginx
include uwsgi_params;
# 通过 socket 连接 uwsgi 。后面对应的就是在 uwsgi 配置文件中创建的 sock 文件 ,添加 上 unix:/ 。
uwsgi_pass unix:///tmp/11it.sock;
}
location /media/ {
# 解析 media 目录。这个目录在 Django 项目中用于用户上传的媒体文件,具体的路径,以自己的项目中路径为准
alias /home/ubuntu/coding/mxonline/media/;
}
location /static/ {
# static 文件路径。这个目录也是在Django 项目中生成的,并且配置的这个目录,还要在 Django 的 setting.py 文件中保持一致,不然会出现无法加载静态文件,导致 css,js 文件无法加载。
alias /home/ubuntu/coding/mxonline/static/;
}
}
接下来将 sites-available 文件夹中刚才添加的文件 ln 到 sites-enabled 文件夹中
ln -s /etc/nginx/sites-available/11it /etc/nginx/sites-enabled/
配置完成之后,我们验证下 nginx 的配置是否成功
sudo service nginx configtest
如果显示 ok ,证明配置没有问题。
启动 nginx 和 uwsgi
sudo service nginx restart
sudo service uwsgi restart
在浏览器中,使用云主机的 外网 ip 访问下,可以看到 nginx 的欢迎页面。
静态文件代理
nginx 主要做静态文件的处理,我们在配置文件中指定了静态文件的路径,但是我们并不是所有的文件都在static 目录中。开发环境和生产环境中 ,对静态文件的路径配置还不同。
生产环境中做如下修改
setting.py 中
# 新增 static 目录,存放项目所有的静态资源
STATIC_ROOT = os.path.join(BASE_DIR, "static")
# 这个注释掉
#STATICFILES_DIRS = (
# os.path.join(BASE_DIR, "static"),
#)
在项目根目录运行命令
python manage.py collectstatic
Django 会将所有用到的静态文件,包括第三方库中的,copy 一份放在 setting.py 中配置的 STATIC_ROOT 中。
启动 uwsgi
uwsgi --ini /etc/uwsgi/apps-available/11it.ini
域名解析配置
域名解析看自己的域名服务商,主要配置 A 记录和 www 记录
以上,基本上完成了我们 Django 生产环境的部署,当然还有很多细节问题没有记录。
下面是一些参考链接
https://foofish.net/django-deploy.html
http://www.jianshu.com/p/d7b9c468f20d
https://www.doraemonext.com/archives/552.html
http://stackoverflow.com/questions/21820444/nginx-error-13-permission-denied-while-connecting-to-upstream
http://pengjunjie.com/blog/single/83/
http://projectsedu.com/2017/02/07/centos7-%E4%B8%8B%E9%80%9A%E8%BF%87nginx-uwsgi%E9%83%A8%E7%BD%B2django%E5%BA%94%E7%94%A8/
http://www.cnblogs.com/jhao/p/6071790.html
https://zhuanlan.zhihu.com/p/25080236
看到这么多参考链接,你就该想到,我在部署时遇到了多少坑吧。
祝大家部署顺利!