在本文中,你将了解如何加快 Docker 构建周期并创建轻量级镜像。还是用比喻来说吧,给 Docker 镜像瘦身就跟我们减肥一样,减肥时期我们吃沙拉,拒绝披萨、甜甜圈和百吉饼。
这是备忘单。
FROM:指定基础(父)镜像。
ENV:设置一个持久环境变量。
RUN:运行一个命令并创建一个图像层。用于将包安装到容器中。
COPY:将文件和目录复制到容器中。
ADD:将文件和目录复制到容器中。可以上传本地.tar 文件中。
CMD:为正在执行的容器提供命令和参数。可以覆盖参数。只能有一个 CMD。
WORKDIR:为下面的指令设置工作目录。
ARG:在构建时传递给 Docker 的变量。
ENTRYPOINT:为正在执行的容器提供命令和参数。关于这件事的争论一直在持续。
EXPOSE:公开端口。
VOLUME:创建一个目录挂载点来访问和存储持久数据。
现在让我们看看如何设计 dockerfile,以便在开发镜像和提取容器时节省时间。
缓存
Docker 的优点之一是提供缓存,帮助你更快地迭代镜像构建。
在构建映像时,Docker 按步骤遍历 Dockerfile 中的指令,按顺序执行每个指令。在检查每个指令时,Docker 会在其缓存中寻找一个可以重用的现有中间镜像,而不是创建一个新的(重复的)中间映像。
如果缓存无效,让无效的指令和所有后续 Dockerfile 指令生成新的中间镜像。一旦缓存失效,Dockerfile 中其余的指令也就失效了。
因此,从 Dockerfile 的顶部开始,如果基础镜像已经在缓存中,那么它将被重用。这将是高效命中。否则,缓存无效。
也是一击
然后将下一条指令与从该基础镜像派生的缓存中的所有子镜像进行比较。比较每个缓存的中间镜像,看指令是否在缓存命中。如果缓存失败,则缓存无效。重复相同的过程,直到到达 Dockerfile 的末尾。
大多数新指令只是简单地与中间镜像中的指令进行比较。如果匹配,则使用缓存的副本。
例如,当在 Dockerfile 中找到
RUN pip install -r requiremtes .txt
指令时,Docker 会在本地缓存的中间镜像中搜索相同的指令。不比较新旧 requirements.txt 文件的内容。
如果使用新包来更新 文件,并使用
RUN pip install
并希望使用新包名称重新运行包安装,则此行为可能会出现问题。我一会儿会展示一些解决方案。
与其他 Docker 指令不同,ADD 和 COPY 指令确实需要 Docker 查看文件的内容,以确定是否存在缓存命中。将引用文件的校验和与现有中间镜像中的校验和进行比较。如果文件内容或元数据发生了更改,则缓存无效。
下面是一些有效使用缓存的技巧。
COPY requirements.txt /tmp/
RUN pip install -r /tmp/requirements.txt
COPY . /tmp/
复制代码
这些是有效使用 Docker 构建缓存的建议。
减小尺寸
Docker 镜像可能会变得很大。你想让它们尺寸变小,这样它们就可以快速拉起,使用很少的资源。让我们给你的镜像瘦身!
吃顿沙拉而不是百吉饼
Alpine base 镜像是一个完整的 Linux 发行版,没有太多其他东西。下载通常小于 5mb,但是它需要更多的时间为构建应用程序所需的依赖项编写代码。
Alpine 源自阿尔卑斯山脉
如果你的容器中需要 Python, Python Alpine 构建是一个不错的折衷方案。它包含 Linux 和 Python,你可以提供大多数其他东西。
我用最新的 Python Alpine 构建的带有打印脚本(“hello world”)的镜像大小为 78.5 MB。下面是 Dockerfile:
FROM python:3.7.2-alpine3.8
ENTRYPOINT [“python”, “./app/my_script.py”, “my_var”]
复制代码
在 Docker Hub 上,基础镜像的大小为 29MB,当构建子镜像时,需要下载并安装 Python,尺寸就变得很大。
除了使用 Alpine 基础镜像,另一种减小镜像大小的方法是使用多级构建。这种技术还会增加 Dockerfile 的复杂性。
多级构建
一个舞台+另一个舞台=多级舞台
多阶段构建使用多个 FROM 指令。你可以有选择地将文件(称为构建工件)从一个阶段复制到另一个阶段。你可以在最终的镜像中扔掉任何你不想要的东西。这种方法可以减少整体镜像的大小。
每个 FROM 指令
下面是Docker文档中经过修改的多级构建示例:
FROM golang:1.7.3 AS build
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=build /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
复制代码
注意,我们通过给 FROM 指令增加一个名字来命名第一阶段。然后,被命名的阶段会通过
COPY --from=
指令引用到Dockerfile 中。
在制造大量容器的情况下,多级构建是有意义的。多级构建可以帮助你从镜像大小中挤出每一寸空间。然而,有时多阶段构建会增加复杂性,使镜像更难维护,因此你可能不会在大多数构建中使用它们。参见此处对折衷和高级模式的进一步讨论。
相反,每个人都应该使用.dockerignore 文件来帮助保持 Docker 镜像的简洁。
.dockerignore
如果你对 Docker 了解得足够多,那么*.dockerignore*就是一些你应该知道的东西。
.dockerignore 类似于.gitignore。它是一个包含 Docker 模式列表的文件,Docker 在生成镜像时需要匹配文件名并排除这些模式。
来.dockerignore 一下
将.dockerignore 文件与 Dockerfile 和构建上下文的其余部分放在同一个文件夹中。
运行 docker build 创建镜像时,docker 检查.dockerignore 文件。如果找到一个,则逐行检查文件并使用 Go 的filepath。匹配规则——以及Docker自己的一些规则——以匹配文件名以进行排除。想想 unix 风格的 glob 模式,而不是正则表达式。
因此将排除扩展名为.jpg 的文件。并且
视频
将排除视频文件夹及其内容。
您可以使用以开头的注释来解释您在.dockerignore 中所做的事情。
使用.dockerignore 从 Docker 镜像中排除不需要的文件是个好主意。
这就是使用.dockerignore 文件的原因。
尺寸检查
让我们看看如何从命令行找到 Docker 镜像和容器的大小。
现在,让我们来看看一些最佳实践来给镜像瘦身。
减少镜像大小和构建时间的八个最佳实践
3.如果使用 apt,请在同一指令中将 RUN apt-get update 与 apt-get install 结合使用。然后在该指令中链接多个包。用\字符在多行上按字母顺序列出包。例如:
RUN apt-get update && apt-get install -y \
package-one \
package-two
&& rm -rf /var/lib/apt/lists/*
复制代码
这种方法减少了要构建的层的数量,并保持简洁。
总结
现在你知道了如何使 Docker 镜像快速构建、快速下载,并且不占用太多空间。和健康饮食一样,知道是成功的一半。享受你的蔬菜。
健康和美味
查看英文原文链接: