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

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

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

相关文章
|
4天前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
73 44
|
5天前
|
数据可视化 开发者 Python
Python GUI开发:Tkinter与PyQt的实战应用与对比分析
【10月更文挑战第26天】本文介绍了Python中两种常用的GUI工具包——Tkinter和PyQt。Tkinter内置于Python标准库,适合初学者快速上手,提供基本的GUI组件和方法。PyQt基于Qt库,功能强大且灵活,适用于创建复杂的GUI应用程序。通过实战示例和对比分析,帮助开发者选择合适的工具包以满足项目需求。
31 7
|
7天前
|
算法 测试技术 开发者
性能优化与代码审查:提升Python开发效率
探讨了Python开发中性能优化和代码审查的重要性,介绍了选择合适数据结构、使用生成器、避免全局变量等性能优化技巧,以及遵守编码规范、使用静态代码分析工具、编写单元测试等代码审查方法,旨在帮助开发者提升开发效率和代码质量。
26 8
|
3天前
|
算法 测试技术 开发者
性能优化与代码审查:提升Python开发效率
性能优化与代码审查:提升Python开发效率
8 1
|
5天前
|
安全 数据库 开发者
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第26天】本文详细介绍了如何在Django框架下进行全栈开发,包括环境安装与配置、创建项目和应用、定义模型类、运行数据库迁移、创建视图和URL映射、编写模板以及启动开发服务器等步骤,并通过示例代码展示了具体实现过程。
22 2
|
6天前
|
算法 测试技术 开发者
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗;代码审查通过检查源代码发现潜在问题,提高代码质量和团队协作效率。本文介绍了一些实用的技巧和工具,帮助开发者提升开发效率。
10 3
|
8天前
|
算法 测试技术 开发者
性能优化与代码审查:提升Python开发效率
性能优化与代码审查:提升Python开发效率
13 1
|
Linux Docker 容器
Docker 从零开始制作基础镜像[centos]
http://www.oschina.net/news/62897/docker-hub-contains-high-risk-vulnerabilities 这里有个统计,docker官方和个人发布的镜像由于版本等各种原因,漏洞较多,那我们如何自己从头开始做个定制的镜像呢?   对,找官方文档 http://docs.
1880 0
|
16天前
|
存储 Docker 容器
docker中挂载数据卷到容器
【10月更文挑战第12天】
43 5
|
2天前
|
JavaScript 持续交付 Docker
解锁新技能:Docker容器化部署在微服务架构中的应用
【10月更文挑战第29天】在数字化转型中,微服务架构因灵活性和可扩展性成为企业首选。Docker容器化技术为微服务的部署和管理带来革命性变化。本文探讨Docker在微服务架构中的应用,包括隔离性、可移植性、扩展性、版本控制等方面,并提供代码示例。
18 1