Docker 杂记
Dockerfile
Dockerfile是一个包含容器镜像定义
的文本文件,可用于启动容器。这个定义
包含命令、基础镜像、配置等。在这篇文章中,我们将介绍每个组件,并讨论在什么场景下使用它们。让我们开始吧。
Docker镜像
在深入了解各个组件之前,我们可能想知道Docker镜像到底是什么。参考:镜像的结构
镜像是一个只读模板,包含创建Docker容器的指令。通常,一个镜像是基于另一个镜像,并进行一些额外的定制。–Docker官方
Docker镜像可以包含很多文件,为了深入了解细节,让我们先拉取一个镜像。
1 |
|
从上面的输出中,我们知道我们从dockerhub拉取了python:alpine3.18
镜像,这个镜像有5层。
1 |
|
基础镜像 / 父镜像
在大多数Dockerfile中,你会看到的第一行是FROM {基础镜像}
,比如FROM python:3.8
。
这一行定义了我们要构建的镜像的基础镜像。基础镜像可能包含一个或多个层。
RUN
RUN
命令可用于执行一些命令,如安装包、下载文件等。需要提到的一点是,每个命令都会在现有镜像上添加一个新层。将多个命令合并到一个RUN
命令中是减小镜像大小和减少层数的常用技巧。
CMD
CMD描述默认的容器参数或命令。用户可以在使用时轻松覆盖默认命令。
ENTRYPOINT
ENTRYPOINT也用于定义始终运行的命令,这意味着它不能被覆盖。ENTRYPOINT可用于确保容器启动时始终运行特定命令,即使用户尝试覆盖它。
COPY
COPY
可用于将本地文件复制到容器镜像中,仅此而已。
ADD
ADD
命令也允许将文件/文件夹从主机复制到镜像。它支持tarball提取和远程URL支持。通常,ADD
比COPY
更受欢迎。现在让我们看一个在Dockerfile中使用ADD
的例子。
假设我们在一个文件夹/tmp/app
中,它有以下文件,
1 |
|
同时,我们在Dockerfile中写入以下命令。
1 |
|
上述命令将文件/tmp/app/server.js
(主机路径)复制到/tmp/server.js
(容器镜像路径)。我们注意到第一个参数应该在上下文内,上下文可以解释为我们执行docker build
命令的路径。
VOLUME
卷可以被视为Docker容器的持久数据存储。以下命令意味着从此镜像启动的任何容器,主机上的/var/www/html
目录将被挂载到容器内的/var/www/html
目录。这意味着在容器内对/var/www/html
目录所做的任何更改都将反映在主机上,反之亦然。
1 |
|
Dive
Dive是一个非常有用的工具,用于分析容器镜像。它使你能够看到每一层的命令和反映在文件系统上的变化。
参考
Docker FileSystem
Docker的filesystem有很多,可以配置,最常用且推荐的目前应该是overlay2,它的性能和稳定性都比较好。如果你对Docker DataRoot list一下,你会发现有很多文件夹,其中有一个是overlay2,这个文件夹就是overlay2的存储位置。
1 |
|
其中有很多各个文件夹,名字都是一串哈希值,这些文件夹就是各个镜像的FileSystem的存储位置,其中是每个都是一个layer,这个layer有可能是一个image 的layer,也可能是正在运行的container的layer,也可能是一个volume的layer。
1 |
|
这里folder name的hash并不是layer的sha256,而是一个短ID,Overlay2 在磁盘上为该层分配的 diff 目录名。
1 |
|
Overlay2 存储结构要点
1. 镜像元数据 & LayerDB
• /var/lib/docker/image/overlay2/imagedb/content/sha256/
这里的
• /var/lib/docker/image/overlay2/layerdb/sha256/
这个文件里的内容(一个短 ID,比如 36849485abab637c0…)才是 Overlay2 在磁盘上为该层分配的 diff 目录名。
2. Overlay2 工作目录
• /var/lib/docker/overlay2/
存放该层的实际文件内容。
• /var/lib/docker/overlay2/
容器运行时挂载点,读取时会把 LowerDir + UpperDir overlay 在这里。