利用Dockerfile文件执行docker build自动构建镜像

一、Dockerfile使用详解

1.1 Dockerfile介绍

        DockerFile是一种被Docker程序解释执行的脚本,由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像,相比手动制作镜像的方式,DockerFile更能直观的展示镜像是怎么产生的,有了DockerFile,当后期有额外的需求时,只要在之前的DockerFile添加或者修改响应的命令即可重新生成新的Docker镜像,避免了重复手动制作镜像的麻烦,类似于shell脚本一样,可以方便高效的制作镜像Docker守护程序 Dockerfile 逐一运行指令,如有必要,将每个指令的结果提交到新镜像,然后最终输出新镜像的ID。Docker守护程序将自动清理之前发送的上下文。

        请注意,每条指令都是独立运行的,并会导致创建新镜像,比如RUN cd /tmp对下一条指令不会有任何影响。

        Docker将尽可能重用中间镜像层(缓存),以显著加速docker build命令的执行过程,这由 Using cache控制台输出中的消息指示。

1.2 Dockerfile镜像制作和使用流程

1.3 Dockerfile文件的制作镜像的分层结构

1.4 Dockerfile文件格式

Dockerfile 是一个有特定语法格式的文本文件

dockerfile 官方说明: https://docs.docker.com/engine/reference/builder/

帮助: man 5 dockerfile

Dockerfile文件说明:

每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写

使用#作为注释

每一行只支持一条指令,每条指令可以携带多个参数

指令按文件的顺序从上至下进行执行

每个指令的执行会生成一个新的镜像层,为了减少dockerfile都按顺序执行,从头开始,已经执行过的指令已经缓存了,不需要再执行,如果后续有一行新的指令没执行过,其往后的指令将会重新执行,所以加速镜像制作,将最常变化的内容放在dockerfile的文件的后面。

二、 Dockerfile相关指令

相关指令:

FROM指定基础镜像
LABEL指定镜像元素
RUN执行shell命令
COPY复制文本
ADD制和解包文件
CMD容器启动命令
ENTRYPOINT入口点
ARG构建参数
VOLUME匿名卷
EXPOST暴露端口
WORKDIR指定工作目录
ONBUILD子镜像引用镜像的指令
USER指定当前用户
HEALTHCHECK健康检查
STOPSIGNAL退出容器的信号
SHELL指定shell
dockerignore文件

这里我们对以下命令进行验证:

FROM,LABEL,RUN,ENV,COPY,ADD,CMD,ENTRYPOINT,VOLUME,EXPOSE,WORKDIR

大小写都可以,一般都是大写

2.1 FROM

定制镜像,需要先有一个基础镜像,在这个基础镜像上进行定制。

        FROM就是指定基础镜像,此指令通常必须放在Dockerfile文件第一个非注释行。后续的指令都是运行于此基础准镜像所提供的运行环境基础镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找制定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件,如果找不到指定的镜像文件,则会返回一个错误信息。

如何选择合适的镜像呢?

        对于不同的软件官方都提供了相关的docker镜像,比如: nginx、redis、mysql、httpd、tomcat等服务类的镜像,也有操作系统类,如: centos、ubuntu、debian等。建议使用官方镜像,比较安全。

格式:

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]


#说明:  
--platform 指定镜像的平台,比如: linux/amd64, linux/arm64, or windows/amd64
tag 和 digest是可选项,如果不指定,默认为latest。

2.2 LABEL

LABEL:说明信息

可以指定镜像元数据,如:镜像作者等。

LABEL <key>=<value> <key>=<value> <key>=<value> ...

"Labels": {
    "com.example.vendor": "ACME Incorporated"
    "com.example.label-with-value": "foo",
    "version": "1.0",
    "description": "This text illustrates that label-values can span multiple lines.",
    "multi.label1": "value1",
    "multi.label2": "value2",
    "other": "value3"
}

2.3 RUN

