Dockerfile关键词实验演示:
理解构建上下文(build context)
- Docker镜像通过docker build指令构建,该指令执行时当前的工作目录就是docker构建的上下文,即build context,上下文中的文件及目录都会作为构建上下文内容发送给Docker Daemon。
用缓存镜像提高效率
FROM(指定基础镜像 image)
作用:必须放在第一行,一个dockerfile中只能有一个FROM关键字
FROM指定基础镜像,每一个定制镜像,必须以一个现有镜像为基础。因此一个Dockerfile中FROM是必须的指令,并且必须是第一条。后续的指令都依赖于该指令指定的 image。FROM 指令指定的基础 image 可以是官方远程仓库中的,也可以位于本地仓库
使用格式:
FROM <image>:<tag> # 注释以#开头。基础镜像的tag可不指定,默认使用latest # 示例:
FROM mysql:5.7
FROM centos:7.2
FROM centos
MAINTAINER(maintainer用来指定镜像创建者信息)
作用:指定镜像的作者信息,包含镜像的所有者和联系人信息
构建指令,用于将 image 的制作者相关的信息写入到 image 中。当我们对该 image 执行 docker inspect 命令时,输出中有相应的字段记录该信息。
使用格式:
常见格式:MAINTAINER 用户名 邮箱
MAINTAINER wangyang "wangyang@itxdl.cn"
LABEL(将元数据添加到镜像:比如说制作时间,镜像版本,著作者信息)
作用:
为镜像添加label以方便组织镜像,记录元数据信息,帮助自动化实现等等。字符串中包含空格需要转义或包含在引号中
使用格式:
LABEL(关键字) key=valule 的格式(如果值中间有空格比较奇怪的,用双引号隔起来,表示是一整个字符串)
# 指令将元数据添加到镜像。`LABEL` 是键值对。要在 `LABEL` 值中包含空格,请像在命令行中一样使用引号和反斜杠
方法一:每一个键值对对应一个关键字
# Set one or more individual labels
LABEL com.example.version="0.0.1-beta"
LABEL vendor1="ACME Incorporated"
LABEL com.example.release-date="2019-09-12"
LABEL com.example.version.is-production=""
方法二:一个关键字,后面跟键值对,键值对之间使用空格隔开
# Set multiple labels on one line
LABEL com.example.version="0.0.1-beta" com.example.release-date="2019-09-12"
方法三:多行标签定义方式,使用换行符书写,一个关键字对应
# Set multiple labels at once, using line-continuation characters to break long lines
LABEL vendor=ACME Incorporated
com.example.is-beta=
com.example.is-production=""
com.example.version="0.0.1-beta"
com.example.release-date="2019-09-12"
标签的继承性和重写性(后面覆盖前面)
- 基础或父镜像(`FROM` 行中的镜像)中包含的标签由您的镜像继承。
- 如果标签已经存在但具有不同的值,则最近应用的值将覆盖任何先前设置的值
- 查看镜像标签格式
docker image inspect --format='' myimage
添加一个标签
mkdir test1
cd test1/
vim Dockerfile
FROM busybox
LABEL author=zhujiantang
将文件制作为镜像(在dockfile文件当前目录执行)
docker build -t zjt:v1 . --no-cache
安装 jq
yum install epel-release
yum install jq
查看标签:从当前找Dockerfile剧本文件创建镜像名为zjt
docker image inspect zjt:v1 --format "{{json .ContainerConfig.Labels}}" | jq
验证标签的继承性
添加一个标签
cd test1/
vim Dockerfile
FROM zjt:v1
LABEL version=v2
将文件制作为镜像(在dockfile文件当前目录执行)
docker build -t zjt:v2 . --no-cache
查看标签:从当前找Dockerfile剧本文件创建镜像名为zjt
docker image inspect zjt:v2 --format "{{json .ContainerConfig.Labels}}" | jq
标签的重写性
添加一个标签
cd test1/
vim Dockerfile
FROM zjt:v2
LABEL version=v3
将文件制作为镜像(在dockfile文件当前目录执行)
docker build -t zjt:v3 . --no-cache
查看标签:从当前找Dockerfile剧本文件创建镜像名为zjt
docker image inspect zjt:v3 --format "{{json .ContainerConfig.Labels}}" | jq
RUN(安装软件用)
作用:
构建指令,RUN 可以运行任何被基础 image 支持的命令。如基础 image 选择了 Centos,那么软件管理部分只能使用 Centos 的包管理命令
用来执行命令行命令,是最常用的指令之一。使用格式,
# shell格式,跟直接在命令行输入命令一行
RUN <命令>
# 示例:RUN mkdir -p /usr/src/redis
# exec格式,类似于函数调用
RUN ["可执行文件", "参数1", "参数2"]
USER(设置container容器的用户)
作用:
- 设置指令,设置启动容器的用户,默认是 root 用户,USER指令和WORKDIR相似,都是改变环境状态并影响以后的层。WORKDIR是改变工作目录, USER则是改变之后的层在执行RUN , CMD以及ENTRYPOINT这类命令时的身份。
- USER帮助你切换到指定的用户,这个用户必须是事先建立好的,否则无法切换。使用格式
格式:
USER <用户名>[:<用户组>]
USER daemon = ENTRYPOINT ["memcached", "-u", "daemon"]
EXPOSE(指定容器需要映射到宿主机器的端口)
作用:
- EXPOSE指令是声明运行时容器提供的服务端口,也只是一个声明,在容器运行时并不会因为这个声明应用就一定会开启这个端口的服务,容器启动时,还是需要通过 -p host-port:container-port来实现映射。
- EXPOSE主要是帮助镜像使用者了解这个镜像服务的监听端口,以方便进行映射配置,另一个用处是在运行时如果是使用随机端口映射,也就是通过 docker run -P的形式时,会自动随机映射EXPOSE声明的端口。
- 使用格式
EXPOSE <端口1> [<端口2>...] **最佳实践建议** 1. 应该使用常用的惯用的端口,如nginx 80,mongoDB 27017
扩展:dockfile文件如果没有前台进程,设置一个前台进程
ENV(用于设置环境变量)
作用
ENV设置环境变量,无论是后面的其它指令,如 RUN(使用 $环境变量key 的形式) ,还是运行时的应用,都可以直接使用这里定义的环境变量。
使用格式有两种,
设置环境变量的时机:
①制作docker镜像时env设置;
- docker run --env设置
注意:
docker run的env比dockerfile中的env优先级更高(范围性小的优先级大于范围性大的)
ARG(设置变量)
作用
ARG设置构建参数,即docker build命令时传入的参数。和ENV的效果差不多,都是设置环境变量,不同的是,ARG设置的是构建环境的环境变量,在容器运行时是不会存在这些环境变量的。
Dockerfile中的ARG指令是定义参数名称,以及默认值(可选)。该默认值可以在执行构建命令docker build时用 –build-arg <参数名>=<值> 来覆盖。
ARG和ENV起作用的时机不同:
使用格式
ARG <参数名>[=<默认值>] **最佳实践建议** 1. 不要使用ARG来保存密码之类的信息,因为通过docker history还是可以看到docker build执行时的所有值 2. 使用ARG,对于使用CI系统(持续集成),用同样的构建流程构建不同的 Dockerfile 的时候比较有帮助,避免构建命令必须根据每个 Dockerfile 的内容修改
<!--这里的变量用的就是 `ARG` 而不是 `ENV`了,因为这条命令运行在 `Dockerfile` 当中的, 像这种临时使用一下的变量没必要存环境变量的值就很适合使用 `ARG`-->
ADD(从 src 复制文件到 container 的 dest 路径)
作用:
作用都是将文件或目录复制到Dockerfile构建的镜像中
用法格式:
ADD <src> <dest>
- <src> 是相对dockfile文件的相对路径,可以是文件或目录的路径,也可以是一个远程的文件 url;
- <dest> 是 container 中的绝对路径
示例:
[root@zjt13 test1]# ls
Dockerfile
[root@zjt13 test1]# touch zjt.sh
[root@zjt13 test1]# vim Dockerfile
创建容器
docker build -t add:v1 .
docker run --name add13 add:v1
docker exec -it add13 /bin/sh
VOLUME(指定挂载点)
作用:
设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是 AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在 Dockerfile中 使用该指令
格式用法:
FROM base
VOLUME ["/tmp/data"]
WORKDIR(切换工作目录)
作用:
在容器内部设置工作目录,这样ENTRYPOINT和CMD指定的命令都会在容器中这个目录下进行。设置指令,可以多次切换(相当于cd命令),对RUN,CMD,ENTRYPOINT生效
格式用法:
WORKDIR /p1 WORKDIR p2 RUN vim a.txt
添加一个标签
cd test1/
vim Dockerfile
FROM nginx:v1
WORKDIR /usr/local/nginx
将文件制作为镜像(在dockfile文件当前目录执行)
docker build -t nginx:v1 . --no-cache
docker exec -it workdir /bin/bash
生产环境中用于将容器经常使用的目录修改为登陆后的默认目录
CMD(设置 container 启动时执行的操作)
作用:
- 用于提供容器运行的默认命令,如果在 docker run 时指定了运行的命令,则CMD命令不会执行。
- CMD指定容器的启动命令。容器实质就是进程,进程就需要启动命令及参数,CMD指令就是用于指定默认的容器主进程的启动命令的。使用格式
用法格式:
ENTRYPOINT(entrypoint设置container启动时执行的操作)
作用:
与CMD类似,ENTRYPOINT不会被docker run中指定的命令覆盖,如果想覆盖ENTRYPOINT,则需要在docker run中指定--entrypoint选项
用法格式:
CMD和ENTRYPOINT 的组合(设置container启动时执行的操作)
重点理解:
cmd 给出的是一个容器的默认的可执行体。也就是容器启动以后,默认的执行的命令,# 如果我们在 run 时指定了命令或者有entrypoint,那么 cmd 就会被覆盖。仍然是上面的 image。run 命令变了:
docker run xx echo glgl
==> glgl
ONBUILD(在这次镜像里面不执行,在别人把当前镜像做成子镜像后再执行。也就是说在子镜像中执行)
作用:
- ONBUILD 指定的命令在构建镜像时并不执行,而是在它的子镜像中执行
- 为镜像创建触发器,当一个镜像被用作其他镜像的基础镜像时,这个触发器会被执行。当子镜像被构建时会插入触发器中的指令。
用法格式:
STOPSIGNAL signal(发送信号)
STOPSIGNAL 指令设置将发送到容器以退出的系统调用信号。这个信号可以是一个有效的无符号数字,与内核的`syscall`表中的位置相匹配,例如`9`,或者是`SIGNAME`格式的信号名,例如:SIGKILL
SHELL (覆盖命令的shell模式所使用的默认 shell)
- Linux 的默认shell是 [“/bin/sh”, “-c”]
- Windows 的是 [“cmd”, “/S”, “/C”]
- SHELL 指令必须以 JSON 格式编写
- SHELL 指令在有两个常用的且不太相同的本shell:cmd 和 powershell,以及可选的 sh 的 windows 上特别有用
HEALTHCHECK (容器健康状况检查命令)
注意
HEALTHCHECK 命令只能出现一次,如果出现了多次,只有最后一个生效
模板
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
查看容器的健康状态
$ docker inspect –format ‘{{json .State.Health.Status}}’ cID