镜像制作及原因
镜像制作是因为某种需求,官方的镜像无法满足需求,需要我们通过一定手段来自定
义镜像来满足要求。
制作镜像往往因为以下原因
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