5

还在用Alpine作为你Docker的Python开发基础镜像?其实Ubuntu更好一点

 2 years ago
source link: https://v3u.cn/a_id_173
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

还在用Alpine作为你Docker的Python开发基础镜像?其实Ubuntu更好一点

首页 - Python /2020-09-03
还在用Alpine作为你Docker的Python开发基础镜像?其实Ubuntu更好一点

    一般情况下,当你想为你的Python开发环境选择一个基础镜像时,大多数人都会选择Alpine,为什么?因为它太小了,仅仅只有 5 MB 左右(对比 Ubuntu 系列镜像接近 100 MB),但事实的真相是,我们选择基础镜像并不是为了体验一下Python语法而已,在此基础上,我们需要调试和安装各种扩展,可能会安装很多三方依赖,甚至预设更多服务,在这种环境下,Alpine就并非是一个很好的选择了,本次我们就来分别在Alpine和Ubuntu上来体验一下安装和编译Python的区别。

    首先分别拉取Alpine和Ubuntu的镜像:

docker pull ubuntu:18.04
docker pull alpine

    拉取完毕后,可以看到,体积上确实差距明显:

REPOSITORY                  TAG                   IMAGE ID            CREATED             SIZE
ubuntu 18.04 6526a1858e5d 2 weeks ago 64.2MB
alpine latest a24bb4013296 3 months ago 5.57MB

    ubuntu占用64mb,而alpine仅仅5.57mb。

    但是先别着急,假设我们的python应用需要做一些科学计算,并且将数据以图形的方式展示出来,这时候就需要matplotlib和pandas这两个库的帮助了,先用ubuntu来安装这俩个库,编写Dockerfile.ubuntu

FROM python:3.7-slim
RUN pip install --no-cache-dir matplotlib pandas

    然后运行镜像脚本:

docker build -f Dockerfile.ubuntu -t 'ubuntu-mat' .

    可以看到,编译好的镜像从原先的60mb暴涨到了263mb。

liuyue:blog liuyue$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu-mat latest 401f0425ce63 About a minute ago 263MB

    使用起来没有什么问题。

    现在,我们来试试Alpine,看看速度和体积上有没有比Ubuntu更具优势

    编写Dockerfile.alpine:

FROM python:3.7-alpine
RUN pip install --no-cache-dir matplotlib pandas

    编译镜像脚本

docker build -f Dockerfile.alpine -t 'alpine-mat' .

    在编译过程中,我们会发现报错了:

liuyue:blog liuyue$ docker build -f Dockerfile.alpine -t 'alpine-mat' .
Sending build context to Docker daemon 112.1kB
Step 1/2 : FROM python:3.7-alpine
3.7-alpine: Pulling from library/python
df20fa9351a1: Pull complete
36b3adc4ff6f: Pull complete
4db9de03f499: Pull complete
cd38a04a61f4: Pull complete
6bbb0c43b470: Pull complete
Digest: sha256:d1375bf0b889822c603622dc137b24fb7064e6c1863de8cc4262b61901ce4390
Status: Downloaded newer image for python:3.7-alpine
---> 078114edb6be
Step 2/2 : RUN pip install --no-cache-dir matplotlib pandas
---> Running in 6d3c44420e5c
Collecting matplotlib
Downloading matplotlib-3.3.1.tar.gz (38.8 MB)
ERROR: Command errored out with exit status 1:
command: /usr/local/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-40p0g06u/matplotlib/setup.py'"'"'; __file__='"'"'/tmp/pip-install-40p0g06u/matplotlib/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-zk64hzam
cwd: /tmp/pip-install-40p0g06u/matplotlib/

    这是怎么搞的?如果你仔细看上面基于Ubuntu的构建,你会发现它下载三方库的安装包是matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64.whl,这是一个预编译的二进制安装包。而Alpine则只能下载源代码(matplotlib-3.1.2.tar.gz)的压缩包,这就是Alpine的致命问题:标准的Linux安装包在Alpine Linux上根本无法使用。

    大多数Linux发行版都使用GNU版本的标准C库(glibc),几乎所有基于C语言的脚本语言都需要这个库,包括Python。但Alpine Linux使用的是musl,那些二进制安装包是针对glibc编译的,因此Alpine禁用了Linux安装包支持。现在大多数Python包都在PyPI上包含了二进制安装包,大大加快了安装时间。但是如果你使用的是Alpine Linux,你需要编译你使用的每一个Python包中的所有C源码。

    这也就意味着你需要自己弄清楚每一个系统库的依赖性。事先编译好需要的依赖,重新改写Dockerfile.alpine:

FROM python:3.7-alpine
RUN apk --update add gcc build-base freetype-dev libpng-dev openblas-dev
RUN pip install --no-cache-dir matplotlib pandas

    再次编译:

docker build -f Dockerfile.alpine -t 'alpine-mat' .

    经过了漫长的编译安装,大约半个小时左右,因为我们都知道从源码编译安装要远远慢于通过安装包安装,此时查看编译好的镜像:

REPOSITORY                  TAG                   IMAGE ID            CREATED              SIZE
alpine-mat latest 601f0425ce63 About a minute ago 873MB

    可以看到体积已经变成873mb了,Alpine最引以为傲的体积小轻便等特性也已经荡然无存。

    虽然从理论上讲,Alpine使用的musl 内核与其他Linux发行版使用的glibc大多是兼容的,但在实际操作中,这种差异可能会造成各种问题。而当这些问题真的发生时,想解决它们就没那么简单了,比如说Alpine的线程默认堆栈容量较小,这会导致Python崩溃,同时也会影响python应用的运行速度。

    结语:在本地环境,如果你只是想“玩一玩”,那么基础镜像选择Alpine无可厚非,但是如果你想要将你的python应用部署到生产环境时,特别是部署分布式系统需要多次编译的场景下,选择老牌的Ubuntu显然更加的明智。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK