Dockerfile文件中主要关键字演示

导读

  • 在这边文章中,主要对Dockerfile里面的各个主要关键字进行解释并且进行演示,给自己做备忘录的同时,也分享给各位大家。

关键字

  • FROM

    • FROM关键字为Dockerfile开始的第一个指令,表明即将从后面的基础镜像开始进行构建。如果本地不存在该镜像,则会在docker.io镜像中进行pull。
    • 在一个Dockerfile文件中,可以有多个FROM关键字,有这个关键字则表明,接下来会创建出一个镜像,多个FROM在同一个Dockerfile文件中,主要的应用场景为,在第一个FROM中,通常会构建一个开发镜像,包含了编译源代码所需要的环境和软件,通常会比较大、在第二个FROM中,将在第一个FROM构建出来的镜像中,将里面编译好的程序直接拷贝出来进行直接部署。
    • 示例:
FROM centos:7 AS builder
LABEL maintainer="xiaojinran@foxmail.com"
RUN echo "Hello Docker!" > /tmp/result.log

FROM centos:7
COPY --from=builder /tmp/result.log /opt
  • ARG

    • ARG类似在编程语言中的定义的变量,他可以在其他关键字中被引用进行解析,但是在CMD关键字中无法被解析,这点需要注意,因为CMD关键字属于运行时,ARG的生命周期只有在构建镜像时,并且可以在docker build 时,通过指定–build-arg <varname>=<value>来改变或者赋予值
    • 示例:
FROM centos:7
LABEL maintainer="xiaojinran@foxmail.com"
ARG AUTHOR="XIAOJINRAN"
ARG VERSION=1.0
RUN echo "This is created by ${AUTHOR},current version is ${VERSION}"

输出结果

Step 1/5 : FROM centos:7
 ---> 5e35e350aded
Step 2/5 : LABEL maintainer="xiaojinran@foxmail.com"
 ---> Using cache
 ---> 8acea508f4f1
Step 3/5 : ARG AUTHOR="XIAOJINRAN"
 ---> Using cache
 ---> 100aecf8a646
Step 4/5 : ARG VERSION=1.0
 ---> Using cache
 ---> 23392ac7d722
Step 5/5 : RUN echo "This is created by ${AUTHOR},current version is ${VERSION}"
 ---> Running in 4ab41d6cd76a
This is created by XIAOJINRAN,current version is 1.0
Removing intermediate container 4ab41d6cd76a
 ---> 6d297ef2db60
Successfully built 6d297ef2db60
  • ENV

    • ENV跟上述的ARG很像,都是dockerfile的变量,不一样的是,ENV的作用范围比ARG要大得多,ENV在构建时和容器运行都有效,因此在CMD关键字中,是可以打印出ENV所定义的值,并且ENV定义的值可以被docker run命令所赋值或覆盖,在ENV变量较多的情况下,也经常用文件的方式进行集体的变量定义,在上述的示例中,可以将ARG关键字换成ENV,并不会有影响,唯一的影响在于不能在docker build 时,通过指定–build-arg <varname>=<value>来改变或者赋予值
    • 示例 :
FROM centos:7
LABEL maintainer="xiaojinran@foxmail.com"
ENV AUTHOR="XIAOJINRAN"
ENV VERSION=1.0
CMD echo "This is created by ${AUTHOR},current version is ${VERSION}"

输出结果

[docker@docker mytest]$  docker container run 04f9fb8782f8
This is created by XIAOJINRAN,current version is 1.0
  • 通过运行加载变量文件的方式,我们可以把环境变量进行传递到容器里面去,变量文件如下:
cat my.env 
AUTHOR="xiaojinran@foxmail.com"
VERSION=3.0
MSG="Hello Docker"
  • 运行容器
$ docker container run --env-file=my.env 04f9fb8782f8 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=f48ec377b710
AUTHOR="xiaojinran@foxmail.com"
VERSION=3.0
MSG="Hello Docker"
HOME=/root
  • CMD

    • CMD为在容器运行时需要执行的一条指令,如果该指令执行完成,则该容器就会停止。在每个生成镜像的代码段里,如果存在多条CMD指令,那么只会执行最后一条,并且可以被docker run后面的指令所覆盖
FROM centos:7
LABEL maintainer="xiaojinran@foxmail.com"
CMD echo "First"
CMD echo "Second"
CMD echo "Third"

输出结果

$ docker container run  4f4910f2cba5
Third

覆盖Dockerfile中的CMD

$ docker container run  4f4910f2cba5 echo "cover"
cover
  • ENTRYPOINT

    • ENTRYPOINT为容器运行的第一个入口,同CMD一样,在每个生成镜像的代码段里,如果存在多条ENTRYPOINT指令,那么只会执行最后一条,与CMD不同的是不能被docker run命令所覆盖,ENTRYPOINT不会被覆盖,而且是第一条被执行的指令。
    • 示例:
  FROM centos:7