RUN 指令用来在构建镜像阶段需要执行 FROM 指定镜像所支持的Shell命令。

通常各种基础镜像一般都支持丰富的shell命令

注意: RUN 可以写多个,每一个RUN指令都会建立一个镜像层,所以尽可能合并成一条指令,比如将多个shell命令通过 && 连接一起成为在一条指令

每个RUN都是独立运行的,和前一个RUN无关

#shell 格式: 相当于 /bin/sh -c <命令> 此种形式支持环境变量
RUN <命令> 
#exec 格式: 此种形式不支持环境变量,注意:是双引号,不能是单引号
RUN ["可执行文件", "参数1", "参数2"]
#exec格式可以指定其它shell
RUN ["/bin/bash","-c","echo hello wang"]

我们创建一个目录:

[root@Node2 ~]#:mkdir /data/docker/dockerfile/system/ -p

进到这个目录下:创建一个Dockerfile文件。

运行一条命令:在根下创建一个文件test.txt。文件内容为test:

[root@Node2 ~]#:cd  /data/docker/dockerfile/system/
[root@Node2 system]#:vim Dockerfile
FROM centos
LABEL author="docker cloud" \
	version="1.0"

RUN echo "test" > /test.txt

这里:文件名只能叫Dockerfile。区分大小写字母!并且只能在当前路径下执行。

在当前文件夹下,构建镜像:

docker build -t centos:v1 .

这样就构建了一个镜像:centos:v1。可以进入镜像,有了一个我们自己创建的文件:/test.txt。

进入镜像,查看验证:

多个 RUN 命令和shell命令不同,多个RUN是独立无关的。比如上一行的RUN是cd /etc/。下一行的RUN是touch 123。则不会在/etc/下创建文件123的。123会创建在根下。两个RUN是独立的。

例子:修改Dockerfile。构建镜像:centos:v2

运行容器,进入查看:123是否在/etc/下还是/下:

可以发现123文件是在/下。并不在/etc/下。

如果想在/etc/下创建文件(夹)

可以写在一行上,RUN cd /etc/ && touch 123

这样就在/etc/下创建了123文件夹

[root@Node2 system]#:cat Dockerfile 
FROM centos
LABEL author="docker cloud" \
	version="1.0"
RUN cd /etc/ && touch 123
[root@Node2 system]#:docker build -t centos:v3 .
......
#查看镜像
[root@Node2 system]#:docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
centos                v3        5005bf4b61a4   5 seconds ago    231MB
centos                v2        afc36b7672c2   16 minutes ago   231MB
......
#运行容器,查看根下不存在123文件,是在/etc/下了。
[root@Node2 system]#:docker run -it 500 bash
[root@00f6cf384624 /]# ls
bin  etc   lib	  lost+found  mnt  proc  run   srv  tmp  var
dev  home  lib64  media       opt  root  sbin  sys  usr
[root@00f6cf384624 /]# cd /etc/
[root@00f6cf384624 etc]# ls 123
123

2.4 ENV

ENV 可以定义环境变量和值,会被后续指令(如:ENV,ADD,COPY,RUN等)通过$KEY或${KEY}进行引用,并在容器运行时保持。

#变量赋值格式1
ENV <key> <value>   #此格式只能对一个key赋值,<key>之后的所有内容均会被视作其<value>的组成
部分
#变量赋值格式2
ENV <key1>=<value1> <key2>=<value2> \  #此格式可以支持多个key赋值,定义多个变量建议使用,减少镜像层
 <key3>=<value3> ...
 
#如果<value>中包含空格,可以以反斜线\进行转义,也可通过对<value>加引号进行标识;另外,反斜线也
可用于续行
#只使用一次变量
RUN <key>=<value> <command>
    
#引用变量
RUN $key .....
#变量支持高级赋值格式
${key:-word}
${kye:+word}

Dockerfile文件:

[root@Node2 system]#:vim Dockerfile 
[root@Node2 system]#:cat Dockerfile 
FROM centos
LABEL author="docker cloud" \
	version="1.0"
