当前位置:   article > 正文

Docker完整版(二)_docker scratch

docker scratch

Docker完整版(二)

一、Dockerfile

1. Dockerfile简介

Dockerfile 是用于构建Docker镜像的脚本文件,由一系列指令构成。通过 docker build命令构建镜像时,Dockerfile 中的指令会由上到下依次执行,每条指令都将会构建出一个镜像。这就是镜像的分层,因此,指令越多,层次数就越多,创建的镜像就越多,效率就越低。所以在定义Dockerfile时,能在一个指令完成的动作就不要分为两条。

2. Dockerfile指令简介

  • 该指令不区分大小写。但是,惯例是将它们大写,以便更容易地将它们与参数区分开来。
  • 指令后至少携带一个参数。
  • # 号开头的行为注释。
  1. FORM

    • 语法:FORM <image>[:<tag>]
    • 解析:用于指定基础镜像,且必须是第一条指令;若省略了 tag,则默认为 latest。
  2. MAINTAINER

    • 语法:MAINTAINER <name>
    • 解析:MAINTAINER 指令的参数填写的一般是维护者姓名和信箱。不过,该指令官方已不建议使用,而是使用 LABEL 指令代替。
  3. LABLE

    • 语法:LABEL<key>=<value> <key>=<value> ……,
    • 解析:LABEL 指令中可以以键值对的方式包含任意镜像的元数据信息,用于替代 MAINTAINER 指令。通过 docker inspect 可查看到 LABEL 与 MAINTAINER 的内容。
  4. ENV

    • 语法 1:ENV <key> <value>
    • 解析: 用于指定环境变量,这些环境变量,后续可以被 RUN 指令使用,容器运行起来之后,也可以在容器中获取这些环境变量。
    • 语法 2:ENV <key1>=<value1> <key2>=<value2> …
    • 解析:可以设置多个变量,每个变量为一对<key>=<value>指定。
  5. WORKDIR

    • 语法:WORKDIR path
    • 解析:容器打开后默认进入的目录,一般在后续的 RUN、CMD、ENTRYPOINT、ADD 等指令中会引用该目录。可以设置多个 WORKDIR 指令。后续 WORKDIR 指令若用的是相对路径,则会基于之前 WORKDIR 指令指定的路径。在使用 docker run 运行容器时,可以通过 -w 参数覆盖构建时所设置的工作目录。
  6. RUN

    • 语法 1:RUN <command>
    • 解析:这里的就是 shell 命令。docker build 执行过程中,会使用 shell 运行指定的 command。
    • 语法 2:RUN [“EXECUTABLE”,“PARAM1”,“PARAM2”, …]
    • 解析:在 docker build 执行过程中,会调用第一个参数"EXECUTABLE"指定的应用程序运行,并使用后面第二、三等参数作为应用程序的运行参数。
  7. CMD

    • 语法 1:CMD [“EXECUTABLE”,“PARAM1”,“PARAM2”, …]
    • 解析:在容器启动后,即在执行完 docker run 后会立即调用执行"EXECUTABLE"指定的可执行文件,并使用后面第二、三等参数作为应用程序的运行参数。
    • 语法 2:CMD command param1 param2, …
    • 解析:这里的 command 就是 shell 命令。在容器启动后会立即运行指定的 shell 命令。
    • 语法 3:CMD [“PARAM1”,“PARAM2”, …]
    • 解析:提供给 ENTERYPOINT 的默认参数。
  8. ENTRYPOINT

    • 语法 1:ENTRYPOINT [“EXECUTABLE”,“PARAM1”,“PARAM2”, …]
    • 解析:在容器启动过程中,即在执行 docker run 时,会调用执行"EXECUTABLE"指定的应用程序,并使用后面第二、三等参数作为应用程序的运行参数。
    • 语法 2:ENTRYPOINT command param1 param2, …
    • 解析:这里的 command 就是 shell 命令。在容器启动过程中,即在执行 docker run 时,会运行指定的 shell 命令。
  9. EXPOSE

    • 语法:EXPOSE <port> [<port>…]
    • 解析: 指定容器准备对外暴露的端口号,但该端口号并不会真正的对外暴露。若要真正暴露,则需要在执行 docker run 命令时使用-p(小 p)来指定说要真正暴露出的端口号。
  10. ARG

    • 语法:ARG <varname>[=<default value>]
    • 解析:定义一个变量,该变量将会使用于镜像构建运行时。若要定义多个变量,则需要定义多个 ARG 指令。
  11. ADD

    • 语法 1:ADD <src> <dest>
    • 语法 2:ADD [“<src>”, “<dest>”] # 路径中存在空格时使用双引号引起来
    • 解析:该指令将复制当前宿主机中指定文件 src 到容器中的指定目录 dest 中。src 可以是宿主机中的绝对路径,也可以时相对路径。但相对路径是相对于 docker build 命令所指定的路径的。src 指定的文件可以是一个压缩文件,压缩文件复制到容器后会自动解压为目录;src 也可以是一个 URL,此时的 ADD 指令相当于 wget 命令;src 最好不要是目录,其会将该目录中所有内容复制到容器的指定目录中。dest 是一个绝对路径,其最后面的路径必须要加上斜杠,否则系统会将最后的目录名称当做是文件名的。
  12. COPY

    • 说明:功能与 ADD 指令相同,只不过 src 不能是 URL。若 src 为压缩文件,复制到容器后不会自动解压。
  13. ONBUILD

    • 语法:ONBUILD [INSTRUCTION]
    • 解析:该指令用于指定当前镜像的子镜像进行构建时要执行的指令。
  14. VOLUME

    • 语法:VOLUME [“dir1”, “dir2”, …]
    • 解析:在容器创建可以挂载的数据卷。

