您当前的位置:首页 > 电脑百科 > 程序开发 > 容器

如何为 Python 应用选择最好的 Docker 镜像?

时间:2022-10-24 14:14:53  来源:  作者:CDA数据分析师

来源丨网络

前言

在使用 Python/ target=_blank class=infotextkey>Python 的早些年,为了解决 Python 包的隔离与管理 virtualenvwrApper 就成为我的工具箱中重要的一员。后来,随着 Python 3 的普及,virtualenvwrapper 逐渐被 venv 所替换。毕竟 venv 是 Python 3 的标配,优点是显而易见的。而这几年,应用场景的的复杂性越来与高,无论是开发还是部署都需要设置复杂的环境。例如使用 redis 实现消息队列,用 Psycopg 完成对于 PostgreSQL 数据库的存取等等。随之而来 Docker 就变成了程序员必不可少的常备工具。为了掌握如何将我的 Python 应用与 Docker 结合起来,就要学习他人的经验分享。于是一次又一次地看到了下面这样的 Dockerfile 例子:

相比起来,我不熟悉 Alpine 这个 linux 发行版本。我很困惑这个版本难道比其它哪些老字号的 Linux 发行版更适合 Docker 的环境吗?至于我的 Python 应用,究竟选择哪一个 Docker 基础镜像更好呢?

对于 Docker 基础镜像的要求

为我的 Python 应用构建一个 Docker 镜像并不是要从零开始,而是从现有的 Linux 基础镜像开始构建。这些基础镜像除了提到过的 Alpine 以外 还有我更熟悉的 Ubuntu、centos 、Debian 等等。在决定选择哪一个之前,我们需要回答的一个问题就是:

  • 我们究竟对于这个 Docker 基础镜像有哪些要求?

  • 这些要求既要满足通常意义上我们对操作系统的要求,也要满足对于 Python 应用的特殊的需求。

归纳起来,我们的需求应当包括这几点:

  • 稳定性:要求今天的构建与以后的构建有相同的基本库、目录结构和基础结构。否则我们的 Python 应用程序将将有可能存在不确定的隐患。

  • 安全更新:需要基础镜像得到良好维护,以便及时获取基本操作系统的安全更新

  • 最新的依赖关系:除非我们的应用仅仅是一个简单的 Python 程序,否则就不得不依赖操作系统所提供 的库和应用程序(例如:GCC 编译器、OpenSSL 库等)。我们需要这些应用和库要足够新,否则就会有各种安全性的问题或者功能性的不足。

  • 丰富的库资源:对于某些应用,可能需要安装一些不太流行的库(例如 lxml 等)。这就需要我们选择的基本镜像提供丰富的库资源。

  • 最新的 Python 版本:虽然可以通过自行安装 Python 来解决,但是拥有最新的 Python 的版本无疑可以节省我们的时间、精力。

  • 小型的 Docker 镜像:在所有条件都相同的情况下,拥有尺寸较小的 Docker 镜像无疑更胜一筹。无论是镜像的构建还是占用存储空间的开销,更小的尺寸一定更有优势。

考虑到应用部署在产环境的需要,我们所选择的 Docker 镜像还应当具备长期支持(Long-term support, LTS) 的承诺。