ENV    name=cxk    class=yun
RUN    touch  ${name}.txt

构建镜像,并运行该镜像:进入查看是否创建了cxk.txt文件:

[root@Node2 system]#:docker build -t centos:v3 .
[+] Building 0.5s (6/6) FINISHED                                                    docker:default
 => [internal] load build definition from Dockerfile                                          0.0s
 => => transferring dockerfile: 206B                                                          0.0s
 => [internal] load metadata for docker.io/library/centos:latest                              0.0s
 => [internal] load .dockerignore                                                             0.0s
 => => transferring context: 2B                                                               0.0s
 => CACHED [1/2] FROM docker.io/library/centos:latest                                         0.0s
 => [2/2] RUN    touch  cxk.txt                                                               0.4s
 => exporting to image                                                                        0.0s
 => => exporting layers                                                                       0.0s
 => => writing image sha256:28925936639bf4d10e552a082d5bdea285faaf7b97644e4ef89ab5d850a69958  0.0s
 => => naming to docker.io/library/centos:v3                                                  0.0s
[root@Node2 system]#:docker run -it centos:v3 bash
[root@c231d5ca5d0c /]# ls
bin	 dev  home  lib64	media  opt   root  sbin  sys  usr
cxk.txt  etc  lib   lost+found	mnt    proc  run   srv	 tmp  var
[root@c231d5ca5d0c /]# echo $name
cxk
[root@c231d5ca5d0c /]# echo $class
yun

2.5 COPY

复制本地宿主机的,到容器中:

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] #路径中有空白字符时,建议使用此格式

说明:

1.可以是多个,可以使用通配符,通配符规则满足GO的filepath.Match规则和filepath.Match。

参考链接: https://golang.org/pkg/path/filepath/#Match

2.必须是build上下文中的路径,就是Dockerfile所在的目录的相对路径,不能是其父目录中的文件

3.如果是目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制

4.如果指定了多个,或在中使用了通配符,则必须是一个目录,且必须以/结尾。虽然不报错,效果不一样了,不加/类似于改名

5.可以是绝对路径或者WORKDIR指定的相对路径

6.使用COPY指令,源文件的各种元数据都会报错。比如读、写、执行权限、文件变更时间等。

7.如果事先不存在,它将会被自动创建,这包括其父目录路径,即递归创建目录。

例子:

wget http://mirrors.aliyun.com/repo/centos-7.repo
COPY hom* /mydir/    
COPY hom?.txt /mydir/

演示:

[root@Node2 system]#:touch index.html    #在宿主机当前目录下,创建文件index.html
[root@Node2 system]#:ls
Dockerfile  index.html
[root@Node2 system]#:vim Dockerfile     #修改Dockerfile文件
[root@Node2 system]#:cat Dockerfile 
FROM centos
LABEL author="docker cloud" \
	version="1.0"    
RUN useradd lisi                    #创建一个用户
COPY --chown=lisi:lisi index.html /data/                #使用copy,将宿主机路径下该文件复制到容器中的/data/目录下。
容器中这个/data/目录如果没有,会自动创建的。

构建镜像,并运行容器,进入查看是否有/data/目录,并且宿主机的index.html文件是否复制在了/data/下,并且权限为lisi。

[root@Node2 system]#:docker build -t centos:v4 .
[+] Building 0.1s (8/8) FINISHED                                                    docker:default
 => [internal] load build definition from Dockerfile                                          0.0s
 => => transferring dockerfile: 209B                                                          0.0s
 => [internal] load metadata for docker.io/library/centos:latest                              0.0s
 => [internal] load .dockerignore                                                             0.0s
 => => transferring context: 2B                                                               0.0s
 => [internal] load build context                                                             0.0s
 => => transferring context: 86B                                                              0.0s
 => [1/3] FROM docker.io/library/centos:latest                                                0.0s
 => CACHED [2/3] RUN useradd lisi                                                             0.0s
 => [3/3] COPY --chown=lisi:lisi index.html /data/                                            0.0s
 => exporting to image                                                                        0.0s
 => => exporting layers                                                                       0.0s
 => => writing image sha256:bd9fb326b5234baa6067c0ee7c81558c545f93ad72dc22d1f31d7d64dfc7a0c3  0.0s
 => => naming to docker.io/library/centos:v4                                                  0.0s
