容器技术之Dockerfile(一)
在前边的随笔中我们聊到了docker的基本命令,镜像,网络,存储卷以及基于现有容器制做docker镜像,相关随笔可参考https://www.cnblogs.com/qiuhom-1874/category/1766327.html;今天我们来聊一聊docker的另一个制作镜像的方式dockerfile;
什么是dockerfile?所谓dockerfile就是用来描述docker镜像制作过程的一指令文件;该文件是一个纯文本文件,docker Daemon 进程可以从该文件中读取指令,从而自动生成镜像;客户端可以使用docker bulid命令来指定dockerfile 所在目录,来生成以dockerfile里描述的镜像构建过程的镜像;
首先我们来了解下dockerfile的格式,dockerfile是一个纯文本文件,我们可以理解为构建镜像的源码;不同于其他编程语言,dockerfile里没有if else 没有循环,它里面仅仅有注释和构建镜像的指令;对于dockerfile注释就是以井号开头的行为注释,这个和shell和其他配置文件的语法一样;除此之外dockerfile里就只有指令了;严格的讲指令是不区分字符大小写的,通常我们约定俗成指令都是纯大写;除此之外在dockerfile的第一非注释行必须是FROM开头来明确的说明我们在基于那个镜像为基础镜像做镜像;
通常情况下dockerfile是放在一个目录下,该目录就是dockerfile的工作目录,我们在制作镜像所依赖的文件都必须放在该目录下,而dockerfile的名称也必须是Dockerfile(首字母大写,名称必须是Dockerfile),如果我们依赖的文件是一个目录下的部分文件,我们也可在dockerfile所在目录创建一个.dockerignore文件,把我们要忽略的文件名称写到里面即可,该文件支持通配符;
了解了上面的dockerfile的基本环境结构,接下来我们来说说dockerfile的指令的用法;
1、FROM:用于指定所创建镜像的基础镜像,如果本地不存在,默认会从dockerhub中下载;该指令是dockerfile里的第一个非注释行的指令;语法格式 FROM <repository>[:<tag>] 或者FROM <repository>@<digest> 其中repository是指定的base 镜像的名称 <tag>是base 镜像的标签为可选项,不指定标签默认表示使用指定镜像的latest版本;
2、MAINTAINER:用于指定维护者信息,dockerfile并不限制MAINTAINER指令可出现的位置,通常我们建议将该指令放在FROM之后;语法格式 MAINTAINER <authtor's detail>, <author's detail>可是任何文本信息,但约定俗成地使用作者名称及邮件地址;
示例:
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" [root@node1 test]#
提示:通常我们都不用MAINTAINER来指定作者信息,该指令几乎是废弃状态,建议使用LEBEL指令来指定;
3、LABEL:该指令用于指定添加镜像的元数据信息;语法格式为LABEL <key>=<value> <key>=<value> <key>=<value> ...;如果添加的元数据信息值中有空格,我们需要使用引号和反斜线进行命令行解析;
示例:
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." [root@node1 test]#
提示:LABEL指令可以使用多次,用于添加更多的元数据信息;
4、COPY:该指令用于从Docker主机复制文件至创建的镜像文件中;语法格式 COPY <src> ... <dest> 或 COPY ["<src>",... "<dest>"];<src>表示要复制的源文件或目录,支持使用通配符;<dest>表示目标路径,即正在创建的image的文件系统路径;建议为<dest>使用绝对路径,否则,COPY指定则以WORKDIR为其起始路径;注意:在路径中有空白字符时,通常使用第二种格式;
文件复制准则
1、<src>必须是Dockerfile所在目录中的文件,不能是其父目录中的文件;
2、如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制;
3、如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以“/”结尾;
4、如果<dest>事先不存在,它会被自动创建,则包括其父目录路径;
示例:
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." COPY html /var/www/html/ COPY test.html /tmp/ [root@node1 test]# tree . ├── Dockerfile ├── html │ ├── test1.html │ └── test2.html └── test.html 1 directory, 4 files [root@node1 test]#
测试:我们基于上面的Dockerfile构建镜像,看看构建好的镜像是否把对应文件都复制到对应目录下了?
[root@node1 test]# ls Dockerfile html test.html [root@node1 test]# pwd /root/test [root@node1 test]# docker build . -t myimg:v0.1 Sending build context to Docker daemon 5.632kB Step 1/6 : FROM busybox:latest latest: Pulling from library/busybox d9cbbca60e5f: Pull complete Digest: sha256:836945da1f3afe2cfff376d379852bbb82e0237cb2925d53a13f53d6e8a8c48c Status: Downloaded newer image for busybox:latest ---> 78096d0a5478 Step 2/6 : MAINTAINER "qiuhom <qiuhom@linux-1874.com>" ---> Running in c311afd3d522 Removing intermediate container c311afd3d522 ---> bf9b966a914b Step 3/6 : LABEL version="1.0" ---> Running in 2ffb577afa08 Removing intermediate container 2ffb577afa08 ---> 5dd2e4b3f594 Step 4/6 : LABEL description="this is test file \ that label-values can span multiple lines." ---> Running in 489165bad668 Removing intermediate container 489165bad668 ---> 994f06ff65f8 Step 5/6 : COPY html /var/www/html/ ---> f2b46094d9a9 Step 6/6 : COPY test.html /tmp/ ---> c78c7188f804 Successfully built c78c7188f804 Successfully tagged myimg:v0.1 [root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v0.1 c78c7188f804 8 seconds ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]#
提示:可以看到docker在读dockerfile时会把一条指令启动一容器来执行,然后每一条指令都会构建成一层镜像;如果我们本地仓库中没有我们指定的基础镜像,它默认会从dockerhub仓库中去把指定镜像拖到本地;docker build命令是用来基于dockerfile来制作镜像的命令,其中-t表示指定我们生成的镜像的标签信息;
运行我们刚才制作好的镜像,看看我们的指定的目录和文件是否都复制到指定镜像中的目录中去了?
[root@node1 test]# docker run --name test --rm -it myimg:v0.1 /bin/sh / # ls bin dev etc home proc root sys tmp usr var / # ls /var/www/html/ test1.html test2.html / # ls /tmp/ test.html / # cat /var/www/html/test1.html this is test1 html / # cat /var/www/html/test2.html this is test2 html / # cat /tmp/test.html this is test dir html / # exit [root@node1 test]#
提示:可以看到我们以刚才制作的镜像运行成容器,容器对应目录有我们指定复制的文件;
5、ADD:该指令类似于COPY指令,ADD支持使用TAR文件和URL路径;语法格式 ADD <src> ... <dest> 或 ADD ["<src>",... "<dest>"];如果<src>为URL且<dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<dest>;如果<dest>以/结尾,则URL指定的文件将被直接下载并保存为<dest>/<filename>;如果<src>是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于“tar -x”命令;然而,通过URL获取到的tar文件将不会自动展开;如果<src>有多个,或其间接或直接使用了通配符,则<dest>必须是一个以/结尾的目录路径;如果<dest>不以/结尾,则其被视作一个普通文件,<src>的内容将被直接写入到<dest>;
示例:
[root@node1 test]# ls Dockerfile html nginx-1.19.0.tar.gz test.html [root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." COPY html /var/www/html/ COPY test.html /tmp/ ADD http://nginx.org/download/nginx-1.18.0.tar.gz /usr/src/ ADD nginx-1.19.0.tar.gz /tmp/ [root@node1 test]#
提示:以上Dokcerfile里指定把当前目录下的nginx-1.19.0.tar.gz 添加到镜像中的/tmp/下,并且会把nginx-1.19.0.tar.gz展开成一个目录;而对于
ADD http://nginx.org/download/nginx-1.18.0.tar.gz /usr/src/这条指令它会把指定url的文件下载到/usr/src/,但是不会tar文件展开;
测试:把上面dockerfile编译成镜像,看看对应目录中的文件是否都展开了?
[root@node1 test]# docker build . -t myimg:v0.2 Sending build context to Docker daemon 1.05MB Step 1/8 : FROM busybox:latest ---> 78096d0a5478 Step 2/8 : MAINTAINER "qiuhom <qiuhom@linux-1874.com>" ---> Using cache ---> bf9b966a914b Step 3/8 : LABEL version="1.0" ---> Using cache ---> 5dd2e4b3f594 Step 4/8 : LABEL description="this is test file \ that label-values can span multiple lines." ---> Using cache ---> 994f06ff65f8 Step 5/8 : COPY html /var/www/html/ ---> Using cache ---> f2b46094d9a9 Step 6/8 : COPY test.html /tmp/ ---> Using cache ---> c78c7188f804 Step 7/8 : ADD http://nginx.org/download/nginx-1.18.0.tar.gz /usr/src/ Downloading 1.04MB/1.04MB ---> 23f47a028853 Step 8/8 : ADD nginx-1.19.0.tar.gz /tmp/ ---> 6ba2693b3084 Successfully built 6ba2693b3084 Successfully tagged myimg:v0.2 [root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v0.2 6ba2693b3084 27 seconds ago 8.54MB myimg v0.1 c78c7188f804 25 minutes ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker run --name test --rm -it myimg:v0.2 /bin/sh / # ls /usr/src/ nginx-1.18.0.tar.gz / # ls /tmp nginx-1.19.0 test.html / # exit [root@node1 test]#
提示:从上面的信息可以看到,在容器中的/usr/src/目录下nginx-1.18.0.tar.gz并没有展开,而在/tmp/下却把niginx-1.19.0.tar.gz展开为nginx-1.19.0;从build的过程来看,除开后面的ADD过程,其他过程都很快,并且明确告诉我们使用了cache,则意味着在本地仓库中有的镜像层,默认是共享的;
6、WORKDIR:该指令用于设定Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指令的工作目录;一个Dockerfile中可以多次使用WORKDIR来指定当前WORKDIR指令到下一个WORKDIR指令之间的指令的工作目录;语法格式WORKDIR <dirpath>;在Dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径,另外,WORKDIR也可调用由ENV指定定义的变量;
示例:
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." WORKDIR /var/www/ COPY html html/ COPY test.html /tmp/ WORKDIR /usr/ ADD http://nginx.org/download/nginx-1.18.0.tar.gz src/ ADD nginx-1.19.0.tar.gz /tmp/ [root@node1 test]#
提示:我们在dockerfile中指定了workdir的路径后,其后的指令就可以以上一个workdir指定的路径 为基准后面使用相对路径;
测试:制作镜像运行容器,看看是否把对应文件都添加到容器的指定目录里?
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." WORKDIR /var/www/ COPY html html/ COPY test.html /tmp/ WORKDIR /usr/ ADD http://nginx.org/download/nginx-1.18.0.tar.gz src/ ADD nginx-1.19.0.tar.gz /tmp/ [root@node1 test]# [root@node1 test]# docker build . -t myimg:v0.3 Sending build context to Docker daemon 1.05MB Step 1/10 : FROM busybox:latest ---> 78096d0a5478 Step 2/10 : MAINTAINER "qiuhom <qiuhom@linux-1874.com>" ---> Using cache ---> bf9b966a914b Step 3/10 : LABEL version="1.0" ---> Using cache ---> 5dd2e4b3f594 Step 4/10 : LABEL description="this is test file \ that label-values can span multiple lines." ---> Using cache ---> 994f06ff65f8 Step 5/10 : WORKDIR /var/www/ ---> Running in 623002a4c418 Removing intermediate container 623002a4c418 ---> 7e6898b36dd5 Step 6/10 : COPY html html/ ---> 57ff5a48a104 Step 7/10 : COPY test.html /tmp/ ---> f66a1bf4040a Step 8/10 : WORKDIR /usr/ ---> Running in b905ff1b4529 Removing intermediate container b905ff1b4529 ---> 1fdceb9a6bfd Step 9/10 : ADD http://nginx.org/download/nginx-1.18.0.tar.gz src/ Downloading 1.04MB/1.04MB ---> 92868df29f5b Step 10/10 : ADD nginx-1.19.0.tar.gz /tmp/ ---> 68161c3beb90 Successfully built 68161c3beb90 Successfully tagged myimg:v0.3 [root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v0.3 68161c3beb90 11 seconds ago 8.54MB myimg v0.2 6ba2693b3084 18 minutes ago 8.54MB myimg v0.1 c78c7188f804 43 minutes ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker run --name test --rm -it myimg:v0.3 /bin/sh /usr # pwd /usr /usr # ls sbin src /usr # ls src/ nginx-1.18.0.tar.gz /usr # ls /tmp/ nginx-1.19.0 test.html /usr # ls /var/www/ html /usr # exit [root@node1 test]#
提示:可以看到我们制作的镜像启动为容器后,默认是我们指定的最后一个workdir的路径;
示例:使用环境变量指定workdi的路径;
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." ENV webhome="/var/www/" src_home="/usr/" WORKDIR $webhome COPY html html/ COPY test.html /tmp/ WORKDIR $src_home ADD http://nginx.org/download/nginx-1.18.0.tar.gz src/ ADD nginx-1.19.0.tar.gz /tmp/ [root@node1 test]#
提示:我们在原有的Dockerfile中添加了ENV webhome="/var/www/" src_home="/usr/" 表示添加两个环境变量,而这两个环境的变量的值分别是“/var/www/” 和“/usr” 这样一来,在后面workdir引用该环境变量时 就会把对应的值给替换过去;dockerfile中变量引用同shell中的变量引用一样都是使用$符合引用变量;
测试:利用上面的Dockerfile编译成镜像,然后运行成容器,看看我们在dockerfile中定义的环境变量是否能够被容器所引用?
[root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v0.3 68161c3beb90 34 minutes ago 8.54MB myimg v0.2 6ba2693b3084 53 minutes ago 8.54MB myimg v0.1 c78c7188f804 About an hour ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker build . -t myimg:v0.4 Sending build context to Docker daemon 1.05MB Step 1/11 : FROM busybox:latest ---> 78096d0a5478 Step 2/11 : MAINTAINER "qiuhom <qiuhom@linux-1874.com>" ---> Using cache ---> bf9b966a914b Step 3/11 : LABEL version="1.0" ---> Using cache ---> 5dd2e4b3f594 Step 4/11 : LABEL description="this is test file \ that label-values can span multiple lines." ---> Using cache ---> 994f06ff65f8 Step 5/11 : ENV webhome="/var/www/" src_home="/usr/" ---> Running in 82738c50a595 Removing intermediate container 82738c50a595 ---> 9f089c14778f Step 6/11 : WORKDIR $webhome ---> Running in 3e9d7d4276bf Removing intermediate container 3e9d7d4276bf ---> 94e17268d7ea Step 7/11 : COPY html html/ ---> cf3be18998db Step 8/11 : COPY test.html /tmp/ ---> 3b81cb058412 Step 9/11 : WORKDIR $src_home ---> Running in 70478cb9d405 Removing intermediate container 70478cb9d405 ---> e0d8ab9331f4 Step 10/11 : ADD http://nginx.org/download/nginx-1.18.0.tar.gz src/ Downloading 1.04MB/1.04MB ---> b4e546989783 Step 11/11 : ADD nginx-1.19.0.tar.gz /tmp/ ---> df3d040b5766 Successfully built df3d040b5766 Successfully tagged myimg:v0.4 [root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v0.4 df3d040b5766 4 minutes ago 8.54MB myimg v0.3 68161c3beb90 41 minutes ago 8.54MB myimg v0.2 6ba2693b3084 59 minutes ago 8.54MB myimg v0.1 c78c7188f804 About an hour ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker run --name test --rm -it myimg:v0.4 /bin/sh /usr # pwd /usr /usr # ls /var/www/ html /usr # ls /usr/src/ nginx-1.18.0.tar.gz /usr #
提示:可以看到我们指定的ENV环境变量是能够被WORKDIR说引用
7、ENV:用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令(如ENV、ADD、COPY等)所调用;调用格式为$variable_name或${variable_name};语法格式ENV <key> <value> 或 ENV <key>=<value> ...;第一种格式中,<key>之后的所有内容均会被视作其<value>的组成部分,因此,一次只能设置一个变量;第二种格式可用一次设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<value>中包含空格,可以以反斜线(\)进行转义,也可通过对<value>加引号进行标识;另外,反斜线也可用于续行;定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能;
示例:
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." ENV web_home="/var/www/html/" COPY html ${web_home} [root@node1 test]#
提示:上面Dockerfile设置了环境变量web_home="/var/www/html" ,后面的COPY引用时直接使用${web_home}即可;COPY html ${web_home}表示把html目录中的文件复制到web_home这个变量所指定的目录中,即/var/www/html/;
测试:编译成镜像,看看是否把对应html目录下的文件复制到/var/www/html/目录下了?
[root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v0.4 df3d040b5766 17 minutes ago 8.54MB myimg v0.3 68161c3beb90 54 minutes ago 8.54MB myimg v0.2 6ba2693b3084 About an hour ago 8.54MB myimg v0.1 c78c7188f804 2 hours ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker build . -t myimg:v0.5 Sending build context to Docker daemon 1.05MB Step 1/6 : FROM busybox:latest ---> 78096d0a5478 Step 2/6 : MAINTAINER "qiuhom <qiuhom@linux-1874.com>" ---> Using cache ---> bf9b966a914b Step 3/6 : LABEL version="1.0" ---> Using cache ---> 5dd2e4b3f594 Step 4/6 : LABEL description="this is test file \ that label-values can span multiple lines." ---> Using cache ---> 994f06ff65f8 Step 5/6 : ENV web_home="/var/www/html/" ---> Running in 4c136d790dd0 Removing intermediate container 4c136d790dd0 ---> 90e193e4e810 Step 6/6 : COPY html ${web_home} ---> e21e9479b0a7 Successfully built e21e9479b0a7 Successfully tagged myimg:v0.5 [root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v0.5 e21e9479b0a7 4 seconds ago 1.22MB myimg v0.4 df3d040b5766 17 minutes ago 8.54MB myimg v0.3 68161c3beb90 54 minutes ago 8.54MB myimg v0.2 6ba2693b3084 About an hour ago 8.54MB myimg v0.1 c78c7188f804 2 hours ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker run --name test --rm -it myimg:v0.5 /bin/sh / # ls /var/www/html/ test1.html test2.html / # exit [root@node1 test]#
提示:可以看到我们打包的镜像运行成容器后,ENV指定的环境变量目录里有html目录下的所有文件;
8、ARG:该指令用于编译阶段可以使用docker build --build-arg向dockerfile里ARG 指定的变量传递值;语法格式ARG <name>[=<default value>];该指令可以在dockerfile中使用多次,也可以给定默认变量一个默认的值,在用户没有向该变量传递值的情况;
示例:
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." ARG web_home="/var/www/html/" COPY html ${web_home} [root@node1 test]#
提示:以上Dockerfile 指定了web_home变量的默认值是“/var/www/html/” 如果在我们build阶段没有使用--build-arg来向web_home传递值时,它默认就是“/var/www/html/”,如果我们使用了 --build-agr 指定web_home的值后,后面引用web_home变量的值就是我们用--build-arg传递给它的值;
测试:使用--build-arg向web_home传递值
[root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v0.5 e21e9479b0a7 14 minutes ago 1.22MB myimg v0.4 df3d040b5766 31 minutes ago 8.54MB myimg v0.3 68161c3beb90 About an hour ago 8.54MB myimg v0.2 6ba2693b3084 About an hour ago 8.54MB myimg v0.1 c78c7188f804 2 hours ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker build . --build-arg web_home="/usr/share/www/html/" -t myimg:v0.6 Sending build context to Docker daemon 1.05MB Step 1/6 : FROM busybox:latest ---> 78096d0a5478 Step 2/6 : MAINTAINER "qiuhom <qiuhom@linux-1874.com>" ---> Using cache ---> bf9b966a914b Step 3/6 : LABEL version="1.0" ---> Using cache ---> 5dd2e4b3f594 Step 4/6 : LABEL description="this is test file \ that label-values can span multiple lines." ---> Using cache ---> 994f06ff65f8 Step 5/6 : ARG web_home="/var/www/html/" ---> Running in d8697abf9206 Removing intermediate container d8697abf9206 ---> 6abb65dab341 Step 6/6 : COPY html ${web_home} ---> 385cba27c288 Successfully built 385cba27c288 Successfully tagged myimg:v0.6 [root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v0.6 385cba27c288 6 seconds ago 1.22MB myimg v0.5 e21e9479b0a7 15 minutes ago 1.22MB myimg v0.4 df3d040b5766 32 minutes ago 8.54MB myimg v0.3 68161c3beb90 About an hour ago 8.54MB myimg v0.2 6ba2693b3084 About an hour ago 8.54MB myimg v0.1 c78c7188f804 2 hours ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker run --name test --rm -it myimg:v0.6 /bin/sh / # ls /usr/share/www/html/ test1.html test2.html / # exit [root@node1 test]#
提示:可以看到我们传递进去的路径下有html目录下的两个网页文件;这说明通过--build-arg 选项可以向Dockerfile里ARG指定指定的变量传递值的;
示例:引用变量给定变量默认值
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." ARG web_home COPY html ${web_home:-"/data/htdoc/"} [root@node1 test]#
提示:引用变量给定变量默认值的方式同shell中的用法一样;${web_home:-"/data/htdoc/"} 表示如果web_home这个变量的值未设定或者为空时,就使用默认的值“/data/htdoc/”这个值,如果设置了,那么设置的是什么值就是什么值;
测试:不使用--build-arg向web_home传递值,看看web_home是否会拿到默认值?
[root@node1 test]# docker build . -t myimg:v0.7 Sending build context to Docker daemon 1.05MB Step 1/6 : FROM busybox:latest ---> 78096d0a5478 Step 2/6 : MAINTAINER "qiuhom <qiuhom@linux-1874.com>" ---> Using cache ---> bf9b966a914b Step 3/6 : LABEL version="1.0" ---> Using cache ---> 5dd2e4b3f594 Step 4/6 : LABEL description="this is test file \ that label-values can span multiple lines." ---> Using cache ---> 994f06ff65f8 Step 5/6 : ARG web_home ---> Running in 9d98f8e3a1f0 Removing intermediate container 9d98f8e3a1f0 ---> f164cc3e24ad Step 6/6 : COPY html ${web_home:-"/data/htdoc/"} ---> 4bedea2590b7 Successfully built 4bedea2590b7 Successfully tagged myimg:v0.7 [root@node1 test]# docker run --name test --rm -it myimg:v0.7 /bin/sh / # ls / bin data dev etc home proc root sys tmp usr var / # ls /data/ htdoc / # ls /data/htdoc/ test1.html test2.html / # exit [root@node1 test]#
提示:可以看到不想web_home传递值,默认就是使用我们给设定的默认值
测试:向web_home传递值,看看是否还会使用默认值呢?
[root@node1 test]# docker build . --build-arg web_home=/web/html/ -t myimg:v0.9 Sending build context to Docker daemon 1.05MB Step 1/6 : FROM busybox:latest ---> 78096d0a5478 Step 2/6 : MAINTAINER "qiuhom <qiuhom@linux-1874.com>" ---> Using cache ---> bf9b966a914b Step 3/6 : LABEL version="1.0" ---> Using cache ---> 5dd2e4b3f594 Step 4/6 : LABEL description="this is test file \ that label-values can span multiple lines." ---> Using cache ---> 994f06ff65f8 Step 5/6 : ARG web_home ---> Using cache ---> f164cc3e24ad Step 6/6 : COPY html ${web_home:-"/data/htdoc/"} ---> 4b6993911e6d Successfully built 4b6993911e6d Successfully tagged myimg:v0.9 [root@node1 test]# docker run --name test --rm -it myimg:v0.9 /bin/sh / # ls / bin dev etc home proc root sys tmp usr var web / # ls /web/ html / # ls /web/html/ test1.html test2.html / # exit [root@node1 test]#
提示:可以看到通过--build-arg传递了web_home的值为“/web/htm/”后,默认的“/data/htdoc/”的值就不会生效;
9、VOLUME:用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷;语法格式 VOLUME <mountpoint> 或 VOLUME ["<mountpoint>"];如果挂载点目录路径下此前的文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中;
示例:
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." ARG web_home COPY html ${web_home:-"/data/htdoc/"} VOLUME ${web_home:-"/data/htdoc/"} [root@node1 test]#
提示:volume是指定镜像里的挂载点,如果该挂载点里面原来是有文件存在,在使用docker run 时,用-v指定把宿主机上的某个目录挂载到该挂载点时,默认会把原来有的文件复制新挂载的卷中;这里还需要特被说一下,这里指定卷是在镜像内部创建一个挂载点,运行成容器还需要我们手动的用-v去指定把那个目录挂载到该挂载点,如果不指定默认就是docker-managed 类型的卷;
测试:编译成镜像,然后运行成容器,看看我们指定的卷宗的文件会不会被覆盖掉?是否会有文件存在?
[root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v0.9 4b6993911e6d 21 minutes ago 1.22MB myimg v0.7 4bedea2590b7 23 minutes ago 1.22MB myimg v0.6 385cba27c288 30 minutes ago 1.22MB myimg v0.5 e21e9479b0a7 46 minutes ago 1.22MB myimg v0.4 df3d040b5766 About an hour ago 8.54MB myimg v0.3 68161c3beb90 2 hours ago 8.54MB myimg v0.2 6ba2693b3084 2 hours ago 8.54MB myimg v0.1 c78c7188f804 2 hours ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker build . -t myimg:v1.0 Sending build context to Docker daemon 1.05MB Step 1/7 : FROM busybox:latest ---> 78096d0a5478 Step 2/7 : MAINTAINER "qiuhom <qiuhom@linux-1874.com>" ---> Using cache ---> bf9b966a914b Step 3/7 : LABEL version="1.0" ---> Using cache ---> 5dd2e4b3f594 Step 4/7 : LABEL description="this is test file \ that label-values can span multiple lines." ---> Using cache ---> 994f06ff65f8 Step 5/7 : ARG web_home ---> Using cache ---> f164cc3e24ad Step 6/7 : COPY html ${web_home:-"/data/htdoc/"} ---> Using cache ---> 4bedea2590b7 Step 7/7 : VOLUME ${web_home:-"/data/htdoc/"} ---> Running in 34cad9ca1f79 Removing intermediate container 34cad9ca1f79 ---> 9554284e4bba Successfully built 9554284e4bba Successfully tagged myimg:v1.0 [root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v1.0 9554284e4bba 2 minutes ago 1.22MB myimg v0.9 4b6993911e6d 24 minutes ago 1.22MB myimg v0.7 4bedea2590b7 26 minutes ago 1.22MB myimg v0.6 385cba27c288 33 minutes ago 1.22MB myimg v0.5 e21e9479b0a7 49 minutes ago 1.22MB myimg v0.4 df3d040b5766 About an hour ago 8.54MB myimg v0.3 68161c3beb90 2 hours ago 8.54MB myimg v0.2 6ba2693b3084 2 hours ago 8.54MB myimg v0.1 c78c7188f804 2 hours ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker run --name test --rm -it myimg:v1.0 /bin/sh / # ls / bin data dev etc home proc root sys tmp usr var / # ls /data/htdoc/ test1.html test2.html / # [root@node1 test]# [root@node1 test]# docker container inspect test -f {{.Mounts}} [{volume f3409b021267bd27d58c4b16fb1bc0dae77d4f92f7b5e6255f4ed26a6c27e459 /var/lib/docker/volumes/f3409b021267bd27d58c4b16fb1bc0dae77d4f92f7b5e6255f4ed26a6c27e459/_data /data/htdoc local true }] [root@node1 test]# ll /var/lib/docker/volumes/f3409b021267bd27d58c4b16fb1bc0dae77d4f92f7b5e6255f4ed26a6c27e459/_data total 8 -rw-r--r-- 1 root root 19 May 31 01:51 test1.html -rw-r--r-- 1 root root 19 May 31 01:51 test2.html [root@node1 test]#
提示:可以看到运行成容器后,默认会把我们指定卷挂载成docker-managed类型的卷;同时我们也看到了对应挂载点上目录会把原有文件复制到现volume中;
测试:手动指定宿主机目录挂载到挂载点,文件是否还会存在呢?
[root@node1 ~]# mkdir /work [root@node1 ~]# docker run --name test1 --rm -it -v /work:/data/htdoc/ myimg:v1.0 /bin/sh / # ls /data/htdoc/ / # [root@node1 ~]# ls /work/ [root@node1 ~]#
提示:手动指定挂载关系,它就不会把原有目录下的文件复制到现挂载目录中了;也就是说,人为手动指定挂载关系,宿主机上的的目录会覆盖容器内挂载点下的文件;只有docker自身管理的挂载的卷才会把原目录下的文件复制到现挂载目录里;
10、EXPOSE:用于为容器打开指定要监听的端口以实现与外部通信(暴露端口);语法格式 EXPOSE <port>[/<protocol>] [<port>[/<protocol>] ...]; <protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议;EXPOSE指令可一次指定多个端口;
示例:
[root@node1 test]# cat Dockerfile FROM busybox:latest MAINTAINER "qiuhom <qiuhom@linux-1874.com>" LABEL version="1.0" LABEL description="this is test file \ that label-values can span multiple lines." ARG web_home COPY html ${web_home:-"/data/htdoc/"} VOLUME ${web_home:-"/data/htdoc/"} EXPOSE 80/tcp 443/tcp [root@node1 test]#
提示:以上dockerfile中暴露了tcp的80和443端口;在dockerfile中使用EXPOSE暴露端口,在运行成容器时,如果不使用-P来暴露端口,容器里的端口还是暴露不出来;这里只是build阶段明确说明要暴露80和443,而运行成容器我们需要使用-P来把build暴露的端口暴露出来;
测试:运行时不使用-P暴露端口,看看是否能够把80和443暴露出来呢?
[root@node1 test]# docker build . -t myimg:v1.1 Sending build context to Docker daemon 1.05MB Step 1/8 : FROM busybox:latest ---> 78096d0a5478 Step 2/8 : MAINTAINER "qiuhom <qiuhom@linux-1874.com>" ---> Using cache ---> bf9b966a914b Step 3/8 : LABEL version="1.0" ---> Using cache ---> 5dd2e4b3f594 Step 4/8 : LABEL description="this is test file \ that label-values can span multiple lines." ---> Using cache ---> 994f06ff65f8 Step 5/8 : ARG web_home ---> Using cache ---> f164cc3e24ad Step 6/8 : COPY html ${web_home:-"/data/htdoc/"} ---> Using cache ---> 4bedea2590b7 Step 7/8 : VOLUME ${web_home:-"/data/htdoc/"} ---> Using cache ---> 9554284e4bba Step 8/8 : EXPOSE 80/tcp 443/tcp ---> Running in 8d7d5b4aab94 Removing intermediate container 8d7d5b4aab94 ---> 79c118ea9eb3 Successfully built 79c118ea9eb3 Successfully tagged myimg:v1.1 [root@node1 test]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE myimg v1.1 79c118ea9eb3 4 seconds ago 1.22MB myimg v1.0 9554284e4bba 24 minutes ago 1.22MB myimg v0.9 4b6993911e6d 46 minutes ago 1.22MB myimg v0.7 4bedea2590b7 48 minutes ago 1.22MB myimg v0.6 385cba27c288 55 minutes ago 1.22MB myimg v0.5 e21e9479b0a7 About an hour ago 1.22MB myimg v0.4 df3d040b5766 About an hour ago 8.54MB myimg v0.3 68161c3beb90 2 hours ago 8.54MB myimg v0.2 6ba2693b3084 2 hours ago 8.54MB myimg v0.1 c78c7188f804 3 hours ago 1.22MB busybox latest 78096d0a5478 2 weeks ago 1.22MB [root@node1 test]# docker run --name test --rm -it myimg:v1.0 /bin/sh / # [root@node1 test]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ca4cea9a6f58 myimg:v1.0 "/bin/sh" 15 seconds ago Up 15 seconds test [root@node1 test]# docker container port test [root@node1 test]#
提示:可以看到运行时,我们不使用-P来暴露端口是把容器内部端口暴露不出来的;
示例:使用-P来暴露dockerfile里定义的端口
[root@node1 test]# docker run --name test --rm -it -P myimg:v1.1 /bin/sh / # [root@node1 test]# docker container port test 443/tcp -> 0.0.0.0:32768 80/tcp -> 0.0.0.0:32769 [root@node1 test]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a78f6cebc0de myimg:v1.1 "/bin/sh" 19 seconds ago Up 19 seconds 0.0.0.0:32769->80/tcp, 0.0.0.0:32768->443/tcp test [root@node1 test]#
提示:可以看到使用-P就可以在运行时把build阶段定义的暴露端口全部给暴露出来;