长期支持 (英语: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 年。

需要注意的是这些镜像预安装的 Python 有可能不是最新的版本。例如 Ubuntu 18.04 预安装的是 Python 3.6.7,而 Python 3 的最新稳定版本已经升级为 Python 3.8.1。因此我们必须在构建 Docker 镜像的时候去完成 Python 的安装或者升级。在一些特定的 Linux 分发版本中,我们甚至需要自行通过编译 Python 源码的方式来获得最新版本的 Python。例如在 CentOS 8 中,就需要用这个办法来安装 Python3.8。至于具体的办法,可以参考在“Python 3.8 已经来了,你准备好了吗?”一文中的介绍。

https://amazonaws-china.com/cn/blogs/china/python-3-8-is-here-are-you-ready/

选项二:Docker 官方的 Python 镜像

这个 Docker 镜像由 Docker 官方提供。该版本的最大特点就是预装了 Python,并且提供多个不同 Python 版本的选项,例如 Python 3.7、Python 3.8、Python 3.9。需要注意的是,这个版本提供了多个不同的变体,如果搞不清楚这一点很容易在使用中遇到难以预料的问题。这些差异很大的变体包括了:

  • Alpine Linux, 关于这个版本,后面会有专门的讨论

  • Debian Buster, 这是基于 Debian 的一个分支版本,是基于 Debian 的标准镜像的 Layer 来构建的。特点是基础库很完整,缺点是尺寸较大,磁盘的利用率较低。

  • Debian Buster slim,这个版本是针对 Debian Buster 的“瘦身”后的版本。尺寸小,磁盘利用率高是其优点。但是,它缺少通用的包,可能会导致对部分的应用支持不好。

选项三:云计算上的 Linux 镜像 – Amazon Linux 2

今天当我们谈到 Docker 在生产环境中的部署的时候,不能缺少的一个话题就是云计算。相比较起来,云计算上 Linux 以及 Docker 的使用与部署与我们熟悉的传统方式有一些区别。例如安全性的要求、与云计算平台的集成以及管理工具等。于是云计算的平台 Linux 分发版本以及 Docker 镜像也就应需而生。AWS 就提供了 Amazon Linux 的两个版本:Amazon Linux 2 和 Amazon Linux。其中,Amazon Linux 2 是 Amazon Linux 的新一代的 Linux 服务器操作系统版本,这也是 AWS 官方推荐使用的版本。至于选择 Amazon Linux 2 的的理由,简单来说这是一个由 Amazon 提供长期支持的(LTS)、进行了针对性性能优化的、强调安全的、免费的 Linux 分发版本以及 Docker 的镜像。

选项四:Alpine 镜像

很难想象,Alpine 这个 Linux 发行版已经有了 14 年的历史。但广为大家所熟知还是要拜 Docker 的流行所赐。最初,Alpine Linux 是 LEAF 项目(Linux Embedded Appliance Framework Project)的一个分支。LEAF 项目的设计的目标是开发出一个可以放在单个软盘上的 Linux 发行版,而后继的 Alpine 在此基础之上附加了一些更常用的软件包例如 Squid、Samba 等等。因此,Alpine 的典型特征就是“ 尺寸小”!当然为达成这个目标就要做出妥协。为减少尺寸就不得不放弃我们熟悉的 Linux 环境中最常见的 GNU C Library(glibc)

https://en.wikipedia.org/wiki/GNU_C_Library

取而代之的是一个迷你版的 C 标准库 musl

http://musl.libc.org/

此外,我们常用的 Linux 工具(例如 grep、ls、cp 等等)则采用了 BusyBox 以求进一步压缩空间。这种努力的结果是非常有成效的,alpine:latest 镜像的尺寸只有区区的 5.59MB,而与之相对的 ubuntu:18.04 的镜像的尺寸却高达 64.2MB。简单计算下来,Alpine 的磁盘空间的需求只是 Ubuntu 18.04 的 8.7% !

对比 – Docker 基础镜像的尺寸

想象一下,在真实的生产环境中我们部署的 Docker 实例的数量可能成百、上千。考虑到数量的因素,Docker 镜像的尺寸就应当是我们考量的一个重要依据。此外启动一个 Docker 实例我们往往需要在尽可能短的时间内完成,Docker 镜像的尺寸无疑也是一个关键因素。那么,我们就将上面列举的 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

好了,在这一项的测试中名次如下 :

python:3.7 > centos:8 > python:3.7-slim > amazonlinux:latest > debian:buster > ubuntu:18.04 > alpine:latest

如果从这个排名来看 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 .7python3-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

4、 python:latest, 构建时间 35.752 秒

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 使用的 musl 库上。原来几乎全部 Linux 发行版都使用 GNU 版本的 C 标准库(glibc)。但是 Alpine Linux 为了减小存储空间而使用了 musl 库。而我们通过 pip 安装的这些二进制 Python 包是基于 glibc 编译而成的。因此 Alpine 无法安装这些 python 库,只能通过源码编译的方式来进行安装。这也就是为什么 Alpine 的 Docker file 会与其它的不同,以及花费如此之多的时间进行构建的秘密。

我相信熟悉 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/

(版权归原作者所有,侵删)



Tags:Docker 镜像?   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
如何为 Python 应用选择最好的 Docker 镜像?
来源丨网络前言在使用 Python 的早些年,为了解决 Python 包的隔离与管理 virtualenvwrapper 就成为我的工具箱中重要的一员。后来,随着 Python 3 的普及,virtualenvwrapper 逐...【详细内容】
2022-10-24  Search: Docker 镜像?  点击:(296)  评论:(0)  加入收藏
▌简易百科推荐
Docker 和传统虚拟机有什么区别?
我有一个程序员朋友,他每年情人节都要送女朋友一台服务器。他说:“谁不想在过节当天收到一台 4核8g 的服务器呢?”“万一对方不要,我还能留着自己用。” 给他一次过节的机会,他能...【详细内容】
2024-03-26  小白debug  微信公众号  Tags:Docker   点击:(12)  评论:(0)  加入收藏
掌握Docker网络驱动程序:优化容器通信
Docker为在容器内包装、交付和运行应用程序提供了一个强大的平台,从而彻底改变了容器化。网络是容器化的重要组成部分,Docker提供了各种网络驱动程序来支持容器之间的通信以...【详细内容】
2024-03-22    51CTO  Tags:Docker   点击:(11)  评论:(0)  加入收藏
Containerd容器管理
Nginx 指定容器名称 使用 ctr container create 命令创建容器后,容器并没有处于运行状态,其只是一个静态的容器。容器基本操作容器基本操作主要是 ctr image 命令,查看命令帮...【详细内容】
2024-03-20  云原生运维圈  微信公众号  Tags:容器   点击:(13)  评论:(0)  加入收藏
如何基于Docker镜像逆向生成Dockerfile
引言你是否曾经遇到过一个想要使用的 Docker 镜像,但却无法修改以适应你的特定需求?或者你可能发现了一个喜欢的 Docker 镜像,但想要了解它是如何构建的?在这两种情况下,将 Docke...【详细内容】
2024-03-07  云原生运维圈  微信公众号  Tags:Docker   点击:(23)  评论:(0)  加入收藏
Kubernetes是什么?主要特点是什么?
Kubernetes是什么?Kubernetes,也称为K8s,是一个开源的容器编排系统,由Google首次开发和维护。它允许容器化的应用程序在集群中自动部署、扩展和管理。Kubernetes提供了一种容器...【详细内容】
2024-02-01    简易百科  Tags:Kubernetes   点击:(162)  评论:(0)  加入收藏
我们一起聊聊容器资源自愈
在企业实际在使用容器这类资源的时候,除了技术本身,要考虑的其他问题也会很多。企业管理的容器有千千万万,出于效率考虑,对于有特殊需求的容器如何进行批量创建和管理呢,这就需要...【详细内容】
2024-01-30  匠心独运维妙维效  微信公众号  Tags:容器   点击:(47)  评论:(0)  加入收藏
Docker与Docker Compose入门:释放你应用部署的威力
今天给大家介绍一项强大而有趣的技能,那就是使用 Docker 和 Docker Compose 来释放你的应用部署的威力!无论你是一名开发人员还是系统管理员,掌握这个技能都将为你的工作带来巨...【详细内容】
2024-01-17  waynblog  微信公众号  Tags:Docker   点击:(66)  评论:(0)  加入收藏
Docker镜像与容器的交互及在容器内部执行代码的原理与实践
Docker作为一种流行的容器技术,已经成为现代应用程序开发和部署的重要工具。在Docker中,镜像是构建和运行容器的基础,而容器则是基于镜像创建的可执行实例。Docker镜像与容器的...【详细内容】
2024-01-10  编程技术汇  今日头条  Tags:Docker   点击:(79)  评论:(0)  加入收藏
如何在 Ubuntu 上安装 Docker
使用 Docker 意味着开启一个新的计算领域,但如果你刚刚开始使用 Docker,安装可能看起来是一项艰巨的任务。在 Ubuntu 上安装 Docker 有两种推荐的方法: 从 Ubuntu 的仓库安装 D...【详细内容】
2024-01-04    Linux中国  Tags:Docker   点击:(124)  评论:(0)  加入收藏
从Kubernetes的探针到DevOps
今天在群里又看有人问如何设置 Kubernetes 的探针,感觉要补充的话太多了,结合我们在一些 DevOps 项目中痛苦的体验,今天一劳永逸的全部说完,此外,也为大家展现一下为什么 DevOps...【详细内容】
2023-12-27  云云众生s  微信公众号  Tags:Kubernetes   点击:(117)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条