[root@Node2 system]#:docker run --rm -it centos:v4 bash
[root@df300b39c30e /]# ls -l /data/
total 0
-rw-r--r--. 1 lisi lisi 0 Aug  2 16:33 index.html
[root@df300b39c30e /]# 

关于复制到容器中,后面加不加/的问题:

 

[root@Node2 system]#:cat Dockerfile
FROM centos:centos7.9.2009
LABEL author="dockerfile cloud" \
	version="1.0"
COPY index.html /data/                #复制到容器中,这里加/也就是:/data/
#构建镜像
[root@Node2 system]#:docker build -t c7:v1 .
[+] Building 0.1s (7/7) FINISHED                                                    docker:default
 => [internal] load build definition from Dockerfile                                          0.0s
 => => transferring dockerfile: 193B                                                          0.0s
 => [internal] load metadata for docker.io/library/centos:centos7.9.2009                      0.0s
 => [internal] load .dockerignore                                                             0.0s
 => => transferring context: 2B                                                               0.0s
 => [internal] load build context                                                             0.0s
 => => transferring context: 112B                                                             0.0s
 => CACHED [1/2] FROM docker.io/library/centos:centos7.9.2009                                 0.0s
 => [2/2] COPY index.html /data/                                                              0.0s
 => exporting to image                                                                        0.0s
 => => exporting layers                                                                       0.0s
 => => writing image sha256:0b4fc12ae8f837c5b6bfc9de5867f53c1b77664b8c218bb7d7f18f6d7f645905  0.0s
 => => naming to docker.io/library/c7:v1                                                      0.0s
#进入容器:
[root@Node2 system]#:docker run -it c7:v1 bash
[root@d37bb6e78069 /]# ls
anaconda-post.log  data  etc   lib    media  opt   root  sbin  sys  usr
bin                dev   home  lib64  mnt    proc  run   srv   tmp  var
[root@d37bb6e78069 /]# ls data        #那么就把index.html复制到了/data/文件夹下。
index.html
[root@d37bb6e78069 /]# cat data/index.html 
nginx port EXPOSE
[root@d37bb6e78069 /]# 
[root@d37bb6e78069 /]# 
[root@d37bb6e78069 /]# exit
exit
[root@Node2 system]#:
[root@Node2 system]#:cat Dockerfile
FROM centos:centos7.9.2009
LABEL author="dockerfile cloud" \
	version="1.0"
COPY index.html /data            #复制到容器中,这里不加/也就是:/data
#构建镜像:
[root@Node2 system]#:docker build -t c7:v2 .
[+] Building 0.1s (7/7) FINISHED                                                    docker:default
 => [internal] load build definition from Dockerfile                                          0.0s
 => => transferring dockerfile: 192B                                                          0.0s
 => [internal] load metadata for docker.io/library/centos:centos7.9.2009                      0.0s
 => [internal] load .dockerignore                                                             0.0s
 => => transferring context: 2B                                                               0.0s
 => [internal] load build context                                                             0.0s
 => => transferring context: 88B                                                              0.0s
 => CACHED [1/2] FROM docker.io/library/centos:centos7.9.2009                                 0.0s
 => [2/2] COPY index.html /data                                                               0.0s
 => exporting to image                                                                        0.0s
 => => exporting layers                                                                       0.0s
 => => writing image sha256:ee778f72054089fb5ffca94ed0ce9f289e3809667a85bbde4d34e9c5d49bb6b1  0.0s
 => => naming to docker.io/library/c7:v2                                                      0.0s
