Docker核心技术和实现原理

镜像制作及原因

镜像制作是因为某种需求,官方的镜像无法满足需求,需要我们通过一定手段来自定
义镜像来满足要求。
制作镜像往往因为以下原因
1. 编写的代码如何打包到镜像中直接跟随镜像发布
2. 第三方制作的内容安全性未知,如含有安全漏洞
3. 特定的需求或者功能无法满足,如需要给数据库添加审计功能
4. 公司内部要求基于公司内部的系统制作镜像,如公司内部要求使用自己的操作系
统作为基础镜像

Docker 镜像制作方式

制作容器镜像,主要有两种方法:
制作快照方式获得镜像(偶尔制作的镜像):在基础镜像上(比如 Ubuntu ),先登
录容器中,然后安装镜像需要的所有软件,最后整体制作快照。
Dockerfile 方式构建镜像(经常更新的镜像):将软件安装的流程写成 Dockerfile
使用 docker build 构建成容器镜像。

快照方式制作镜像

制作命令

docker commit

功能
从容器创建一个新的镜像。
参数
-a : 提交的镜像作者;
-c : 使用 Dockerfile 指令来创建镜像;可以修改启动指令
-m : 提交时的说明文字;
-p : commit 时,将容器暂停。
样例

Dockerfile 格式

该指令不区分大小写。然而,约定是它们是大写的,以便更容易地将它们与参数区分
开来。 Docker 按顺序运行指令 Dockerfile Docker 将以 开头 的行视为 # 注释,行中其他任何地方的标记 # 都被视为参数。这允许像 这样的语句:

为什么需要 Dockerfile

可以按照需求自定义镜像
docker commit 一样能够自定义镜像,官方的镜像可以说很少能直接满足
我们应用的,都需要我们自己打包自己的代码进去然后做成对应的应用镜像对外
使用。
很方便的自动化构建,重复执行
通过 dockerfile 可以自动化的完成镜像构建,而不是像 docker commit 一样,
手动一个命令一个命令执行,而且可以重复执行, docker commit 的话很容易忘
记执行了哪个命令,哪个命令没有执行。
维护修改方便,不再是黑箱操作
使用 docker commit 意味着所有对镜像的操作都是黑箱操作,生成的镜像也
被称为黑箱镜像 ,dockerfile 很容易二次开发。
更加标准化,体积可以做的更小
docker 容器启动后,系统运行会生成很多运行时的文件,如果使用 commit
导致这些文件也存储到镜像里面,而且 commit 的时候安装了很多的依赖文件,
没有有效的清理机制的话会导致镜像非常的臃肿。使用 Dockerfile 则会更加标准
化,而且提供多级构建,将编译和构建分开,不会有运行时的多余文件,更加的
标准化。

Dockerfile 指令

