本文章为原创内容,只发布于 CSDN 博客 和 我的私人博客,转载请注明,谢谢
基于 Docker 的 Django 容器化部署教程分为三部分,当前所在的是第一部分
- 基于 Docker 的 Django 容器化部署之一:定制属于自己的 docker 镜像
- 基于 Docker 的 Django 容器化部署之二:docker-compose 部署 Django 项目
- 基于 Docker 的 Django 容器化部署之三:定时备份,两步实现服务器迁移
项目部署一直都是很繁琐的事情,由于开发环境和上线服务器的环境不同,所以各种依赖软件包的安装、迭代更新的部署、各种命令的执行都是问题,由此容器化进行项目上线就是一个很好的解决办法。
本次使用的是 Docker
,属于 Linux 容器
的一种封装,提供简单易用的容器使用接口。docker
将应用程序与该程序的依赖打包到一个文件里面,运行这个文件,就会生成一个轻量级、可移植的虚拟容器,然后发布到任何流行的 Linux 或 Windows 机器上,程序在这个虚拟容器里面运行就像在真实的物理机上面运行一样。这种容器技术,可以为我们提供一个隔离的运行环境,并且只提供我们所需要的内容。
了解 docker 及 docker-compose
Docker
Docker
的整个生命周期由三部分组成:镜像(image)
+ 容器(container)
+ 仓库(repository)
。
Docker
可以生成多个镜像,每个镜像,可以创建多个容器。可以理解成:每一个容器都是一个独立的虚拟操作系统,互不影响,而镜像就是这个操作系统的安装包。想要生成一个容器,就要用安装包(镜像)生成一次,这就是 Docker
的核心概念。发布到仓库(比如 DockerHub
)时,是以镜像为单位。
镜像,是一个只读的模板,一个独立的文件系统,包括运行容器所需的数据,可以用来创建新的容器。镜像可以包含一个完整的
Linux
操作环境,里面仅安装了Python
或者其他用户需要的程序。容器,是由镜像实例化而来,容器是基于镜像创建的,即容器中的进程依赖于镜像中的文件,类似虚拟机,里面可以运行特定的应用,并且容器与容器是相互隔离的。这有点像面向对象的概念:镜像就是类,容器是类实例化之后的对象。
仓库,与
Git
和Github
类似,Docker
使用的默认仓库是由官方维护的Docker hub
公共仓库,此仓库是用来包含镜像的位置,同时其还提供了一个注册服务器(register)来保存多个仓库,每个仓库又可以包含多个具备不同tag
的镜像,而仓库支持的操作如上传、拉取等动作类似于Git
。
docker-compose
Docker Compose
是 docker
提供的一个命令行工具,用来定义和运行由多个容器组成的应用。使用 compose,我们可以通过 YAML
文件声明式的定义应用程序的各个服务,并由单个命令完成应用的创建和启动。简单来说,就是用来编排多个容器,将启动容器的命令统一写到 docker-compose.yml
文件中,一次启动全部启动。
安装 docker 及 docker-compose
- 参考 centos7 安装 docker-ce 和 docker-compose
- 参考 Debian9 安装 docker-ce 和 docker-compose
- 参考 Github Actions:云打包创建 docker 镜像
基于 Dockerfile 构建镜像
打包镜像,就要用到一个文本文件,这个文本默认名称就是 Dockerfile
.
镜像构建的过程中有一个非常重要的概念就是分层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。
先来看一下我的目录结构,这样子编排是因为后面要使用 docker-compose
.
├── django
├── docker-compose.yml
└── nginx
在项目的根目录下新建一个 Dockerfile
文件,无后缀,写入下面内容
# 从仓库拉取 python 官方的 image,:3.7就是标签,代表是 3.7 版本的 python 镜像
FROM python:3.7
# 作者信息
LABEL "author"="HONGWEI"
LABEL "blog"="https://www.zhwei.cn/"
LABEL "E-mail"="i@zhwei.cn"
# 设置 python 环境变量
ENV PYTHONUNBUFFERED 1
# 构建参数
## 定义存放本机中的 django 项目的目录
ARG work_dir=/opt/hw-blog
# 在镜像中创建目录并设置项目运行的工作目录
RUN mkdir -p ${work_dir}
WORKDIR ${work_dir}
# 将 django 的源码复制到容器的工作目录,其中requirements.txt在里面
ADD ./django ${work_dir}
# 安装依赖包
RUN pip install -r requirements.txt
构建镜像
docker build -t hw-website .
构建完之后查看一下docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hw-website latest 4ff*****1cae About a minute ago 1.06GB
定制属于自己的 docker 镜像
当你以上面的方式进行打包镜像的时候你会发现镜像的体积很大,并且里面有好多包是我们不需要的
- Centos 的 Python 3.7 的镜像 900M+,包含 python2
- Ubuntu 的 Python 3.7 的镜像 800M+,
- Python:3.7-alpine 镜像 90M+,但好多东西没有,需要自己构建
所以我们就要进行自己定制,里面只有我需要的
Dockerfile
# 从仓库拉取 带有 python 3.7 的 Alpine Linux 环境
FROM python:3.7-alpine
# 作者信息
LABEL "author"="HONGWEI"
LABEL "blog"="https://www.zhwei.cn/"
LABEL "E-mail"="i@zhwei.cn"
# 构建参数,工作目录
ARG work_dir=/opt/hw-blog
RUN mkdir -p ${work_dir}
WORKDIR ${work_dir}
# 将当前目录复制到容器的工作目录
ADD ./django ${work_dir}
# 安装alpine依赖, system update\ mysqlclient\ system lib\ Pillow\ bash
RUN apk update \
&& apk add --virtual mysqlclient-build gcc python3-dev musl-dev \
&& apk add --no-cache mariadb-dev \
&& apk add --virtual system-build linux-headers libffi-dev \
&& apk add --no-cache jpeg-dev zlib-dev freetype-dev lcms2-dev openjpeg-dev tiff-dev tk-dev tcl-dev \
&& apk add --no-cache bash bash-doc bash-completion \
&& pip install pip -U \
&& pip install -r ${work_dir}/requirements.txt
# 在Alpine上,pip将从源代码构建需要依赖包来install,如mysqlclient需要gcc和musl-dev,因此需要将apk del *-build推迟到安装Python模块之后
RUN apk del mysqlclient-build \
&& apk del system-build
构建镜像
docker build -t hw-website .
构建完之后查看一下docker images
,效果立杆见影
REPOSITORY TAG IMAGE ID CREATED SIZE
hw-website latest 14a*****6c5a 12 minutes ago 549MB
依赖包说明:
python:3.7-alpine
:alpine
是一个Linux
系统发行版,主打小巧、轻量、安全。我们程序运行需要Python
环境,因此使用这个小巧但包含完整 Python 环境的基础镜像来构建我们的应用镜像。mysqlclient
:我使用的是mysql
数据库。编译所需的库文件在pypi
上可以查到 mysqlclient 依赖库Pillow
:使用django
处理图片时,会使用到Pillow
这个Python
库。Pillow 依赖库
所以至于你需要的其他库的依赖,需要去搜索一下
小技巧
- 添加 alpine apk 源
参考 Alpine Linux package management 和 alpine-mirrors/mirrors.yaml
# 添加alpine apk源
RUN echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories;
RUN echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories;
RUN echo "https://mirrors.tuna.tsinghua.edu.cn/alpine/latest-stable/main/" >> /etc/apk/repositories;
RUN echo "https://mirrors.tuna.tsinghua.edu.cn/alpine/latest-stable/community/" >> /etc/apk/repositories;
RUN echo "http://dl-cdn.alpinelinux.org/alpine/latest-stable/community/" >> /etc/apk/repositories;
RUN echo "http://dl-2.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories;
RUN echo "http://dl-3.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories;
RUN echo "http://dl-4.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories;
RUN echo "http://dl-5.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
- 添加豆瓣
pip
源
# 构建参数,pip源
ARG pip_url=https://pypi.douban.com/simple
ARG pip_host=pypi.douban.com
# 更新 pip 到最新
RUN pip install pip -U -i ${pip_url}
# 将本地的文件拷贝到容器镜像
COPY requirements.txt /requirements.txt
# pip 安装依赖文件
RUN pip install -r requirements.txt -i ${pip_url} --trusted-host ${pip_host}
好了,问题来了
镜像我都构建完了,怎么用呢?
请看下一篇 基于 Docker 的 Django 容器化部署之二:docker-compose 部署 Django 项目