前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >docker 仓库里面python好多tag都代表什么意思?我们该如何选择

docker 仓库里面python好多tag都代表什么意思?我们该如何选择

原创
作者头像
张琳兮
修改2020-05-26 09:42:02
2.7K1
修改2020-05-26 09:42:02
举报
文章被收录于专栏:首富手记首富手记首富手记

docker 仓库里面python好多tag都代表什么意思?我们该如何选择

作者:张首富
时间:2020-05-25
w x:y18163201

起因

今天让我同事帮忙构建一个基于python代码的docker包,然后他问我使用那个底层镜像,我说你直接去docker hub上找一个,他打开之后问我这么多我该使用那个,他们之间有什么不一样呢?

比较不同tag之间的区别

我们在docker hub上能看到很多python tag的标签,我们这边以3.6版本的来做介绍

3.6.10-buster, 3.6-buster
3.6.10-slim-buster, 3.6-slim-buster, 3.6.10-slim, 3.6-slim
3.6.10-stretch, 3.6-stretch
3.6.10-slim-stretch, 3.6-slim-stretch
3.6.10-alpine3.11, 3.6-alpine3.11, 3.6.10-alpine, 3.6-alpine
3.6.10-alpine3.10, 3.6-alpine3.10

我们查看他们构建的dockerfile其实就能看出来大概的区别

docker tag

基础版本

3.6.10-apline3.10

apline:3.10

3.6.10-apline3.11

apline:3.11

3.6.10-slim-stretch

debian:stretch-slim

3.6.10-slim-buster

debian:buster-slim

3.6.10-buster

buildpack-deps:buster

3.6.10-stretch

buildpack-deps:stretch

其实我们从上面这个表格就可以看出来,他们之间的区别就是因为底层镜像不一样而造成的差异。

debian版本号

debian发行版本号

含义

buster

当前的稳定版

stretch

旧的稳定版,包含了Debian官方最近一次发行的软件包,优先推荐使用的版本

testing

测试版本,包含了哪些暂时未被收录进”稳定版“的软件包

ubstable

不稳定版,开发版本

buildpack-deps 基础镜像

该镜像包含了通常开发所必须的头文件和工具(比如源码管理工具)。但是这个镜像中添加了非必须的东西,有点违反docker最小构建的原理。

这里推荐使用debian为基础镜像

用Alpine 会让python Docker 的构建慢50倍

一般我们选择docker 镜像为基础镜像时,Apline Linux 就会被推荐,因为他小,如果我们在使用go,这将是一个很好的选择,因为go不依赖于任何环境。

但是如果我们打包的是python代码,那个Apline Linux会是你的构建:

  1. 让你的构建更慢
  2. 让你的镜像更大
  3. 浪费我们宝贵的时间
  4. 偶尔引入一些令人费解的运行时bug

详情请看这个:https://www.infoq.cn/article/VODLe9FsiBkQdlcxJZZj

Apline镜像探秘

Alpine 是众多Linux发行版中的一员,和Centos,Ubuntu,Debian 之类一样,只是一个发行版的名字,号称安全小巧,有自己的包管理工具apk

与Centos 和Ubuntu他们不同的是,Apline并没有像Red Hat 之类的大公司为其提供维护支持,软件包数量也比这些发行版少很多(如果只看开箱即用的默认软件仓库,Apline只有10000个软件包,而ubuntu,Debian的软件包数量均大于50000).

容器崛起之前,Apline 还是个无名之辈,可能是因为大家并不是很关心操作系统本身的大小,毕竟大家只关心业务数据和文档,程序,库文件和系统本身大小通常可以忽略不计。

容器技术席卷整个软件产业之后,大家都注意到了一个问题,那就是容器的镜像太大了,浪费磁盘空间,拉去镜像时间长,不够轻便。于是,人们开始寻求适用于容器的更小镜像。对于那些耳熟能详的发行版(例如 Ubuntu、Debian、Fedora)来说,只能通过删除某些工具(例如 ifconfignetstat)将镜像体积控制在 100M 以下。而对于 Alpine 而言,什么都不用删除,镜像大小也就只有 5M 而已。

Alpine 镜像的另一个优势是包管理工具的执行速度非常快,安装软件体验非常顺滑。诚然,在传统的虚拟机上不需要太关心软件包的安装速度,同一个包只需要装一次即可,无需不停重复安装。容器就不一样了,你可能会定期构建新镜像,也可能会在运行的容器中临时安装某些调试工具,如果软件包的安装速度很慢,会很快消磨掉我们的耐心。

为了更直观,我们来做个简单的对比测试,看看不同的发行版安装 tcpdump 需要多长时间,测试命令如下:

→ time docker run <image> <packagemanager> install tcpdump

测试结果如下:

Base image           Size      Time to install tcpdump
---------------------------------------------------------
alpine:3.11          5.6 MB      1-2s
archlinux:20200106   409 MB      7-9s
centos:8             237 MB      5-6s
debian:10            114 MB      5-7s
fedora:31            194 MB    35-60s
ubuntu:18.04          64 MB      6-8s

