使用 Docker 让部署 Django 项目更加轻松


使用 Docker 让部署 Django 项目更加轻松

文章插图
 
作者:HelloGitHub-追梦人物
之前一系列繁琐的部署步骤让我们感到痛苦 。这些痛苦包括:
  • 要去服务器上执行 n 条命令
  • 本地环境和服务器环境不一致,明明本地运行没问题,一部署服务器上就挂挂,死活启动不起来
  • 如果上面的情况发生了,又要去服务器上执行 n 条命令以解决问题
  • 本地更新了代码,部署上线后,上述历史又重演一遍,想死的心都有了
那么我们有没有办法,让本地开发环境和线上环境保持一致?这样我们在部署上线前,就可以在本地进行验证,只要验证没问题,我们就有 99% 的把握保证部署上线后也没有问题(1%保留给程序玄学) 。
这个办法就是使用 Docker 。
Docker 是一种容器技术,可以为我们提供一个隔离的运行环境 。要使用 Docker,首先我们需要编排一个镜像,镜像就是用来描述这个隔离环境应该是什么样子的,它需要安装哪些依赖,需要运行什么应用等,可以把它类比成一搜货轮的制造图 。
有了镜像,就可以在系统中构建出一个实际隔离的环境,这个环境被称为容器,就好比根据设计图,工厂制造了一条船 。工厂也可以制造无数条这样的船 。
容器造好了,只要启动它,隔离环境便运行了起来 。由于事先编排好了镜像,因此无论是在本地还是线上,运行的容器内部环境都一样,所以保证了本地和线上环境的一致性,大大减少了因为环境差异导致的各种问题 。
所以,我们首先来编排 Docker 镜像 。
类似于分离 settings.py 文件为 local.py 和 production.py,我们首先建立如下的目录结构,分别用于存放开发环境的镜像和线上环境的镜像:
HelloDjango-blog-tutorial blog ... compose local production django Nginx ...local 目录下存放开发环境的 Docker 镜像文件,production 下的 django 文件夹存放基于本项目编排的镜像,由于线上环境还要用到 Nginx,所以 nginx 目录下存放 Nginx 的镜像 。
线上环境
镜像文件
我们先来在 productiondjango 目录下编排博客项目线上环境的镜像文件,镜像文件以 Dockerfile 命名:
FROM Python:3.6-alpineENV PYTHONUNBUFFERED 1RUN apk update# Pillow dependencies && apk add jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-devWORKDIR /AppRUN pip install pipenv -i https://pypi.douban.com/simpleCOPY Pipfile /app/PipfileCOPY Pipfile.lock /app/Pipfile.lockRUN pipenv install --system --deploy --ignore-pipfileCOPY . /appCOPY ./compose/production/django/start.sh /start.shRUN sed -i 's/r//' /start.shRUN chmod +x /start.sh首先我们在镜像文件开头使用 FROM python:3.6-alpine 声明此镜像基于 python:3.6-alpine 基础镜像构建 。alpine 是一个 linux 系统发行版,主打小巧、轻量、安全 。我们程序运行需要 Python 环境,因此使用这个小巧但包含完整 Python 环境的基础镜像来构建我们的应用镜像 。
ENV PYTHONUNBUFFERED 1 设置环境变量 PYTHONUNBUFFERED=1
接下来的一条 RUN 命令安装图像处理包 Pilliow 的依赖,因为如果使用 django 处理图片时,会使用到 Pillow 这个Python 库 。
接着使用 WORKDIR /app 设置工作目录,以后在基于此镜像启动的 Docker 容器中执行的命令,都会以这个目录为当前工作目录 。
然后我们使用命令 RUN pip install pipenv 安装 pipenv,-i 参数指定 pypi 源,国内一般指定为豆瓣源,这样下载 pipenv 安装包时更快,国外网络可以省略 -i 参数,使用官方的 pypi 源即可 。
然后我们将项目依赖文件 Pipfile 和 Pipfile.lock copy 到容器里,运行 pipenv install 安装依赖 。指定 --system 参数后 pipenv 不会创建虚拟环境,而是将依赖安装到容器的 Python 环境里 。因为容器本身就是个虚拟环境了,所以没必要再创建虚拟环境 。
接着将这个项目的文件 copy 到容器的 /app 目录下(当然有些文件对于程序运行是不必要的,所以一会儿我们会设置一个 dockerignore 文件,里面指定的文件不会被 copy 到容器里) 。
然后我们还将 start.sh 文件复制到容器的 / 目录下,去掉回车符(windows 专用,容器中是 linux 系统),并赋予了可执行权限 。
start.sh 中就是启动 Gunicorn 服务的命令:
#!/bin/shpython manage.py migratepython manage.py collectstatic --noinputgunicorn blogproject.wsgi:application -w 4 -k gthread -b 0.0.0.0:8000 --chdir=/app我们会让容器启动时去执行此命令,这样就启动了我们的 django 应用 。--chdir=/app 表明以 /app 为根目录,这样才能找到 blogproject.wsgi:application 。


推荐阅读