#运行容器:进入
[root@Node2 system]#:docker run -it c7:v2 bash
[root@4ea5ed32c30c /]# ls
anaconda-post.log  data  etc   lib    media  opt   root  sbin  sys  usr
bin                dev   home  lib64  mnt    proc  run   srv   tmp  var
[root@4ea5ed32c30c /]# cat data         #这里的data是文件,相当于把index.html复制进来改名为data了
nginx port EXPOSE

2.6 ADD

        该命令可认为是增强版的COPY,不仅支持COPY,还支持自动解缩。可以将复制指定的 到容器中的。

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

说明:

  • 可以是Dockerfile所在目录的一个相对路径;也可是一个 URL;还可是一个 tar 文件(自动解压)

  • 可以是绝对路径或者是 WORKDIR 指定的相对路径

  • 如果是目录,只复制目录中的内容,而非目录本身

  • 如果是一个 URL ,下载后的文件权限自动设置为 600

  • 如果为URL且不以/结尾,则指定的文件将被下载并直接被创建为,如果以 / 结尾,则文件名URL指定的文件将被直接下载并保存为/< filename>

  • 如果是一个本地文件系统上的打包文件,如: gz, bz2 ,xz ,它将被解包 ,其行为类似于"tar -x"命令,但是通过URL获取到的tar文件将不会自动展开

  • 如果有多个,或其间接或直接使用了通配符,则必须是一个以/结尾的目录路径;如果不以/结尾,则其被视作一个普通文件,的内容将被直接写入到

示例:

ADD test relativeDir/          # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir/         # adds "test" to /absoluteDir/
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /

我们准备一个清华源的文件qh.repo

将容器中的/etc/yum.repos.d/下的repo文件删除,将该qh.repo文件通过ADD的方式添加到指定路径下:

Dockerfile文件如下:

构建镜像:

运行容器:查看是否有qh.repo

2.7 CMD

        一个容器中需要持续运行的进程一般只有一个,CMD 用来指定启动容器时默认执行的一个命令,且其运行结束后,容器也会停止,所以一般CMD 指定的命令为持续运行且为前台命令。

如果docker run没有指定任何的执行命令或者dockerfile里面也没有entrypoint,那么开启容器后就会使执行CMD指定的默认的命令

前面介绍过的RUN命令是在构建镜像执行的命令,注意二者的不同之处

每个dockerfile只能有一条CMD命令,如指定了多条,只有最后一个被执行

如果用户启动容器时用docker run xxx指定运行的命令,则会覆盖CMD指定的命令

# 使用 exec 执行,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量
CMD ["executable","param1","param2"] 

# 在 /bin/sh 中执行,提供给需要交互的应用;此种形式支持环境变量
CMD command param1 param2 


# 提供给 ENTRYPOINT 命令的默认参数
CMD ["param1","param2"]

范例:

CMD ["nginx", "-g", "daemon off;"]

repo源下载在本地:

wget http://mirrors.aliyun.com/repo/Centos-8.repo

wget http://mirrors.aliyun.com/repo/Centos-7.repo

构建镜像:

 由于构建的镜像中CMD命令是前台运行的命令。所以运行系统类容器时,依旧是启动状态:

另一种用法:

现拉取一个centos:centos7.9.2009

[root@Node2 system]#:vim Dockerfile 
FROM centos:centos7.9.2009
LABEL author="dockerfile cloud" \
	version="1.0"

