如何为 Python 应用选择最好的 Docker 镜像?
关注公众号并添加到“星标⭐”,防止错过消息
后台回复【资料包】获取学习资料
前言
对于 Docker 基础镜像的要求
稳定性:要求今天的构建与以后的构建有相同的基本库、目录结构和基础结构。否则我们的 Python 应用程序将将有可能存在不确定的隐患。
丰富的库资源:对于某些应用,可能需要安装一些不太流行的库(例如 lxml 等)。这就需要我们选择的基本镜像提供丰富的库资源。
最新的 Python 版本:虽然可以通过自行安装 Python 来解决,但是拥有最新的 Python 的版本无疑可以节省我们的时间、精力。
小型的 Docker 镜像:在所有条件都相同的情况下,拥有尺寸较小的 Docker 镜像无疑更胜一筹。无论是镜像的构建还是占用存储空间的开销,更小的尺寸一定更有优势。
考虑到应用部署在产环境的需要,我们所选择的 Docker 镜像还应当具备长期支持(Long-term support, LTS) 的承诺。
Linux 镜像版本的选择
围绕着上述的需求,我们很容易就会找到一批候选的版本。乍看起来,这些基础镜像应该能够满足我们的需要。接下来我们需要仔细甄别其具体的差异,以找出最适合我们的版本,尤其是适合我们的 Python 应用。
选项一:传统的 Linux 分发版本 – Ubuntu TLS、CentOS 以及 Debian
这三个 Linux 分发版本历史久远(Debian 早在 1993 年就已出现),名气很大,在 Linux 服务器市场上拥有广泛的用户。
Ubuntu 18.04(Docker 镜像的名字 ubuntu:18.04)发布于 2018 年 4 月,由于这是 Canonical 公司的长期支持版本(LTS),意味着该版本的用户在 2023 年之前都将获得安全更新。 CentOS 8( Docker 镜像的名字 centos:8 )于 2019 年发布,将在 2024 年前进行全面更新,并在 2029 年前提供维护更新。 Debian 10(Docker 镜像的名字 debian:buster)发布于 2019 年 7 月,承诺支持到 2024 年。
https://amazonaws-china.com/cn/blogs/china/python-3-8-is-here-are-you-ready/
选项二:Docker 官方的 Python 镜像
Alpine Linux, 关于这个版本,后面会有专门的讨论 Debian Buster, 这是基于 Debian 的一个分支版本,是基于 Debian 的标准镜像的 Layer 来构建的。特点是基础库很完整,缺点是尺寸较大,磁盘的利用率较低。 Debian Buster slim,这个版本是针对 Debian Buster 的“瘦身”后的版本。尺寸小,磁盘利用率高是其优点。但是,它缺少通用的包,可能会导致对部分的应用支持不好。
选项三:云计算上的 Linux 镜像 – Amazon Linux 2
选项四:Alpine 镜像
取而代之的是一个迷你版的 C 标准库 musl
此外,我们常用的 Linux 工具(例如 grep、ls、cp 等等)则采用了 BusyBox 以求进一步压缩空间。这种努力的结果是非常有成效的,alpine:latest 镜像的尺寸只有区区的5.59MB,而与之相对的 ubuntu:18.04 的镜像的尺寸却高达 64.2MB。简单计算下来,Alpine 的磁盘空间的需求只是 Ubuntu 18.04 的 8.7% !
对比 – Docker 基础镜像的尺寸
测试日期:2020 年 2 月 28 日
Linux 分发版本 | 镜像名称 | 拉取命令 | 尺寸 |
---|---|---|---|
Ubuntu | ubuntu:18.04 | docker pull ubuntu:18.04 | 64.2MB |
Alphine | alpine:latest | docker pull alpine:latest | 5.59MB |
Debian | debian:buster | docker pull amd64/debian:buster | 114MB |
CentOS | centos:8 | docker pull centos:8 | 237MB |
Amazon Linux 2 | amazonlinux:latest | docker pull amazonlinux:latest | 163MB |
Debian | python:3.7 | docker pull python:3.7 | 919MB |
Alphine | python:3.7-slim | docker pull python:3.7-slim | 179MB |
如果从这个排名来看 centos 8 无疑表现的差强人意,故被淘汰。从数字来看似乎 alpine 是最好的选择。且慢,我们再来进行下一项测试- 构建时间。
对比 – Docker 镜像的构建时间
在大多数的时间里,我们所使用的 Docker 镜像都需要从基础镜像开始构建。例如下面的这个 Dockerfile 就用来构建一个 Flask 的应用
# Dockerfile-flask
# Simply inherit the Python 3 image.
FROM python:3
# Set an environment variable
ENV APP /app
# Create the directory
RUN mkdir $APP
WORKDIR $APP
# Expose the port uWSGI will listen on
EXPOSE 5000
# Copy the requirements file in order to install
# Python dependencies
COPY requirements.txt .
# Install Python dependencies
RUN pip install -r requirements.txt
# We copy the rest of the codebase into the image
COPY . .
# Finally, we run uWSGI with the ini file
这种模式带来的问题就是我们不得不考虑构建带来的额外的开销。尤其在一个复杂的项目中,我们需要构建的则不仅仅上面这样简单的场景,复杂的应用往往需要一个较长的构建时间。如果构建时间的开销比较大或者比较复杂,则必然增加了额外的管理、部署以及监控的成本。我的这个测试场景比较简单,只是安装 Python3,以及比较常见的 python 包 numpy、matplotlib 和 pandas。看看每一种 Docker 基础镜像的构建所需的时间是多少。
1、ubuntu:18 , 构建时间 1 分 31.044 秒
FROM ubuntu:18.04
RUN apt-get update -y && \
apt-get install -y python3.7 python3-pip python3.7-dev
RUN pip3 install --upgrade pip
RUN pip3 install --no-cache-dir numpy matplotlib pandas
2、amazonlinux:2 , 构建时间 30.898 秒
FROM amazonlinux:latest
RUN yum update -y && \
yum install -y python3 python3-devel
RUN pip3 install --no-cache-dir numpy matplotlib pandas
3、debian:latest , 构建时间 52.237 秒
FROM debian:buster
RUN apt-get update -y && \
apt-get install -y python3 python3-pip python3-dev
RUN pip3 install --no-cache-dir numpy matplotlib pandas
FROM python:3.7
RUN apt-get update -y && \
apt-get install -y python3-pip
RUN pip3 install pip --upgrade
RUN pip3 install --no-cache-dir numpy matplotlib pandas
5、python:3.7-slim, 构建时间 53.475 秒
FROM python:3.7
RUN apt-get update -y && \
apt-get install -y python3-pip
RUN pip3 install pip --upgrade
RUN pip3 install --no-cache-dir numpy matplotlib pandas
6、alpine:latest ,构建时间 24 分 43.122 秒
FROM alpine:latest
RUN apk update && \
apk add --no-cache --update \
gcc make automake gcc g++ python3 python3-dev cython freetype-dev
RUN pip3 install --upgrade pip
RUN pip3 install --no-cache-dir numpy matplotlib pandas
alpine:latest > ubuntu:18.04 > > python:3.7-slim > debian:buster > python:last > amazonlinux:latest
确实没有看错,被我们寄予厚望的 Alpine 镜像的构建时间居然是24 分钟以上。与构建速度最快的 Amazon Linux 2 比较起来足足慢了有24 倍的时间!!
如果细心一些,你会发现这个 Dockerfile 与上面的几个不同,多出了 gcc、make、automake、g++这些与编译工具和几个库。事实上,在我第一次构建的时候遇到了这样的错误信息 :
这真是未曾预料的问题啊!深究之下终于发现在 Appine 使用 pip 安装 matplotlib 以及 pandas 的时候,并不是从 PyPi 的仓库中下载 whl 包,而是需要下载源代码然后编译再进行安装的。标准的预编译的 Python 包居然无法直接安装,这究竟是为什么?
我相信熟悉 Alpine 的用户会与我争论,Alpine 的 Edge 版本会解决这个问题。不幸的是,Edge 版本目前还不是稳定版本。如果用于生产环境,我们还是不要自寻烦恼为好。
结论
这个测试也许不能覆盖我们需要的各个角度,但至少给我们提供了一个选择的参考。而我在这个测试之后也得到了自己需要的结果,
Alpine 显然不适合作为 Python 应用的基础镜像。尽管它提供了惊人存储的空间上效率,但它对于 Python 包支持的不足的缺陷是难以弥补的。也许 Alpine 更适合于一些对于镜像尺寸敏感的场合,还可以考虑将它用于你的 Go 应用。 在 AWS 云计算的环境中,Amazon Linux 2 的性能表现是有目共睹的。如果你希望得到一个稳定、安全以及高性能的 Python 基础镜像,那就不要忘记 Amazon Linux 2 这个选择。 Ubuntu 18.04 以及 Debian 10 表现的中规中矩,完全在我的意料之中。考虑到 Debian 10(Buster)较 Ubuntu 更新一些。这应该是一个好选择。不过随着 Ubuntu 20.04 LTS 即将发布,在我的候选清单上也许要多出一个。 至于 Docker 官方的 Python 镜像,并没有看出明显的优点。考虑到安全性与维护性的问题,我不认为这是个好的选择。 关于 Docker 基础镜像的选择,还需要考虑的一点就是 Linux 一致性的问题。杂乱的、多样化的 Linux 版本会在大规模应用的时候带来不可预估的风险,不可掉以轻心。
作者:费良宏
译自:https://aws.amazon.com/cn/blogs/china/choose-the-best-docker-image-for-your-python-application/
译者:#公众号:进击云原生
推荐阅读
K8S 1.25 中的重大更改和删除12 张图讲解 Spark 在 K8S 中实战操作
ES、Kibana on K8S 详解与实战操作
深入理解 K8S Pod 调试与实践技巧
2.8W 字 17 张图,详解 Flink 在 K8S 中的部署与实战操作
用 Grafana Mimir 可视化云原生监控报警
8 张图高可用 Hadoop 在 K8S 中部署完全指南
7 张图入门 Hadoop 在 K8S 环境中部署
8 张图详解 MySQL 在 K8S 环境中部署与监控
K8S 1.25 两特性减少应用滚动上线停机时间Adobe 用 Argo 高级部署模式的最佳实践Docker 镜像构建保姆级入门实战指南12 图入门高性能分布式对象存储 MinIO17 张图实战 + 理清 K8S 网络排错思路,硬核!16 张图硬核讲解 Kubernetes 网络模型