好吧,既然 Alpine 这么棒,为什么不用它作为所有镜像的基础镜像呢?别急,先一步一步来,为了趟平所有的坑,需要分两种情况来考虑:

  1. 使用 Alpine 作为第二构建阶段(run 阶段)的基础镜像
  2. 使用 ALpine 作为所有构建阶段(run 阶段和 build 阶段)的基础镜像

run 阶段使用 Alpine

带着激动的心情,将 Alpine 镜像加入了 Dockerfile:

FROM gcc AS mybuildstage
COPY hello.c .
RUN gcc -o hello hello.c

FROM alpine
COPY --from=mybuildstage hello .
CMD ["./hello"]

第一个坑来了,启动容器出现了错误:

standard_init_linux.go:211: exec user process caused "no such file or directory"

这个报错在上篇文章已经见识过了,上篇文章的场景是使用 scratch 镜像作为 C 语言程序的基础镜像,错误的原因是 scratch 镜像中缺少动态库文件。可是为什么使用 Alpine 镜像也有报错,难道它也缺少动态库文件?

也不完全是,Alpine 使用的也是动态库,毕竟它的设计目标之一就是占用更少的空间。但 Alpine 使用的标准库与大多数发行版不同,它使用的是 musl libc,这个库相比于 glibc 更小、更简单、更安全,但是与大家常用的标准库 glibc 并不兼容。

你可能又要问了:‘既然 musl libc 更小、更简单,还特么更安全,为啥其他发行版还在用 glibc?’

mmm。。。因为 glibc 有很多额外的扩展,并且很多程序都用到了这些扩展,而 musl libc 是不包含这些扩展的。详情可以参考 musl 的文档

也就是说,如果想让程序跑在 Alpine 镜像中,必须在编译时使用 musl libc 作为动态库。

所有阶段使用 Alpine

为了生成一个与 musl libc 链接的二进制文件,有两条路:

  • 某些官方镜像提供了 Alpine 版本,可以直接拿来用。
  • 还有些官方镜像没有提供 Alpine 版本,我们需要自己构建。

golang 镜像就属于第一种情况,golang:alpine 提供了基于 Alpine 构建的 Go 工具链。

构建 Go 程序可以使用下面的 Dockerfile

FROM golang:alpine
COPY hello.go .
RUN go build hello.go

FROM alpine
COPY --from=0 /go/hello .
CMD ["./hello"]

生成的镜像大小为 7.5M,对于一个只打印 ‘hello world’的程序来说确实有点大了,但我们可以换个角度:

  • 即使程序很复杂,生成的镜像也不会很大。
  • 包含了很多有用的调试工具。
  • 即使运行时缺少某些特殊的调试工具,也可以迅速安装。

Go 语言搞定了,C 语言呢?并没有 gcc:alpine 这样的镜像啊。只能以 Alpine 镜像作为基础镜像,自己安装 C 编译器了,Dockerfile 如下:

FROM alpine
RUN apk add build-base
COPY hello.c .
RUN gcc -o hello hello.c

FROM alpine
COPY --from=0 hello .
CMD ["./hello"]

必须安装 build-base,如果安装 gcc,就只有编译器,没有标准库。build-base 相当于 Ubuntu 的 build-essentials,引入了编译器、标准库和 make 之类的工具。

最后来对比一下不同构建方法得到的 ‘hello world’镜像大小:

  • 使用基础镜像 golang 构建:805MB
  • 多阶段构建,build 阶段使用基础镜像 golang,run 阶段使用基础镜像 ubuntu:66.2MB
  • 多阶段构建,build 阶段使用基础镜像 golang:alpine,run 阶段使用基础镜像 alpine:7.6MB
  • 多阶段构建,build 阶段使用基础镜像 golang,run 阶段使用基础镜像 scratch:2MB

最终镜像体积减少了 99.75%,相当惊人了。再来看一个更实际的例子,上一节提到的使用 net 的程序,最终的镜像大小对比:

  • 使用基础镜像 golang 构建:810MB
  • 多阶段构建,build 阶段使用基础镜像 golang,run 阶段使用基础镜像 ubuntu:71.2MB
  • 多阶段构建,build 阶段使用基础镜像 golang:alpine,run 阶段使用基础镜像 alpine:12.6MB
  • 多阶段构建,build 阶段使用基础镜像 golang,run 阶段使用基础镜像 busybox:glibc:12.2MB
  • 多阶段构建,build 阶段使用基础镜像 golang 并使用参数 CGO_ENABLED=0,run 阶段使用基础镜像 ubuntu:7MB

镜像体积仍然减少了 99%

啰里啰嗦了这么多,你大概知道要使用那个镜像去构建 docker 包了吧!

参考:

用 Alpine 会让 Python Docker 的构建慢 50 倍

Docker 镜像制作教程:针对不同语言的精简策略

python-images

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • docker 仓库里面python好多tag都代表什么意思?我们该如何选择
    • 起因
      • 比较不同tag之间的区别
        • debian版本号
        • buildpack-deps 基础镜像
      • 用Alpine 会让python Docker 的构建慢50倍
        • Apline镜像探秘
          • run 阶段使用 Alpine
          • 所有阶段使用 Alpine
      相关产品与服务
      容器镜像服务
      容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档