LABEL maintainer="xiaojinran@foxmail.com"
ENTRYPOINT ["echo","Hello Docker"]

输出结果

$ docker container run 7f8c36642cb3 echo "Hello"
Hello Docker echo Hello
  • 这里有一点需要注意,如果我把ENTRYPOINT写成命令行模式,不为数组形式,则CMD的所有指令将被忽略掉,包括docker run传递进去的指令,意味着CMD都不会起作用
FROM centos:7
LABEL maintainer="xiaojinran@foxmail.com"
ENTRYPOINT echo "Hello:"

输出结果

$ docker container run 2c9f788529a9  "Docker"
Hello:
  • EXPOSE

    • EXPOSE为运行时容器需要曝露出来的端口,可以通过在docker run 时,指定-p来绑定宿主机端口,这个是在运行时有效,在构建时意义不是特别大
    • 示例:
FROM centos:7
LABEL maintainer="xiaojinran@foxmail.com"
EXPOSE 80
CMD sleep 30

容器运行时输出结果

$ docker container run -p 80 -d c22b7fb53471
7447580ff9dbf9a9189d575fdabdefe9a2fedbc98e913145e770d2114ff1339e
$ docker port 7447580ff9d
80/tcp -> 0.0.0.0:32771
  • VOLUME

    • VOLUME为容器运行时,指定的外部挂载卷,可以由多个容器和主机一起共享这个卷,数据写入不会影响镜像层。
    • 示例:
FROM centos:7
LABEL maintainer="xiaojinran@foxmail.com"
VOLUME /data
CMD echo "Hello,Docker!" >> /data/test.log

运行两个容器时的结果

$ docker container run -v /tmp:/data  902da181c405
$ docker container run -v /tmp:/data  902da181c405
$ cat /tmp/test.log 
Hello,Docker!
Hello,Docker!

可以看到,这个容器共享了同一个卷的同一个文件,这个在需要读取配置和写入持久化数据的场景下非常有用

  • WORKDIR

    • WORKDIR比较好理解,就是切换到某个目录,即使这个目录不存在也会自动创建,相当于执行了mkdir -p path/to/dir && cd path/to/dir
    • 示例:
FROM centos:7
LABEL maintainer="xiaojinran@foxmail.com"
WORKDIR /opt/my/path/can/be/anywhare
CMD pwd

容器运行结果

$ docker container run ff9149266b20
/opt/my/path/can/be/anywhare
  • COPY

    • COPY正如其英文释义,就是复制,而且这个复制是允许从宿主机拷贝到镜像当中去,并且支持通配符表达式,同时拷贝时是递归拷贝
FROM centos:7
LABEL maintainer="xiaojinran@foxmail.com"
COPY * /opt/hosted_files/
CMD ls -l /opt/hosted_files

容器运行结果

$ docker container run d26523f325f9
total 8
-rw-rw-r-- 1 root root 110 Jan 10 07:56 Dockerfile
-rw-rw-r-- 1 root root  63 Jan 10 06:37 my.env
drwxrwxr-x 2 root root  22 Jan 10 07:58 test

宿主机目录情况

$ ls -lrt
total 8
-rw-rw-r-- 1 docker docker  63 Jan 10 01:37 my.env
-rw-rw-r-- 1 docker docker 110 Jan 10 02:56 Dockerfile
drwxrwxr-x 3 docker docker  18 Jan 10 02:59 myfiles

可以看到,在容器里面,myfiles文件夹没有了,直接显示myfiles下面包含的内容信息,并且权限也发生了变化

  • ADD

    • ADD同COPY一样,也是可以从宿主机添加文件到镜像里面去,但是ADD更多的时候是添加压缩包文件,通过ADD添加的文件,如果为压缩包格式,那么ADD会执行解压操作
 FROM centos:7
LABEL maintainer="xiaojinran@foxmail.com"
ADD * /opt/hosted_files/
CMD ls -l /opt/hosted_files

容器运行结果

$ docker container run 8a9cadc209e0
total 8
-rw-rw-r-- 1 root root 109 Jan 10 08:06 Dockerfile
-rw-rw-r-- 1 1000  994  63 Jan 10 06:37 my.env
drwxrwxr-x 3 1000  994  18 Jan 10 07:59 myfiles

Dockerfile所在目录内容

$ ll
total 8
-rw-rw-r-- 1 docker docker 109 Jan 10 03:06 Dockerfile
-rw-rw-r-- 1 docker docker 280 Jan 10 03:07 my.tar.gz

可见,ADD指令并没有拷贝my.tar.gz这个文件,而是直接解压了放到了目标文件夹之中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值