2018年01月18日

Docker+Django+Vue联合开发环境搭建

作者 非鱼

项目目标:开启一个新项目的时候,初始化一堆乱七八糟的环境和基础框架是最费心费力了,可能你两三天都没办法开始写业务逻辑或者页面。所以,如果能有一个比较万能的脚手架项目,以后直接复制这个代码出来开始写自己的业务逻辑就好办多了。

目前比较理想的项目框架是Vue做单页面前端,Django(或者其它语言)只做后端restful接口,但发布时是要作为一个站点一起发布的。另外还要考虑到开发过程中的方便性,因此才有了这篇示例文章,作为一个开始新项目的简单指引。

首先,需要做两个Docker镜像,一个Nginx,一个Django+Vue环境。可以基于alpine linux从干净环境开始安装,Nginx镜像也可以直接下载官方版本,自己只需要写站点的conf文件就可以了,它只负责一件事:把站点的请求转发到vue的8080端口,同时把/api/目录的请求转发到django的8000端口。

然后开始建设项目结构:(映射当前目录到django+vue容器,并在docker中执行以下命令)

django-admin startproject website_t
cd website_t
django-admin startapp backend
vue init webpack frontend
cd frontend
npm install

这样外层的django负责整个站点,api接口实现在backend的views里面,当然业务逻辑很多的时候直接使用多个app目录分别负责就可以了,在urls里面按照api/+业务子目录的形式来区分。frontend目录就是vue的项目目录,该目录不包含后端逻辑,纯前端代码。

在backend/views.py里面增加一个方法:

from django.http import JsonResponse
def index(request):
    return JsonResponse({'foo': 'bar'})

修改website_t下面的urls.py,添加一个api/目录的URL映射: path(‘api/’, include(‘backend.urls’)),
同时添加backend下面的urls.py文件,增加一个URL定义:

from django.urls import path, include
from backend import views
urlpatterns = [
    path('', views.index),
]

这样在启动django站点之后访问/api/应该就可以看到这个返回的json信息。

接下来启动一个vue容器,直接映射frontend这一级目录,并指定启动命令为npm run dev,这样vue的开发环境就启动起来了,并可以通过8080端口访问,修改了vue的文件之后它也是即时生效的。
然后再启动一个django容器,映射website_t这一级目录,并指定启动命令为python manage.py runserver 0.0.0.0:8000,这样django的开发环境就启动起来了,可以通过8000端口访问,而且修改了django的python文件以后它也是即时生效的。
然后需要启动一个nginx容器,分别用vue和django的别名link到另外两个容器上,同时映射一个站点conf文件到/etc/nginx/conf.d目录,内容是:

server{
    listen 80;
    server_name _;
    location / {
        proxy_pass http://vue:8080;
    }
    location /api/ {
        proxy_pass http://django:8000;
    }
}

这样nginx容器启动以后,在浏览器里面访问localhost,打开的静态页面就是Vue的页面,在Vue的页面里使用ajax请求/api/目录下的接口,就可以直接访问到django的代码。
docker的启动脚本差不多是这样的:

docker run -d --rm --name django -v $PWD:/app djangovue python manage.py runserver 0.0.0.0:8000
docker run -d --rm --name vue -v $PWD/frontend:/app djangovue npm run dev
docker run -d --rm --name nginx -v $PWD/nginxconf:/etc/nginx/conf.d -p 80:80 --link django:django --link vue:vue nginx

PS:默认情况下这样访问Vue还会有些问题,会报Invalid Host Header的错误,这个是webpack的一个限制,需要在frontend/build/webpack.dev.conf.js里面的devServer段添加一个配置项:disableHostCheck:true,同时需要修改frontend/conf/index.js里面的host配置为:host: ‘0.0.0.0’,这样配置以后才能正常访问。

如果某次代码写错导致vue或者django崩了,重启这个docker容器即可。

至此整个开发环境就算完成了,可以开始写代码了。

到正式发布站点的时候,django需要配置成使用uwsgi来运行,而不是使用manage.py runserver,vue需要在frontend目录下运行一次npm run build,打包后的HTML和JS,CSS等文件在frontend/dist目录下。
配置生产环境的Nginx站点conf文件,项目root目录指向frontend/dist目录,然后将api/转发给uwsgi,其它路径全部通过

location / {
    try_files $uri $uri/ /index.html;
}

来处理,即可实现静态文件和接口文件的访问。(理论上django不再处理除restful接口外的任何请求,否则还要处理Django的static文件)