【Docker 那些事儿】容器为什么傲娇?全靠 Hub 撑腰
1. Docker Hub
🍑 docker search 命令
Docker Hub 上有许多镜像, 但并不都是 Docker 官方人员制作的, 一些镜像是由 Docker 用户上传并维护的。工作中可以通过
docker search
命令从镜像仓库中查找所需要的镜像。 示例代码如下:以上示例中,查找的是与 CentOS 有关的镜像,Docker Hub 中有关 CentOS 的镜像远不止这些,这里显示的只是其中一部分。 下面对镜像的每项信息进行讲解。
NDEX
镜像索引,这里代表镜像仓库。
NAME
镜像名称。
DESCRIPTION
关于镜像的描述,使用户可以有方向性地选择镜像。
STARS
镜像的星标数,反映 Docker 用户对镜像的收藏情况,值越高代表使用的用户越多。
OFFICIAL
有此标记的都是 Docker 官方维护的镜像,没有此标记的通常是用户上传的镜像。
AUTOMATED
用来区分是否为自动化构建的镜像,有此标记的为自动化构建的镜像,否则不是。
🍑 docker search 参数运用
给
docker search
命令添加不同的参数,就会得到不同的查询结果,下面对各参数进行解释。
--automated
表示只列出自动化构建的镜像,示例代码如下:
--no-trunc
表示显示完整的镜像描述,示例代码如下:
-s
表示列出星标数不小于指定值的镜像,需要在参数后添加指定值,示例代码如下:
🍑 镜像推送
用户向 Docker Hub 推送镜像需要有一个 Docker Hub 账号。在 Docker 客户端使用
docker login
命令登录 Docker Hub 账号,如图所示👇下面使用
docker push
命令向 Docker Hub 推送镜像,示例代码如下:这里第 6 行出现了报错,镜像没有推送成功,报错信息显示请求资源被拒绝。这是因为 DockerHub 上的镜像都有一个 tag 标签,用户上传镜像时需要给镜像添加 tag 标签。 下面使用 docker tag 命令给镜像添加 tag 标签,示例代码如下:
tag 标签添加完之后,再查看一遍镜像,确保准确无误,示例代码如下:
可以看到,先前的镜像并没有发生改变,Docker 只是在它的基础上又创建了一个新镜像。与先前的镜像相比,新镜像只是修改了名字,镜像大小不变。 有了新镜像就可以将其推送给 Docker Hub 了,示例代码如下:
镜像推送完成之后, 可以登录 Docker Hub 查看, 验证镜像是否推送成功, 如图所示👇
从上图可以看出,镜像已经推送成功,这个镜像在 Docker Hub 上可以供所有用户下载并使用。 尝试拉取先前推送的镜像,示例代码如下:
镜像拉取完成后,查看是否拉取成功,示例代码如下:
从以上示例中可以看出,已经成功拉取了先前推送的镜像,拉取的镜像与本地的镜像相比,ID 号和镜像大小都是相同的。这就体现出了 DockerHub 官方镜像库的方便之处,用户可以将镜像上传到云端,做到随用随取,也可以将自己优秀的镜像与广大开源爱好者共享。 Docker Hub 在给用户带来便利的同时,也暴露出了极大的安全问题。任何 Docker 用户都可以随时随地上传镜像到 Docker Hub,将其推送给其他 Docker 用户,任何用户都可以拉取使用这些镜像,但谁都无法辨别所下载的镜像是否包含恶意信息。 <font color=#FF0000 >2018 年发生了一起安全事故,一名 Docker 用户上传了 17 个带有恶意软件的镜像,攻击者利用这些恶意 Docker 镜像在受害者的计算机上安装基于 XMRig 的门罗币挖矿软件。其中一些镜像已经安装超过一百万次,还有一些则被使用了数十万次。Docker 官方网站维护人员调查确认后删除了这些恶意镜像,风波才得以平息。</font> 在使用 Docker 镜像时要先在测试环境中安装运行,最安全的方法是尽可能使用自制的 Docker 镜像或使用经过验证的镜像。
2. Docker 镜像优化
Docker 镜像采用的是层级结构,一个镜像最多拥有 127 层 UnionFS。每条 Dockerfile 命令都会创建一个镜像层,增加镜像大小。在生产环境中使用 Docker 容器时,要尽可能地精简 Docker 镜像,减少 UnionFS 的层数。 精简镜像不仅能缩短新镜像的构建时间,还能减少磁盘用量。由于精简后的镜像更小,用户在拉取镜像时能节省时间,部署服务的效率也能得到提升。精简镜像包含的文件更少,更加不容易被攻击,提高了镜像的安全性。
🍑 base 镜像优化
base 镜像优化就是在满足环境要求的前提下使用最小的 base 镜像。常用的 Linux base 镜像有 CentOS、Ubuntu、Alpine 等,其中一些比较小的 base 镜像适合作为精简镜像的基础镜像,如 Alpine、BusyBox 等。 下面分别拉取 Alpine 与 BusyBox 的镜像进行对比,示例代码如下:
Scratch 是一个空镜像,只能用于构建其他镜像,常用于执行一些包含了所有依赖的二进制文件。如果以 Scratch 为 base 镜像,意味着不以任何镜像为基础,下面的指令将作为镜像的第一层存在。 BusyBox 相对于 Scratch 多了一些常用的 Linux 命令,BusyBox 的官方镜像大小只有 1MB 多一点,非常适合构建小镜像。 Alpine 是一款高度精简又包含了基本工具的轻量级 Linux 发行版,官方 base 镜像只有 5MB 多一点,很适合当作 base 镜像使用。
🍑 Dockerfile 优化
用户在定义 Dockerfile 文件时,使用太多的 RUN 命令,会导致镜像非常靡肿,甚至超出可构建的最大层数。根据优化原则,应该将多条 RUN 命令合并为一条命令,精心设计每一个 RUN 命令,减小镜像体积,并且精心编排,最大化地利用缓存。 下面创建一个 Dockerfile 文件,示例代码如下:
接着, 使用这个 Dockerfile 构建一个新的镜像, 示例代码如下:
从以上示例中可以看到,整个镜像构建的过程是十分烦琐的。 查看新镜像的大小与 UnionFS 的层数,示例代码如下:
从以上示例中可以看到,新镜像
centos/vim-bulky
的大小是 509MB,而镜像的 UnionFS 层数是 8 层。 这样编写 Dockerfile 导致新镜像非常庞大,既增加了构建部署的时间,也很容易出错。 下面对 Dockerfile 进行优化,示例代码如下:在 Dockerfile 中使用 "&" 与 ''**" 将多条命令合成一条,"&&” 表示命令还没有结束,''**"表示换行。 下面通过优化过的 Dockerfile 构建新镜像,示例代码如下:
从以上示例可以看出,优化后的 Dockerfile 构建镜像的过程比优化前精简了一些。 查看并对比两个新镜像,示例代码如下:
从以上示例中可以看到,镜像
centos/vim-portable
只有 305MB,比镜像centos/vim-bulky
节省了 204MB 的资源,甚至比源镜像centos/vim
还小了 21MB。 接着,查看镜像centos/vim-portable
的 UnionFS 层数,示例代码如下:从以上示例中可以看到,镜像
centos/vim-portable
的 UnionFS 只有 6 层,而先前的镜像centos/vim-bulky
有 8 层 UnionFS。
🍑 清理无用的文件
在 RUN 命令中使用 yum、apt、apk 等工具时,可以借助这些工具自带的参数进行优化。如执行
apt-get install-y
时添加--no-install-recommends
选项,就可以不安装建议性的依赖包,这些依赖包都是不必要的。 组件的安装和清理要放置在同一条命令里面,因为 Dockerfile 的每条命令都会产生一个新的镜像层,在执行下一条命令时,上一条命令所产生的镜像层已经为只读层,不可修改。Ubuntu 或 Debian 系统使用rm -rf/var/lib/apt/lists/*
清理镜像中的缓存文件,CentOS 等系统使用yum clean all
命令清理。 Docker 社区中还有许多优化镜像的工具,如压缩镜像的工具 Docker-squash,用起来简单方便。
3. 本章小结
本章介绍了 Docker 镜像的构成,采用了层级结构,层层递进; 然后介绍了镜像的仓库,包括官方公有仓库 Docker Hub 和 私有仓库; 最后详细讲解了如何构建 Docker 镜像,并对 Dockerfile 文件进行了简单的优化。 相信大家通过本章的学习,已经掌握了镜像的原理以及操作方式。
版权声明: 本文为 InfoQ 作者【飞向星的客机】的原创文章。
原文链接:【http://xie.infoq.cn/article/bce51c06e149b8a97fc11f2aa】。文章转载请联系作者。
评论