前情提要
- 上一节讲解了如何配置fabric环境,以及写了一个简单的demo
- 这一节主要讲解用fabric实现django项目自动化部署的实现,其它项目只需要加上自己的理解修改一下就可以了
django项目部署流程
- 自动化部署实际上就是模拟一遍人工部署的流程而已,所以我们需要先了解一个django项目部署的流程
- 项目在经过测试后觉得没有问题,需要将代码中的develop环境改成product环境,此时django服务器自带的图片渲染功能失效,需要安装nginx服务以达成负载均衡和图片服务的作用
- 服务器安装好nginx,但是很明显服务器上什么都没有,因此需要首先确保服务器的环境(python版本、pip、数据库等)和本地环境保持一致
- 环境配置好了,但是代码不在服务器上,此时需要使用git将远程仓库的代码clone到服务器上
- 代码有了,但是运行程序所需的依赖没有,此时使用命令pip install -r requirements.txt来安装依赖
- 依赖弄好了,数据库里面表还没有创建,输入命令python manage.py migrate来创建表
- 表有了,但是静态文件没有收集,需要使用命令python manage.py collectstatic来收集静态文件,收集后的静态文件目录需要在nginx中进行配置,否则访问不到
- 以上步骤弄好了,基本就准备完毕了,将项目后台运行即可
将思路映射为代码
- 有了思路以后,将思路写成python程序,请自行阅读注释理解
import os
from fabric.api import (
env, run, prefix, local, settings,
roles, cd
)
from fabric.contrib.files import exists, upload_template
from fabric.decorators import task
from fabric.utils import abort
'''
对env进行配置,fabric运行时会自动调用env中的配置
env.roledefs是一种方便的写法,其实和键值对是等效的
'''
# 设置远程服务器,注意服务器的格式是 主机名@公网ip:22 的形式,键的名字随意
env.roledefs = {
'myserver': ['ubuntu@49.234.220.132:22']
}
# 设置远程服务器登录密码
env.passwords = {
'ubuntu@49.234.220.132:22': '123456'
}
# 设置远程主机名
env.HOST_NAME = 'ubuntu'
# 设置django项目工程的名字,即使用django-admin startproject命名的名字
env.PROJECT_NAME = 'project'
# 设置虚拟环境的名字,建议项目创建虚拟环境,在隔离性,可维护性上都有很大优势
env.VENV_NAME = 'project-env'
# 设置远程服务器虚拟环境所在目录,下面组成起来就是 /home/ubuntu/Django/venvs,os模块可以有效地解决跨平台的问题
env.VENVS_PATH = os.path.join('/home', env.HOST_NAME, 'Django', 'venvs')
# 设置远程服务器虚拟环境目录
env.VENV_PATH = os.path.join(env.VENVS_PATH, env.VENV_NAME)
# 设置激活虚拟环境的命令(linux版本)
env.VENV_ACTIVATE = os.path.join(env.VENV_PATH, 'bin', 'activate')
# 设置项目仓库所在路径(一般项目仓库都在虚拟环境目录下)
env.GIT_PATH = os.path.join(env.VENV_PATH, env.PROJECT_NAME)
# 设置github代码的地址,最好用ssh的地址
env.GIT_REMOTE = 'git@gitee.com:kimu/studio.git'
# 设置项目所在路径(项目在项目仓库目录下)
env.PROJECT_PATH = os.path.join(env.GIT_PATH, env.PROJECT_NAME)
def _ensure_python3():
"""
确保python环境在服务器上已存在
"""
with settings(warn_only=True):
local('echo 开始确认远程服务器是否存在python3...')
# run命令用于在远程主机上执行命令
result = run('python3 --version')
if result.failed:
local('echo 远程服务器没有python3,开始在远程服务器上安装python3...')
run('sudo apt-get install python3')
def _ensure_python3_pip():
"""
确保python的第三方包管理库pip
"""
with settings(warn_only=True):
local('echo 开始确认远程服务器是否存在pip...')
result = run('pip3 --version')
if result.failed:
local('echo 远程服务器不存在python3-pip,开始安装python3-pip...')
run('sudo apt-get install python3-pip')
def _ensure_virtualenv():
"""
确保服务器内有相对应的虚拟环境
"""
with settings(warn_only=True):
local('echo 开始确认远程服务器是否存在项目所需虚拟环境...')
if not exists(env.VENV_PATH):
local('echo 开始在远程服务器上创建虚拟环境...')
# 先创建虚拟环境外部的文件夹
if not exists(env.VENVS_PATH):
run('mkdir -p %s' % env.VENVS_PATH)
# 安装python创建虚拟环境需要的依赖
run('pip3 install python3-venv')
# 用虚拟环境库创建虚拟环境
run('python3 -m venv %s' % env.VENV_PATH)
def _ensure_git_project():
"""
确保服务器内有对应的代码,并且是最新的状态,且依赖已更新
"""
# 在执行这段代码的时候,必须是虚拟环境已存在的情况
with prefix('source %s' % env.VENV_ACTIVATE):
with settings(warn_only=True):
local('echo 开始确认远程服务器是否有最新的项目代码...')
# 判断项目仓库是否存在
if not exists(env.GIT_PATH):
local('echo 项目仓库不存在,开始在远程服务器上clone项目...')
# -C 指定clone的位置
run('git -C %s clone %s' % (env.VENV_PATH, env.GIT_REMOTE))
else:
# 仓库存在,但是代码不是最新,更新即可
local('echo 项目仓库存在,开始更新代码...')
run('git -C %s pull' % env.GIT_PATH)
# 项目代码确保后,更新依赖
local('echo 开始更新项目依赖...')
run('pip3 install -r %s' % os.path.join(env.GIT_PATH, 'requirements.txt'))
def _ensure_mysql():
"""
确保能够完成django的数据库迁移,即在数据库中创建更新表
"""
with prefix('source %s' % env.VENV_ACTIVATE):
with settings(warn_only=True):
local('echo 开始对数据库进行迁移...')
result = run('python3 % migrate' % os.path.join(env.PROJECT_PATH, 'manage.py'))
if result.failed:
abort('远程服务器数据库不存在,请先创建数据库!')
def _ensure_static():
"""
确保静态文件成功被收集,nginx需要用到它们
"""
with prefix('source %s' % env.VENV_ACTIVATE):
with settings(warn_only=True):
local('echo 开始收集静态文件...')
result = run('python3 %s collectstatic' % os.path.join(env.PROJECT_PATH, 'manage.py'))
if result.failed:
abort('django的静态文件路径配置有问题,请检查!')
@task
@roles('myserver')
def deploy():
"""
自动化部署任务,task将其指定为一个远程执行的任务,roles指定在哪些服务器上执行
"""
# 确保python3
_ensure_python3()
# 确保pip
_ensure_python3_pip()
# 确保虚拟环境已存在
_ensure_virtualenv()
# 以下操作都需要在激活虚拟环境的前提下执行
# 确保代码和依赖
_ensure_git_project()
# 确保数据库迁移
_ensure_mysql()
# 确保静态文件成功被收集
_ensure_static()
# 所有条件都已经满足,如果nginx的配置正确,就可以正常运行项目了,这里推荐使用supervisord管理gunicorn运行
with cd(settings.GIT_PATH):
run('supervisorctl -c conf/supervisord.conf')
run('restrat all')
在服务器上还需要配置什么?
- ssh服务,为了不用输入密码就可以拉取自己github代码
- nginx,当然也可以用fabric进行自动化配置
至此,django的自动化部署已讲解完毕,有兴趣的读者可以自己写一个简单的项目并且进行部署