指令清单
FROM
功能
FROM 指令用于 为镜像文件构建过程指定基础镜像 ,后续的指令运行于此基
础镜像所提供的运行环境;
注意事项
FROM 指令必须是 Dockerfile 非注释行或者 ARG 之后的第一个指令
实践中,基准镜像可以是任何可用镜像文件,默认情况下, docker build 会在
docker 主机上查找指定的镜像文件 ,在其不存在时,则 会自动从 Docker 的公共
pull 镜像下来。如果找不到指定的镜像文件, docker build 会返回一个错误信
息;
FROM 可以在一个 Dockerfile 中出现多次,如果有需求在一个 Dockerfile
创建多个镜像 , 或将一个构建阶段作为另一个的依赖。
如果 FROM 语句没有指定镜像标签,则 默认使用 latest 标签
参数
<platform>: 构建的 cpu 架构,如 linux/amd64 , linux/arm64 ,
windows/amd64
<image> :指定作为 base image 的名称;
<tag> base image 的标签,省略时默认 latest
<digest> :是镜像的哈希码;
AS <name>: 指定构建步骤的名称,配合 COPY --from=<name> 可以完成多
级构建
LABEL
功能
为镜像添加元数据,元数据是 kv 对形式
语法
Shell
LABEL <key>=<value> <key>=<value> <key>=<value> ...
COPY
功能
用于从 docker 主机复制新文件或者目录至创建的新镜像指定路径中 。
语法
参数
<src> :要复制的源文件或目录, 支持使用通配符
<dest> :目标路径,即正在创建的 image 的文件系统路径; 建议 <dest> 使用
绝对路径 ,否则, COPY 指定以 WORKDIR 为当前路径
在路径中有空白字符时,通常使用第 2 种格式;
--chown :修改用户和组
--from <name> 可选项 :
可以从之前构建的步骤中拷贝内容,结合 FROM .. AS <name> 往往用作
多级构建,后续我们有实战课专门完成多级构建
注意事项
<src> 必须是 build 上下文中的路径, 不能是其父目录中的文件
如果 <src> 是目录 ,则其 内部文件或子目录会被递归复制 ,但 <src> 目录自身
不会被复制
如果指定了多个 <src> ,或在 <src> 中使用了通配符,则 <dest> 必须是一个目
录,且 必须以 / 结尾
如果 <dest> 事先不存在,它将 会被自动创建 ,这包括父目录路径。
ENV
功能
用于为镜像定义所需的 环境变量 ,并可被 Dockerfile 文件中 位于其后的 其它指
( ENV ADD COPY ) 所调用
调用格式为 $variable_name ${variable_name}
语法
WORKDIR
功能
Dockerfile 中所有的 RUN CMD ENTRYPOINT COPY ADD 指定
定工作目录
语法
注意事项
默认的工作目录是 /
如果提供了相对路径,它将相对于前一条 WORKDIR 指令的路径。
WORKDIR 指令可以解析先前使用设置的环境变量 ENV
ADD
功能
ADD 指令类似于 COPY 指令, ADD 支持使用 TAR 文件和 URL 路径 , 会自动
完成解压和下载
语法
参数
<src> :要复制的源文件或目录, 支持使用通配符
<dest> :目标路径,即正在创建的 image 的文件系统路径; 建议 <dest> 使用
绝对路径 ,否则, ADD 指定以 WORKDIR 为其实路径;在路径中有空白字符时,
通常使用第 2 种格式;
--chown :修改用户和组
RUN
功能
用于指定 docker build 过程中运行的程序,其可以是任何命令
语法
参数
第一种格式中, <command> 通常是一个 shell 命令 , 且 “/bin/sh -c” 来运
,Windows 默认为 cmd /S /C 。如果一个脚本 test.sh 不能自己执行,必须要
/bin/sh -c test.sh 的方式来执行,那么,如果使用 RUN shell 形式 ,最后
得到的命令相当于:
Bash
/bin/sh -c "/bin/sh -c 'test.sh'"
第二种语法格式中的参数是一个 JSON 格式的数组 ,其中 <executable> 为要
运行的命令,后面的 <paramN> 为传递给命令的选项或参数;然而,此种格式指
定的命令 不会以 “/bin/sh -c” 来发起 ,因此 常见的 shell 操作 如变量替换以及通配
(?,* ) 替换 将不会进行 ;不过,如果要运行的命令依赖于此 shell 特性的话,可
以将其替换为类似下面的格式。 RUN ["/bin/bash", "-c", "<executable>",
"<param1>"]
Shell
ENV WEB_SERVER_PACKAGE nginx-1.21.1.tar.gz
RUN cd ./src && tar -xf ${WEB_SERVER_PACKAGE}
CMD
功能
类似于 RUN 指令 CMD 指令也可用于运行任何命令或应用程序,不过,二
者的运行时间点不同
RUN 指令运行于映像文件 构建 过程 中,而 CMD 指令运行于基于 Dockerfile
构建出的新映像文件 启动 一个容器时
CMD 指令的首要 目的在于为启动的容器指定默认要运行的程序 ,且其运行结
束后,容器也将终止;不过, CMD 指定的命令其可以被 docker run 的命令行选
项所覆盖
Dockerfile 中可以存在 多个 CMD 指令,但仅最后一个会生效
注意事项
第二种则用于为 ENTRYPOINT 指令提供默认参数
json 数组中,要使用 双引号 ,单引号会出错
EXPOSE
功能
用于为容器 声明 打开指定要监听的端口 以实现与外部通信
EXPOSE 指令实际上并不发布端口。它充当构建图像的人和运行容器的人之
间的一种文档,关于要发布哪些端口。要在运行容器时实际发布端口,使用 -p
数发布和映射一个或多个端口,或者使用 -P flag 发布所有暴露的端口并将它们映
射宿主机端口。
语法
Shell
EXPOSE <port> [<port>/<protocol>...]
参数
<protocol> tcp/udp 协议
<port> :端口
样例
Shell
EXPOSE 80/tcp
ENTRYPOINT
功能
用于指定容器的启动入口
语法
参数
json 数组中,要使用 双引号 ,单引号会出错
样例
Shell
ENTRYPOINT ["nginx","-g","daemon off;"]
ARG
功能
ARG 指令类似 ENV ,定义了一个变量;区别于 ENV :用户可以在构建时
docker build --build-arg <varname> = <value> 进行对变量的修改; ENV 不可以;
如果用户指定了未在 Dockerfile 中定义的构建参数,那么构建输出警告。
语法
注意事项
Dockerfile 可以包含一个或多个 ARG 指令
ARG 支持指定默认值
使用范围:定义之后才能使用,定义之前为空,如下面的案例,执行命令
docker build --build-arg username=what_user . 第二行计算结果为
some_user ,不是我们指定的 build-arg 中的参数值 what_user
ENV ARG 同时存在, ENV 会覆盖 ARG
VOLUME
功能
用于在 image 中创建一个挂载点目录
通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成
的。
语法
参数
mountpoint: 挂载点目录
注意事项
如果挂载点目录路径下此前有文件存在,docker run 命令会在卷挂载完
成后将此前的所有文件复制到新挂载的卷中
其实 VOLUME 指令只是起到了声明了容器中的目录作为匿名卷,但是并
没有将匿名卷绑定到宿主机指定目录的功能。
volume 只是指定了一个目录,用以在用户忘记启动时指定 -v 参数也可以
保证容器的正常运行。比如 mysql ,你不能说用户启动时没有指定 -v ,然后
删了容器,就把 mysql 的数据文件都删了,那样生产上是会出大事故的,所
mysql dockerfile 里面就需要配置 volume ,这样即使用户没有指定 -v
容器被删后也不会导致数据文件都不在了。还是可以恢复的。
volume 与 -v 指令一样,容器被删除以后映射在主机上的文件不会被删除。
如果-v volume 指定了同一个位置,会以 -v 设定的目录为准,其实
volume 指令的设定的目的就是为了避免用户忘记指定 -v 的时候导致的数据丢
失,那么如果用户指定了 -v ,自然而然就不需要 volume 指定的位置了。
样例
Shell
VOLUME ["/data1","/data2"]
SHELL
功能
SHELL 指令允许覆盖用于 shell 命令形式的默认 shell
Linux 上的默认 shell ["/bin/sh" "-c"] ,在 Windows 上是 ["cmd" "/S"
"/C"]
SHELL 指令必须以 JSON 格式写入 Dockerfile
语法
Shell
SHELL ["executable", "parameters"]
参数
executable shell
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值