3. Dockerfile指令用法

1.3.1 构建自己的HelloWorld镜像

(1)scratch境像

在构建自己的镜像之前,首先要了解一个特殊的镜像 scratch。

scratch 镜像是一个空镜像,是所有镜像的 Base lmage(相当于面向类).对象编程中的Object类)。scratch 镜像只能在 Dockerfile 中被继承,不能通过 pull 命令拉取,不能 run,也没有 tag。不并且它也不会生成镜像中的文件系统层。在 Docker 中,scratch 是一个保留字,用户不能作为自己的镜像名称使用。

(2)安装编译器

yum install -y gcc gcc-c++
  • 1

由于下面要编写、编译一段c语言代码,所以要先安装一下c语言的编译器。

由于后面在编译时要使用c的静态库,所以要再安装 glibc-static。·

yum install -y glibc-static
  • 1

注意:
在CentOS 8上安装glibc-static时可能会遇到以下错误:No package glibc-static available。这是因为在CentOS 8中,glibc-static软件包已被移除。

glibc-static软件包包含了glibc库的静态版本,用于编译和链接需要静态库的程序。然而,由于静态库的使用逐渐减少,CentOS 8决定将glibc-static软件包从默认仓库中删除。

如果您确实需要安装glibc-static,有几种解决方法可供选择:

  1. 使用其他发行版:如果您需要使用glibc-static,可以考虑使用其他发行版,如CentOS 7或Ubuntu等,它们可能仍然提供glibc-static软件包。

  2. 手动编译安装:您可以手动从源代码编译和安装glibc-static。首先,您需要下载glibc的源代码,并按照编译和安装指南进行操作。请注意,这是一项复杂的任务,需要一定的技术知识和经验。

  3. 寻找第三方仓库:您可以尝试寻找第三方仓库,这些仓库可能提供了glibc-static软件包。但请注意,使用第三方仓库存在一定的风险,请确保您从可信任的来源获取软件包。

(3)创建hello.c

在宿主机任意目录创建一个名称为 hello.c 的文件。这里在/root 下 mkdir 一个目录 hw,然后将 hello.c 文件创建在这里。文件内容如下:

# 创建目录
mkdir hw

# 进入目录
cd ./hw

