原文转载自「刘悦的技术博客」https://v3u.cn/a_id_173

一般情况下,当你想为你的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显然更加的明智。

原文转载自「刘悦的技术博客」 https://v3u.cn/a_id_173

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

  1. Docker教程:使用docker配置python开发环境

    http://blog.csdn.net/pipisorry/article/details/50808034 Docker的安装和配置 [Docker教程:docker的安装] [Docker教程: ...

  2. Docker制作私有的基础镜像

    debootstrap是debian/ubuntu下的一个工具,用来构建一套基本的系统(根文件系统).生成的目录符合Linux文件系统标准(FHS),即包含了/boot./etc./bin./usr等 ...

  3. docker学习系列-jdk基础镜像制作

    准备一台安装有docker服务的机器 1.编辑Dockerfile   vim Dockerfile FROM centos:latest ADD ./jdk-8u141-linux-x64.tar. ...

  4. 如何运用docker配合python开发

    在网络层,互联网提供所有应用程序都要使用的两种类型的服务,尽管目前理解这些服务的细节并不重要,但在所有TCP/IP概述中,都不能忽略他们: 无连接分组交付服务(Connectionless Packe ...

  5. 还在用背单词App?使用Python开发英语单词自测工具,助你逆袭单词王!

    学英语广告 最近也许是刚开学的原因,不管是公众号,还是刷抖音,导出都能看到关于学英语.背单词的广告. 不知道现在学生们背单词买的什么辅导材料.反正我们上学那会,<星火阅读>特别的火.记得当 ...

  6. linux 创建docker基础镜像

    通过Dockerfile创建镜像时,一般都是基于 Docker Hub 提供的官方镜像.以下分别介绍在ubuntu16和centos7 两个系统上创建个人私有基础镜像的方法.  一.ubuntu16创 ...

  7. 尝试自己建立以alpine 为基础的docker基础镜像和组件镜像

    安装ubuntu14.04 然后 #获取root权限 sudo su #安装docker apt-get install docker #准备基础镜像 docker pull alpine docke ...

  8. Docker从零构建php-nginx-alpine镜像

    虽然之前也曾用docker环境运行了一些项目,但对于镜像这块还不是很理解,且鉴于网上现成的镜像都包含太多用不到的库,所以决定从零开始构建一个自己的镜像. alpine linux为基础镜像 docke ...

  9. Docker 系列二(操作镜像).

    一.镜像管理 1.拉取镜像 docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] -- Docker 镜像仓库地址 :一般是 域名或者IP[:端口号 ...

随机推荐

  1. shellcode编写

    shellcode编写 shellcode是一段用于利用软件漏洞而执行的代码,通常使用机器语言编写,其目的往往是让攻击者获得目标机器的命令行shell而得名,其他有类似功能的代码也可以称为shellc ...

  2. java 5种IO模型

    每日一句 人的痛苦会把自己折磨到多深呢? 每日一句 You cannot swim for new horizons until you have courage to lose sight of t ...

  3. CenterNet训练时黑白图片不能画框的问题

    解决CenterNet在detect.py中不能画框的问题 在第centernet.py的第198行的中加上这一行 image = image.convert('RGB')

  4. Python报错 ImportError: DLL load failed while importing win32api: %1 不是有效的 Win32 应用程序 的解决方法

    今天在用jupyter notebook 的时候发生了kernel error,点开之后提示了以下报错信息 Traceback (most recent call last): File " ...

  5. JAVA - 线程同步和线程调度的相关方法

    JAVA - 线程同步和线程调度的相关方法 wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁:wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等 ...

  6. ubuntu下连microsoft sql server解决方案

    shell for MSSQL: https://github.com/dbcli/mssql-cli mssql-cli -S 127.0.0.1,1433 -d testDB -U myuser ...

  7. 数据库系列:MySQL索引优化总结(综合版)

    1 背景 作为一个常年在一线带组的Owner以及老面试官,我们面试的目标基本都是一线的开发人员.从服务端这个技术栈出发,问题的范围主要还是围绕开发语言(Java.Go)等核心知识点.数据库技术.缓存技 ...

  8. 疫情在校学生之——用python对某校园热水服务app进行测试,实现自动免费用水(仅供参考)

    写在前面的过场话: 本文只是对某校园热水服务app做个测试,其实本人并没有做大坏事,并未传播相关技术,文章以下内容的敏感部分会打码,并且相关厂商已经正在进行漏洞修复,大家看看就好.文章后会提供&quo ...

  9. 人人都能学会的 Python 多线程指南~

    大家好鸭!有没有想我~(https://jq.qq.com/?_wv=1027&k=rX9CWKg4) 在 Python 中,多线程最常见的一个场景就是爬虫,例如这样一个需求,有多个结构一样的 ...

  10. Linux系列之文本操作命令

    前言 Linux 有八个常用的文本操作命令:cat.head.tail.nl.grep.sed.more.less.本文介绍它们的区别和简单用法. cat命令 显示文本的最基本命令. cat file ...