相信你也被你第一次使用docker打包的python的image惊讶到了吧,代码1MB镜像却可以有1个多G,构建也需要几分钟。

通过最佳实践可以让你的image从v1进化到v2。老司机可以直接到最后去看dockerfile

REPOSITORY  TAG      IMAGE ID         CREATED          SIZE
flask       v1       baefe66b1304     3 days ago       1.59GB
flask       v2       a8a98b14a0df     2 days ago       324MB

在本文中,您将学习:

  • 多阶段构建的工作原理以及Python如何使多阶构建。让你的镜像很小

  • Python合理编写dockerfile加快构建时间。让你的build很快

python 多阶构建

多阶构建原理

多阶构建原理简单的说就是现在一个镜像中编译代码,然后把编译好的最小代码复制到第二个镜像中。这样第二个镜像就不包含那些为了编译安装的工作环境,从而获得一个不包含编译环境较小的image

  • 在第一个映像中,安装编译器和其他构建工具,然后编译源代码。
  • 在第二个映像中,仅安装运行代码所需的软件包,然后复制由第一个映像创建的已编译工件。
# 第一个镜像:
FROM ubuntu:18.04 AS compile-image
RUN apt-get update
RUN apt-get install -y --no-install-recommends gcc build-essential

WORKDIR /root
COPY hello.c .
RUN gcc -o helloworld hello.c

# 这是第二个镜像也是最终我们的生成的镜像
FROM ubuntu:18.04 AS runtime-image

COPY --from=compile-image /root/helloworld .   <-注意这里,将在第一个镜像compile-image 中编译好的的代码copy到runtime-image里面
CMD ["./helloworld"]

如果我们docker build按照上述步骤进行操作,则最终图像是最后一个阶段,即runtime-image。
最后该映像只有88.9MB,基本上ubuntu:18.04与其生成的映像大小相同(并与之共享大部分层):我们有一个映像,该映像可以获取已编译的工件,而不必在其各层中包含编译器。

使用venv

在上面的示例中,我们复制了一个二进制文件,这使工作更轻松:只需复制这一件事。但是在python中,其中包含一些需要编译的代码(在C / C ++ / Rust中),以及许多Python依赖项。

一个简单的方法是使用virtualenv

FROM python:3.7-slim AS compile-image
RUN apt-get update
RUN apt-get install -y --no-install-recommends build-essential gcc

RUN python -m venv /opt/venv
# 使用我们建好的虚拟python环境:
ENV PATH="/opt/venv/bin:$PATH"

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY setup.py .
COPY myapp/ .
RUN pip install .

FROM python:3.7-slim AS build-image
COPY --from=compile-image /opt/venv /opt/venv

# 使用我们建好的虚拟python环境:
ENV PATH="/opt/venv/bin:$PATH"
CMD ['myapp']

快速构建

快速构建的关键是利用docker的缓存,缓存的原理看这里

python我们只需要记住先COPY requirements.txt,pip install 这样就可以利用docker的缓存层,加快构建

COPY requirements.txt .
RUN  pip install  -r requirements.txt
COPY . .

最佳实践dockerfile

一个的flask app为一个例子:

FROM python:3.6-stretch as compile_stage
####################定义环境变量 start####################
#定义工作目录
ENV WORK_PATH /usr/src/app
WORKDIR $WORK_PATH
#使用虚拟python环境
RUN python -m venv $WORK_PATH/venv
ENV PATH="$WORK_PATH/venv/bin:$PATH"
#可以使用pip的缓存
#requirements.txt不变的时候会直接使用缓存层
COPY requirements.txt .
#国内同学用一下清华源
RUN  pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple && \
     pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
#复制项目代码,记得在.dockerignore把项目不需要的文件忽略掉
COPY . $WORK_PATH

FROM python:3.6-alpine
#设置pytohn虚拟环境
ENV WORK_PATH /usr/src/app
ENV PATH="$WORK_PATH/venv/bin:$PATH"
WORKDIR $WORK_PATH

#从名为compile_stage的image复制构建结果到工作目录
COPY --from=compile_stage $WORK_PATH/. .
CMD ["gunicorn",  "run:app ", "-c","gunicorn.conf.py"]
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