@ShuyRoy
This commit is contained in:
Xingyu Wang 2021-05-12 11:23:12 +08:00
parent f177c60b91
commit bc37b1db32

View File

@ -3,23 +3,20 @@
[#]: author: (Daniel Schier https://fedoramagazine.org/author/danielwtd/)
[#]: collector: (lujun9972)
[#]: translator: (ShuyRoy)
[#]: reviewer: ( )
[#]: reviewer: (wxy)
[#]: publisher: ( )
[#]: url: ( )
构建更小的容器
如何构建更小的容器
======
![build smaller containers][1]
![](https://img.linux.net.cn/data/attachment/album/202105/12/112108han4e111a6v16act.jpg)
水獭图片节选自[Dele Oluwayomi][2] 发表在 [Unsplash][3]上的照片
使用容器工作是很多用户和开发者的日常任务。容器开发者经常需要频繁地构建容器镜像。如果你开发容器你有想过减小镜像的大小吗比较小的镜像有一些好处。在下载的时候所需要的带宽更少而且在云环境中运行的时候也可以节省开销。而且在Fedora [CoreOS][4]、[IoT][5]以及[Silverblue][6]上使用较小的容器镜像提升了整体系统性能,因为这些操作系统严重依赖于容器工作流。这篇文章将会提供一些减小容器镜像大小的技巧。
使用容器工作是很多用户和开发者的日常任务。容器开发者经常需要频繁地(重新)构建容器镜像。如果你开发容器,你有想过减小镜像的大小吗?较小的镜像有一些好处。在下载的时候所需要的带宽更少,而且在云环境中运行的时候也可以节省开销。而且在 Fedora [CoreOS][4]、[IoT][5] 以及[Silverblue][6] 上使用较小的容器镜像可以提升整体系统性能,因为这些操作系统严重依赖于容器工作流。这篇文章将会提供一些减小容器镜像大小的技巧。
### 工具
以下例子所用到的主机操作系统是Fedora Linux33。例子使用 [Podman][7] 3.1.0 和[Buildah][8] 1.2.0。在大多数Fedora Linux变体中Podman和Buildah都被预装好了。如果你没有安装Podman和Buildah可以用下边的命令安装
以下例子所用到的主机操作系统是 Fedora Linux 33。例子使用 [Podman][7] 3.1.0 和[Buildah][8] 1.2.0。Podman 和 Buildah 已经预装在大多数 Fedora Linux 变种中。如果你没有安装 Podman 和 Buildah可以用下边的命令安装
```
$ sudo dnf install -y podman buildah
@ -27,20 +24,18 @@ $ sudo dnf install -y podman buildah
### 任务
从一个基础的例子开始。构建一个满足以下需求的web容器。
从一个基础的例子开始。构建一个满足以下需求的 web 容器:
* 容器必须基于Fedora Linux
* 使用Apache httpd web 服务器
* 容器必须基于 Fedora Linux
* 使用 Apache httpd web 服务器
* 包含一个定制的网站
* 容器应该比较小
下边的步骤都是在比较复杂的镜像上进行的。
下边的步骤也适用于比较复杂的镜像。
### 设置
首先,创建一个工程目录。这个目录将会包含你的网站和容器文件
首先,创建一个工程目录。这个目录将会包含你的网站和容器文件
```
$ mkdir smallerContainer
@ -49,7 +44,7 @@ $ mkdir files
$ touch files/index.html
```
制作一个简单的登录页面。对于这个演示,你可以将下面的HTML复制到 _index.html_ 文件中。
制作一个简单的登录页面。对于这个演示,你可以将下面的 HTML 复制到 `index.html` 文件中。
```
<!doctype html>
@ -100,20 +95,20 @@ $ touch files/index.html
</html>
```
此时你可以选择在浏览器中测试上面的 _index.html_ 文件。
此时你可以选择在浏览器中测试上面的 `index.html` 文件:
```
$ firefox files/index.html
```
最后,创建一个容器文件。这个文件可以命名为 _Dockerfile_ 或者 _Containerfile_
最后,创建一个容器文件。这个文件可以命名为 `Dockerfile` 或者 `Containerfile`
```
$ touch Containerfile
```
现在你应该有了一个工程目录,并且该目录中的文件系统布局如下。
现在你应该有了一个工程目录,并且该目录中的文件系统布局如下:
```
smallerContainer/
|- files/
@ -124,14 +119,14 @@ smallerContainer/
### 构建
现在构建镜像。下边的每个阶段都会添加一层改进来帮助减小镜像的大小。你最终会得到一系列镜像,但只有一个 _Containerfile_
现在构建镜像。下边的每个阶段都会添加一层改进来帮助减小镜像的大小。你最终会得到一系列镜像,但只有一个 `Containerfile`
#### 阶段0一个基本的容器镜像
#### 阶段 0一个基本的容器镜像
你的新镜像将会非常简单,它只包含强制性步骤。在 _Containerfile_ 中添加以下内容。
你的新镜像将会非常简单,它只包含强制性步骤。在 `Containerfile` 中添加以下内容:
```
# 使用 Fedora 33作为基镜像
# 使用 Fedora 33 作为基镜像
FROM registry.fedoraproject.org/fedora:33
# 安装 httpd
@ -140,7 +135,7 @@ RUN dnf install -y httpd
# 复制这个网站
COPY files/* /var/www/html/
# 设置端口为80/tcp
# 设置端口为 80/tcp
EXPOSE 80
# 启动 httpd
@ -149,15 +144,13 @@ CMD ["httpd", "-DFOREGROUND"]
在上边的文件中有一些注释来解释每一行内容都是在做什么。更详细的步骤:
1. 在FROM registry.fedoraproject.org/fedora:33 的基础上创建一个构建容器
2. 运行命令: _dnf install -y httpd_
3. 将与 _Containerfile_ 有关的文件拷贝到容器中
4. 设置EXPOSE 80来说明哪个端口是可以自动设置的
5. 设置一个CMD指令来说明如果从这个镜像创建一个容器应该运行什么
1. 在 `FROM registry.fedoraproject.org/fedora:33` 的基础上创建一个构建容器
2. 运行命令: `dnf install -y httpd`
3. 将与 `Containerfile` 有关的文件拷贝到容器中
4. 设置 `EXPOSE 80` 来说明哪个端口是可以自动设置的
5. 设置一个 `CMD` 指令来说明如果从这个镜像创建一个容器应该运行什么
运行下边的命令从工程目录创建一个新的镜像。
运行下边的命令从工程目录创建一个新的镜像:
```
$ podman image build -f Containerfile -t localhost/web-base
@ -174,13 +167,13 @@ registry.fedoraproject.org/fedora 33 9f2a56037643 3 months ago 182 MB
以上这个例子中展示的镜像在现在占用了467 MB的空间。剩下的阶段将会显著地减小镜像的大小。但是首先要验证镜像是否能够按照预期工作。
输入以下命令来启动容器
输入以下命令来启动容器
```
$ podman container run -d --name web-base -P localhost/web-base
```
输入以下命令可以列出你的容器
输入以下命令可以列出你的容器
```
$ podman container ls
@ -188,16 +181,15 @@ CONTAINER ID IMAGE COMMAND CREATED STATUS
d24063487f9f localhost/web-base httpd -DFOREGROUN... 2 seconds ago Up 3 seconds ago 0.0.0.0:46191->80/tcp web-base
```
以上展示的容器正在运行,它正在监听的端口是 _46191_ 。从运行在主机操作系统上的web浏览器转到 _localhost:46191_ 应该呈现你的web页面。
以上展示的容器正在运行,它正在监听的端口是 `46191` 。从运行在主机操作系统上的 web 浏览器转到 `localhost:46191` 应该呈现你的 web 页面:
```
$ firefox localhost:46191
```
#### 阶段1清除缓存并将残余的内容从容器中删除
#### 阶段 1清除缓存并将残余的内容从容器中删除
为了优化容器镜像的大小,第一步应该总是执行”清理“。这将保证安装和打包所残余的内容都被删掉。这个过程到底需要什么取决于你的容器。对于以上的例子,只需要编辑 _Containerfile_ 让它包含以下几行。
为了优化容器镜像的大小,第一步应该总是执行“清理”。这将保证安装和打包所残余的内容都被删掉。这个过程到底需要什么取决于你的容器。对于以上的例子,只需要编辑 `Containerfile` 让它包含以下几行。
```
[...]
@ -207,7 +199,7 @@ RUN dnf install -y httpd && \
[...]
```
构建修改后的 _Containerfile_ 来显著地减小镜像这个例子中是237 MB
构建修改后的 `Containerfile` 来显著地减小镜像(这个例子中是 237 MB
```
$ podman image build -f Containerfile -t localhost/web-clean
@ -216,11 +208,11 @@ REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/web-clean latest f0f62aece028 6 seconds ago 237 MB
```
#### 阶段2删除文档和不需要的依赖包
#### 阶段 2删除文档和不需要的依赖包
许多包在安装时会被建议拉下来,包含一些弱依赖和文档。这些在容器中通常是不需要的,可以删除。 _dnf_ 命令的选项表明了他不需要包含弱依赖或文档。
许多包在安装时会被建议拉下来,包含一些弱依赖和文档。这些在容器中通常是不需要的,可以删除。 `dnf` 命令有选项可以表明它不需要包含弱依赖或文档。
再次编辑 _Containerfile_ ,并在 _dnf install_ 行中添加删除文档和弱依赖的选项:
再次编辑 `Containerfile` ,并在 `dnf install` 行中添加删除文档和弱依赖的选项:
```
[...]
@ -230,7 +222,7 @@ RUN dnf install -y httpd --nodocs --setopt install_weak_deps=False && \
[...]
```
构建经过以上修改后的 _Containerfile_ 可以得到一个更小的镜像231 MB
构建经过以上修改后的 `Containerfile` 可以得到一个更小的镜像231 MB
```
$ podman image build -f Containerfile -t localhost/web-docs
@ -239,11 +231,11 @@ REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/web-docs latest 8a76820cec2f 8 seconds ago 231 MB
```
#### 阶段3使用更小的容器基镜像
#### 阶段 3使用更小的容器基镜像
前面的阶段结合起来,使得示例镜像的大小减少了一半。但是仍然还有一些途径来进一步减小镜像的大小。这个基镜像 _registry.fedoraproject.org/fedora:33_ 是通用的。它提供了一组软件包许多人希望这些软件包预先安装在他们的Fedora Linux容器中。但是通用Fedora Linux基镜像中提供的包通常必须要的更多。Fedora工程也为那些希望只从基本包开始,然后只添加所需内容来实现较小总镜像大小的用户提供了一个 _fedora-minimal_ 镜像。
前面的阶段结合起来,使得示例镜像的大小减少了一半。但是仍然还有一些途径来进一步减小镜像的大小。这个基镜像 `registry.fedoraproject.org/fedora:33` 是通用的。它提供了一组软件包,许多人希望这些软件包预先安装在他们的 Fedora Linux 容器中。但是,通用Fedora Linux 基镜像中提供的包通常必须要的更多。Fedora 项目也为那些希望只从基本包开始,然后只添加所需内容来实现较小总镜像大小的用户提供了一个 `fedora-minimal` 镜像。
使用 _podman image search_ 来查找 _fedora-minimal_ 镜像如下所示。
使用 `podman image search` 来查找 `fedora-minimal` 镜像,如下所示:
```
$ podman image search fedora-minimal
@ -251,11 +243,10 @@ INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
fedoraproject.org registry.fedoraproject.org/fedora-minimal 0
```
_fedora-minimal_ 基镜像不包含[DNF][9]而是倾向于不需要Python的较小的[microDNF][10]。当 _registry.fedoraproject.org/fedora:33__registry.fedoraproject.org/fedora-minimal:33_ 替换后,需要用 _microdnf_ 来替换 _dnf_
`fedora-minimal` 基镜像不包含 [DNF][9],而是倾向于使用不需要 Python 的较小的 [microDNF][10]。当 `registry.fedoraproject.org/fedora:33``registry.fedoraproject.org/fedora-minimal:33` 替换后,需要用 `microdnf` 命令来替换 `dnf`
```
# 使用Fedora minimal 33作为基镜像
# 使用 Fedora minimal 33 作为基镜像
FROM registry.fedoraproject.org/fedora-minimal:33
# 安装 httpd
@ -263,7 +254,7 @@ RUN microdnf install -y httpd --nodocs --setopt install_weak_deps=0 && \
microdnf clean all -y
[...]
```
使用 _fedora-minimal_ 重新构建后的镜像大小如下所示 169 MB
使用 `fedora-minimal` 重新构建后的镜像大小如下所示 169 MB
```
$ podman image build -f Containerfile -t localhost/web-docs
@ -272,14 +263,13 @@ REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/web-minimal latest e1603bbb1097 7 minutes ago 169 MB
```
最开始的镜像大小是**467 MB**。结合以上每个阶段所提到的方法,进行重新构建之后可以得到最终大小为**169 MB**的镜像。最终的 _总_ 镜像大小比最开始的 _基_ 镜像大小小了182 MB
最开始的镜像大小是 **467 MB**。结合以上每个阶段所提到的方法,进行重新构建之后可以得到最终大小为 **169 MB** 的镜像。最终的 _总_ 镜像大小比最开始的 _基_ 镜像小了 182 MB
### 从零开始构建容器
前边的内容使用一个容器文件和Podman来构建一个新的镜像。还有最后一个方法要展示——使用Buildah来从头构建一个容器。Podman使用与Buildah相同的库来构建容器。但是Buildah被认为是一个纯构建工具。Podman被设计来是为了代替Docker的。
使用Buildah从头构建的容器是空的——它里边什么都 _没有_ 。所有的东西都需要安装或者从容器外拷贝。幸运地是使用Buildah可以相当简单。下边是一个从头开始构建镜像的小的Bash脚本。除了运行这个脚本你也可以在终端逐条地运行脚本中的命令来更好的理解每一步都是做什么的。
前边的内容使用一个容器文件和 Podman 来构建一个新的镜像。还有最后一个方法要展示——使用 Buildah 来从头构建一个容器。Podman 使用与 Buildah 相同的库来构建容器。但是 Buildah 被认为是一个纯构建工具。Podman 被设计来是为了代替 Docker 的。
使用 Buildah 从头构建的容器是空的——它里边什么都 _没有_ 。所有的东西都需要安装或者从容器外复制。幸运地是,使用 Buildah 相当简单。下边是一个从头开始构建镜像的小的 Bash 脚本。除了运行这个脚本,你也可以在终端逐条地运行脚本中的命令,来更好的理解每一步都是做什么的。
```
#!/usr/bin/env bash
@ -291,7 +281,7 @@ CONTAINER=$(buildah from scratch)
# 挂载容器文件系统
MOUNTPOINT=$(buildah mount $CONTAINER)
# 安装一个基本的文件系统和最小的包以及nginx
# 安装一个基本的文件系统和最小的包以及 nginx
dnf install -y --installroot $MOUNTPOINT --releasever 33 glibc-minimal-langpack httpd --nodocs --setopt install_weak_deps=False
dnf clean all -y --installroot $MOUNTPOINT --releasever 33
@ -305,14 +295,14 @@ buildah copy $CONTAINER 'files/*' '/var/www/html/'
# 设置端口为 80/tcp
buildah config --port 80 $CONTAINER
# 启动httpd
# 启动 httpd
buildah config --cmd "httpd -DFOREGROUND" $CONTAINER
# 将容器保存为一个镜像
buildah commit --squash $CONTAINER web-scratch
```
或者可以通过将上面的脚本传递给Buildah来构建镜像。注意不需要root权限。
或者,可以通过将上面的脚本传递给 Buildah 来构建镜像。注意不需要 root 权限。
```
$ buildah unshare bash web-scratch.sh
@ -321,13 +311,12 @@ REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/web-scratch latest acca45fc9118 9 seconds ago 155 MB
```
最后的镜像只有**155 MB**!而且[攻击面][11]也减少了。甚至在最后的镜像中都没有安装DNF或者microDNF
最后的镜像只有 **155 MB**!而且 [攻击面][11] 也减少了。甚至在最后的镜像中都没有安装 DNF或者 microDNF
### 结论
构建一个比较小的容器镜像有许多优点。减少所需要的带宽、磁盘占用以及攻击面,都会得到更好的镜像。只用很少的更改来减小镜像的大小很简单。许多更改都可以在不改变结果镜像的功能下完成。
只保存所需的二进制文件和配置文件来构建非常小的镜像也是可能的。
--------------------------------------------------------------------------------
@ -337,7 +326,7 @@ via: https://fedoramagazine.org/build-smaller-containers/
作者:[Daniel Schier][a]
选题:[lujun9972][b]
译者:[ShuyRoy](https://github.com/Shuyroy)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出