# 编辑文件
vim hello.c
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
#include<stdio.h>
int main()
{
   
	printf("hello my docker world\n");
 	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

(4)编译测试hello.c

使用 gcc 编译 hello.c 文件。

在这里插入图片描述 (5)创建Dockerfile

在 hw 目录中新建 Dockerfile,内容如下:

FROM scratch
ADD hello /
CMD ["/hello"] 
  • 1
  • 2
  • 3

(6)构建镜像

在这里插入图片描述

  • -t 用于指定要生成的镜像的<repository>与<tag>。若省略 tag,则默认为 latest。

  • 最后的点(.)是一个宿主机的 URL 路径,构建镜像时会从该路径中查找 Dockerfile 文件。同时该路径也是在 Dockerfile 中 ADD、COPY 指令中,若使用的是相对路径,那个相对路径就相对的这个路径。不过需要注意,即使 ADD、COPY 指令中使用绝对路径来指定源文件,该源文件所在路径也必须要在这个 URL 指定目录或子目录内,否则将无法找到该文件。

  • 通过 docker images 查看本地镜像,可以看到新构建的 hello-my-world 镜像。

(7)运行新镜像

在这里插入图片描述

(8)为镜像重打标签

某镜像被指定为 latest 后,后期又出现了更新的版本需要被指定为 latest,那么原 latest 镜像就应被重打<tag>标签,否则,当最新版被发布为 latest 后,原镜像就会变为悬虚镜像。
通过 docker tag 命令可对镜像重打标签。所谓重打标签,实际是复制了一份原镜像,并为新的镜像指定新的<tag>。当然,重新指定<repository>也是可以的。所以,新镜像的 ImageID、Digest 都与原镜像的相同。

在这里插入图片描述
查看镜像,发现增加了一个新的镜像。

在这里插入图片描述

1.3.2 构建自己的CentOS镜像

从镜像中心拉取来的 centos:7 镜像中是没有 vim、ifconfig、wget 等常用命令的,这里要构建一个自己的 centos7 镜像,使这些命令都可以使用。

(1)创建 Dockerfile

在宿主机任意目录创建一个文件,并命名为 Dockerfile。这里在/root 下 mkdir 一个目录 dfs。然后将如下内容复制到该文件中:

FROM centos:7
MAINTAINER zhangsan zs@163.com
LABEL version="1.0" description="this is a custom centos image"
ENV WORKPATH /usr/local
WORKDIR $WORKPATH
RUN yum -y install vim net-tools wget
CMD /bin/bash
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

(2)构建镜像 build

在这里插入图片描述
当看到下面的日志时说明构建完成。

在这里插入图片描述
此时通过 docker images 命令可以查看到刚刚生成的新的镜像。并且还发现,新镜像的大小要大于原镜像的,因为新镜像安装了新软件。
在这里插入图片描述
(3)运行新建镜像

运行了新镜像后,发现默认路径是 /usr/local 了,ifconfig、vim 命令可以使用了。在这里插入图片描述

1.3.3 悬虚镜像

悬虚镜像是指既没有 Repository 又没有 Tag 的镜像。当新建了一个镜像后,为该镜像指定了一个已经存在的 TAG,那么原来的镜像就会变为悬空镜像。
为了演示悬虚镜像的生成过程,这里先修改前面定义的 Dockerfile,然后再生成镜像,且生成的新的镜像与前面构建的镜像的名称与 Tag 均相同。

(1)修改 Dockerfile

修改 /root/dfs 中的 Dockerfile。修改任意内容均可。这里仅将原来的 LABEL 中的 version 值由 1.0 修改为了 2.0,其它没变。

FROM centos:7
MAINTAINER zhangsan zs@163.com
LABEL version="2.0" description="this is a custom centos image"
ENV WORKPATH /usr/local
WORKDIR $WORKPATH
RUN yum -y install vim net-tools wget
CMD /bin/bash
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

(2)构建镜像 build

在构建镜像之前,先查看前面构建的 cucentos:1.0 镜像的 ID,以备在后面进行对比。

在这里插入图片描述

构建镜像时仍然指定镜像为 cucentos:1.0,与前面的镜像完全重名。

在这里插入图片描述

构建完毕后,再次查看镜像,发现原来 cucentos:1.0 镜像的名称与 Tag 均变为了<none>,即变为了悬虚镜像。

在这里插入图片描述

(3)删除悬虚镜像

悬虚镜像是一种“无用”镜像,其存在只能是浪费存储空间,所以一般都是要删除的。对于悬虚镜像的删除,除了可以通过 docker rmi <imageID>进行删除外,还有专门的删除命令 docker image prune,该命令能够一次性删除本地全部的悬空镜像。不过有个前提,就是这些悬虚镜像不能是已经启动了容器的,无论容器是否是退出状态。当然,如果再加上-a 选项,则会同时再将没有被任何容器使用的镜像也删除。

另外,还有一个命令 docker system prune 也可以删除悬虚镜像。只不过,其不仅删除的是悬虚镜像,还有其它系统“无用”内容。

在删除这个悬虚镜像之前,首先查看其是否启动了容器。如果启动了,则先将容器删除。

在这里插入图片描述

在删除了相关容器后再运行 docker image prune

在这里插入图片描述

此时再查看就发现悬虚镜像已经被删除了。

在这里插入图片描述

使用 docker system prune 命令可删除系统中的四类“无用”内容,其中就包含悬虚镜像 dangling images。

在这里插入图片描述

1.3.4 CMD与ENTERYPOINT用法

这两个指令都用于指定容器启动时要执行的命令,无论哪个指令,每个 Dockerfile 中都只能有一个 CMD/ENTERYPOINT 指令,多个 CMD/ENTERYPOINT 指令只会执行最后一个。不同的是,CMD 指定的是容器启动时默认的命令,而 ENTRYPOINT 指定的是容器启动时一定会执行的命令。即 docker run 时若指定了要运行的命令,Dockerfile 中的 CMD 指令指定的命令是不会执行的,而 ENTERYPOINT 中指定的命令是一定会执行的。

1.3.4.1 CMD-shell
  1. 创建 Dockerfile

在 dfs 目录中新建文件 Dockerfile2,并定义内容如下。

FROM centos:7
CMD cal
  • 1
  • 2
  1. 构建镜像 build

在这里插入图片描述

说明:-f 用于指定本次构建所要使用的 Dockerfile 文件。如果文件名不是 docker build 默认加载的 Dockerfile 这个名称。

在这里插入图片描述

  1. 运行新建镜像

运行后可以查看到当前月份的日历。

在这里插入图片描述

  1. 覆盖 CMD

在这里插入图片描述

在 docker run 命令中指定要执行的命令,Dockerfile 中通过 CMD 指定的默认的命令就不会在执行。

  1. 不能添加命令选项

在这里插入图片描述

这种方式无法为 CMD 中指定的默认的命令指定选项。

1.3.4.2 CMD-exec
  1. 创建 Dockerfile

在 dfs 目录中新建文件 Dockerfile3,并将如下内容复制到文件中。

FROM centos:7
CMD ["/bin/bash", "-c", "cal"]
  • 1
  • 2
  1. 构建镜像 build

使用 Dockerfile3 构建镜像 mycal:2.0。

在这里插入图片描述

  1. 运行新建镜像

运行结果与 shell 方式的相同。

在这里插入图片描述

  1. 覆盖 CMD

运行结果与 shell 方式的相同,也可以被覆盖。

在这里插入图片描述

  1. 不能添加命令选项

虽然在 CMD 中指定可以从命令行接收选项,但运行结果与 shell 方式的相同,也不能添加命令选项。这是由 CMD 命令本身决定的。

在这里插入图片描述

1.3.4.3 ENTRYPOINT-shell
  1. 创建 Dockerfile

在 dfs 目录中新建文件 Dockerfile4,并将如下内容复制到文件中。

FROM centos:7
ENTRYPOINT cal
  • 1
  • 2
  1. 构建镜像 build

使用 Dockerfile4 构建镜像 mycal:3.0。

在这里插入图片描述

  1. 运行新建镜像

在这里插入图片描述

  1. ENTRYPOINT 不会被覆盖

ENTRYPOINT 指定的命令是不会被 docker run 中指定的命令给覆盖掉的。

在这里插入图片描述

  1. 添加命令选项无效

在 docker run 中添加的命令选项,对于 ENTRYPOINT 中指定的命令是无效的。在这点上不像 CMD 指令一样报错。

在这里插入图片描述

1.3.4.4 ENTRYPOINT-exec
  1. 创建 Dockerfile

在 dfs 目录中新建文件 Dockerfile5,并将如下内容复制到文件中。

FROM centos:7
ENTRYPOINT ["cal"]
  • 1
  • 2
  1. 构建镜像 build

使用 Dockerfile5 构建镜像 mycal:4.0。

在这里插入图片描述

  1. 运行新建镜像

运行结果与 shell 方式的相同。

在这里插入图片描述

  1. ENTRYPOINT 不会被覆盖

运行结果会报错,系统认为 date 是 cal 的非法参数。

在这里插入图片描述

  1. 添加命令选项生效

与之前不同的是,这种情况下在 docker run 中添加的命令选项是有效的。

在这里插入图片描述

1.3.4.5 ENTRYPOINT 与 CMD 同用
  1. 创建 Dockerfile

在 dfs 目录中新建文件 Dockerfile6,并将如下内容复制到文件中。此时的 CMD 中给出的就是 ENTRYPOINT 的参数,注意不能是选项。

FROM centos:7
CMD ["hello world"]
ENTRYPOINT ["echo"]
  • 1
  • 2
  • 3
  1. 构建镜像 build

使用 Dockerfile6 构建镜像 myecho:latest。

在这里插入图片描述
在这里插入图片描述

  1. 运行新建镜像

在这里插入图片描述

  1. 添加命令选项生效

docker run -it myecho 命令后添加选项 > hello.log,用于将输出的内容重定向写入到 hello.log 文件中。选项生效。

在这里插入图片描述

  1. 覆盖 CMD 生效

docker run -it myecho 命令后指定新的参数,用于覆盖 CMD 中的参数,生效。

在这里插入图片描述

1.3.4.6 总结

Dockerfile 中的 [command] 或 [“EXECUTABLE”] 如果是通过 CMD 指定的,则该镜像的启动命令 docker run 中是不能添加参数 [ARG] 的。因为 Dockerfile 中的 CMD 是可以被命令中的 [COMMAND] 替代的。如果命令中的 IMAGE 后仍有内容,此时对于 docker daemon 来说,其首先认为是替代用的 [COMMAND],如果有两个或两个以上的内容,后面的内容才会认为是 [ARG]。所以,添加的 -y 会报错,因为没有-y 这样的[COMMAND]。

Dockerfile 中的 [command] 或 [“EXECUTABLE”] 如果是通过ENTRYPOINT 指定的,则该镜像的启动命令 docker run 中是可以添加参数 [ARG] 的。因为 Dockerfile 中的 ENTRYPOINT 是不能被命令中的 [COMMAND] 替代的。如果命令中的 IMAGE 后仍有内容,此时对于 docker daemon 来说,其只能是 [ARG]。

不过,docker daemon 对于 ENTRYPOINT 指定的 [command] 与 [“EXECUTABLE”] 的处理方式是不同的。如果是 [command] 指定的 shell,daemon 会直接运行,而不会与 docker run 中的 [ARG] 进行拼接后运行;如果是 [“EXECUTABLE”] 指定的命令,daemon 则会先与 docker run 中的[ARG]进行拼接,然后再运行拼接后的结果。

结论:无论是 CMD 还是 ENTRYPOINT,使用[“EXECUTABLE”]方式的通用性会更强些。

1.3.5 ADD与COPY指令

  1. 准备工作

在宿主机/root 目录中 mkdir 一个目录 ac。将事先下载好的任意某 tar.gz 包上传到 /root/ac 目录。本例在 zookeeper 官网

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/867171
推荐阅读
相关标签
  

闽ICP备14008679号