RUN rm -rf /etc/yum.repos.d/*        #删除所有yum源
COPY epel-7.repo /etc/yum.repos.d/    #将本地的epel源复制进容器的yum中
ADD qh.repo /etc/yum.repos.d/        #清华源
RUN yum install -y epel-release.noarch    #下载epel源
RUN yum install -y nginx                    #yum安装nginx
ADD nginx-1.18.0.tar.gz /usr/local/src        #将本地的nginx源码包复制进去
COPY index.html /usr/share/nginx/html        #首页
CMD ["nginx","-g","daemon off;"]            

写一个主页,并且构建镜像:

后台启动:

[root@Node2 system]#:docker run -d --name cn -p 80:80 c7:v1
2991e1f182a645bf3e2090254dcfc373c38a0a521a708ac8c606b8eb58416c3b

验证:可以看到,我们指定了宿主机与容器的端口。访问宿主机的IP端口默认80。

2.8 ENTRYPOINT

功能类似于CMD,配置容器启动后执行的命令及参数

# 使用 exec 执行
ENTRYPOINT ["executable", "param1", "param2"]

# shell中执行
ENTRYPOINT command param1 param2

ENTRYPOINT不能被docker run提供的参数覆盖,而是追加,即如果docker run命令有参数,那么参数全部都会作为ENTRYPOINT的参数。

如果docker run后面没有额外参数,但是dockerfile中的CMD里有(即上面CMD的第三种用法),即Dockerfile中既有CMD也有ENTRYPOINT,那么CMD的全部内容会作为ENTRYPOINT的参数。

如果docker run 后面有额外参数,同时Dockerfile中即有CMD也有ENTRYPOINT,那么docker run后面的参数覆盖掉CMD参数内容,最终作为ENTRYPOINT的参数。

可以通过docker run --entrypoint string 参数在运行时替换,注意string不要加空格

使用CMD要在运行时重新写命令本身,然后在后面才能追加运行参数,ENTRYPOINT则可以运行时无需重写命令就可以直接接受新参数

每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个生效。

例子:编译安装nginx:

[root@Node2 system]#:ls
Centos-7.repo  Centos-8.repo  Dockerfile  epel-7.repo  index.html  nginx-1.18.0.tar.gz  qh.repo

Dockerfile文件:

[root@Node2 system]#:cat Dockerfile 
FROM centos:centos7.9.2009
LABEL author="dockerfile cloud" \
	version="1.0"

RUN rm -rf /etc/yum.repos.d/
COPY epel-7.repo /etc/yum.repos.d/        #通过下载到本地:wget https://mirrors.aliyun.com/repo/epel-7.repo
ADD qh.repo /etc/yum.repos.d/

RUN yum -y install gcc gcc-c++ make automake pcre pcre-devel zlib zlib-devel openssl openssl-devel wget
ADD nginx-1.18.0.tar.gz /usr/local/src        #准备nginx源码包到本地,ADD可以支持解压包
RUN cd /usr/local/src/nginx-1.18.0 && ./configure --prefix=/apps/nginx && make && make install
COPY index.html /apps/nginx/html        #我们在本地准备的index.html文件
CMD ["-g","daemon off;"]
ENTRYPOINT ["/apps/nginx/sbin/nginx"]    #CMD会不在

构建镜像:docker build -t c7:v3 .

启动容器:

docker run -d -p 80:80 --name centnginx c7:v3

这里c7:v3是镜像,后面不跟参数,那么ENTRYPOING会使用CMD中的命令,作为参数。放在ENTRYPOINT的后面执行。也就是:/apps/nginx/sbin/nginx -g daemon off

2.9 VOLUME

        在容器中创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等,一般会将宿主机上的目录挂载至VOLUME 指令指定的容器目录。即使容器后期被删除,此宿主机的目录仍会保留,从而实现容器数据的持久保存。

宿主机目录为:/var/lib/docker/volumes/<volume_id>/_data

语法:

vOLUME <容器内路径>
VOLUME ["<容器内路径1>", "<容器内路径2>"...]

注意:

Dockerfile中的VOLUME实现的是匿名数据卷,无法指定宿主机路径和容器目录的挂载关系

通过docker rm -fv <容器ID> 可以删除容器的同时删除VOLUME指定的卷

示例:在容器创建两个/data1/和/data2/的挂载点

Dockerfile文件:

[root@Node2 system]#:cat Dockerfile 
FROM centos:centos7.9.2009
LABEL author="dockerfile cloud" \
	version="1.0"
VOLUME ["/data1/","/data2/"]

构建镜像:

 运行容器:发现在根下自动创建了两个文件夹/data1/和/data2/

在/data1/下创建一个文件123321

开一个终端查看宿主机:那么在宿主机也会有一个123321的文件:

同理我们也可以在宿主机创建一个文件夹root_Node2。看是否在容器中/data1/下也创建了该文件夹。

[root@Node2 ~]#:mkdir /var/lib/docker/volumes/efb1be01ff17e52521e07bc175a9c444e5bbed1e42af49f7797e5e30cd940b39/_data/root_Node2

 那么在容器中也有了该文件夹。

总结:VOLUME会在宿主机中挂载上容器中的指定目录,但宿主机中的挂载点不是我们决定的。一般默认在/var/lib/docker/volumes/<volume_id>/_data/下。

2.10 EXPOSE

        指定服务端的容器需要对外暴露(监听)的端口号,以实现容器与外部通信。EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会真正暴露端口,即不会自动在宿主进行端口映射因此,在启动容器时需要通过 -P 或-p ,Docker 主机才会真正分配一个端口转发到指定暴露的端口才可使用。

 注意:即使Dockerfile没有EXPOSE 端口指令,也可以通过docker run -p临时暴露容器内程序真正监听的端口,所以EXPOSE 相当于指定默认的暴露端口,可以通过docker run -P 进行真正暴露。

EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>] ..]
    
#说明
<protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议

示例:

EXPOSE 80 443
EXPOSE 11211/udp 11211/tcp

编译安装nginx,暴露端口:

[root@Node2 system]#:cat Dockerfile 
FROM centos:centos7.9.2009
LABEL author="dockerfile cloud" \
	version="1.0"

RUN rm -rf /etc/yum.repos.d/
COPY epel-7.repo /etc/yum.repos.d/
ADD qh.repo /etc/yum.repos.d/

RUN yum -y install gcc gcc-c++ make automake pcre pcre-devel zlib  zlib-devel openssl openssl-devel wget
ADD nginx-1.18.0.tar.gz /usr/local/src
RUN cd /usr/local/src/nginx-1.18.0 && ./configure --prefix=/apps/nginx && make && make install
VOLUME ["/apps/nginx/html"]
COPY index.html /apps/nginx/html
CMD ["-g","daemon off;"]
EXPOSE 80 443
ENTRYPOINT ["/apps/nginx/sbin/nginx"]

[root@Node2 system]#:echo "nginx port EXPOSE" > index.html

构建镜像:

 

那么在本机的路径下的文件:通过查看容器详细信息:docker inspect web1查看容器中的/apps/nginx/html/对应在宿主机的哪个路径。过滤出一个叫Source的一行:

可以看到这个index.html就是容器中nginx的主页

这样就通过暴露端口的方式,找到本机的哪个端口。也可以在宿主机修改主页文件,而不必进入容器中了。

在删除容器时如果指定-v选项。那么宿主机的这个文件夹也一并删除了。

2.11 WORKDIR

        为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录。

        WORKDIR 指定工作目录(或称当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会自行创建。

WORKDIR /path/to/workdir

范例:

#两次RUN独立运行,不在同一个目录,
RUN cd /app
RUN echo "hello" > world.txt


#如果想实现相同目录可以使用WORKDIR
WORKDIR /app
RUN echo "hello" > world.txt

可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

则最终路径为 /a/b/c

验证:

Dockerfile文件:

[root@Node2 system]#:cat Dockerfile 
FROM centos:centos7.9.2009
LABEL author="dockerfile cloud" \
	version="1.0"

WORKDIR /data/
RUN touch a.txt
CMD ["tail","-f","/etc/hosts"]

构建镜像:

运行容器:进入查看:

这样我们touch a.txt创建的文件就在指定的/data/下了。WORKDIR指定文件目录。

---end---

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值