HONGWEI's Blog

基于 Docker 的 Django 容器化部署之一:定制属于自己的 docker 镜像

Django 157

本文章为原创内容,只发布于 CSDN 博客我的私人博客,这里是为了让大家预览 Django-Blog 项目的时候好跳转,转载请注明,谢谢


基于 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 或者其他用户需要的程序。

  • 容器,是由镜像实例化而来,容器是基于镜像创建的,即容器中的进程依赖于镜像中的文件,类似虚拟机,里面可以运行特定的应用,并且容器与容器是相互隔离的。这有点像面向对象的概念:镜像就是类,容器是类实例化之后的对象。

  • 仓库,与 GitGithub 类似,Docker 使用的默认仓库是由官方维护的 Docker hub 公共仓库,此仓库是用来包含镜像的位置,同时其还提供了一个注册服务器(register)来保存多个仓库,每个仓库又可以包含多个具备不同 tag 的镜像,而仓库支持的操作如上传、拉取等动作类似于 Git

docker-compose

Docker Composedocker 提供的一个命令行工具,用来定义和运行由多个容器组成的应用。使用 compose,我们可以通过 YAML 文件声明式的定义应用程序的各个服务,并由单个命令完成应用的创建和启动。简单来说,就是用来编排多个容器,将启动容器的命令统一写到 docker-compose.yml 文件中,一次启动全部启动。

安装 docker 及 docker-compose

基于 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"="[email protected]"

# 设置 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"="[email protected]"

# 构建参数,工作目录
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-alpinealpine 是一个 Linux 系统发行版,主打小巧、轻量、安全。我们程序运行需要 Python 环境,因此使用这个小巧但包含完整 Python 环境的基础镜像来构建我们的应用镜像。 - mysqlclient:我使用的是mysql数据库。编译所需的库文件在pypi上可以查到 mysqlclient依赖库 - Pillow:使用 django 处理图片时,会使用到 Pillow 这个 Python 库。Pillow依赖库

所以至于你需要的其他库的依赖,需要去搜索一下

小技巧

  • 添加alpine apk源

参考 Alpine Linux package managementalpine-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 项目


本文链接: https://blog.zhwei.cn/article/ji-yu-docker-de-django-rong-qi-hua
版权声明: 本博客所有文章除特别声明外,均遵循 CC 4.0 BY-NC-SA 版权协议。转载请附上原文链接!