[TOC]
Dockerfile语法
FROM #指定基础镜像
注意:只能在Dockerfile中出现一次,且位于最上层
(后续也会出现有多个FROM的情况,镜像分层)
FROM centos:centos7.2.2009
MAINTAINER #指定镜像创建者
maintainer
MAINTAINER yq "yq@qq.com"
LABEL #将元数据添加到镜像
(标签的定义)
LABEL "www.yq.com"="YQ WEB"
LABEL version="1.0"
LABEL nginx-version="1.18.0" \
key1=yq
拓展1:根据Dockerfile文件生成镜像
(注意:在当前目录下执行命令后,会将当前目录下所有作为镜像的原材料)
$ docker build -t label:v1 --no-cache
-t 镜像名:版本 #指定镜像名,版本号
--no-cache #生成镜像过程中不建立缓存(建立缓存后,下一次生成不会再次执行详细步骤,直接使用缓存)
拓展2:Dockerfile原理
创容器、可写层中执行、所有层级保存为新镜像、删容器
基于已存在的镜像中创建容器,将Dockerfile中的指令放入可写层执行,完成后将所有层级保存为一个新镜像,删除刚才创建的容器,基于此镜像再创建一个容器,将下一个指令放入可写层中执行,完成后将所有层级保存为一个新镜像,删除刚才创建的容器,循环往复,直到执行完Dockerfile中所有指令(每个关键字的执行都会创建一个容器,执行完毕保存层级后就会被删除)

拓展3:格式化处理,筛选容器中的 json 信息
$ docker image inspect label:v1 --format "{{json .Author}}" | jq
$ docker image inspect label:v1 --format "{{ json .ContainerConfig.Labels}}" | jq
拓展4:继承与重写(只要是元数据,都会符合这个特性)
不仅发生在 label 指令中,也可以对:其他的镜像、启动命令、作者信息等指令使用
**继承:**新镜像不改变之前的指令
**重写:**新镜像先继承之前的指令,再根据需要,对指令进行修改
RUN #指定镜像中,需要执行的命令
注意:每一个RUN指令,都会重新创建一个容器,进入执行命令时都在初始位置(执行的命令注意当前所在位置)
注意:
1)将同一个应用服务的操作,放入一个指令中
Dockerfile的每一个指令都被封装在独立文件层级中
镜像中,若层级的操作相同,时可以重用的:存储空间、过程
2)尽可能将容易变化的层级放入上层
从底层到上层,在镜像的重用过程中,若中间出现了变化,上层的操作虽然一样,但最后结果不一样
3)RUN 后的命令能否执行,取决于镜像环境能否执行

RUN cd /tmp && curl -L 'http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.8/bin/apache-tomcat-7.0.8.tar.gz' | tar -xz
RUN ["/bin/bash", "-c", "echo hello"]
USER #设置容器的用户
如果不指定,默认为root
USER nginx
EXPOSE #指定容器需要映射到宿主机的端口(信息级别)
#可以映射多个端口
EXPOSE 80 3306
ENV #设置容器中的环境变量
(只能用此方法设置,在容器中 /etc/profile 设置的不会生效)
ENV NAME nginx
ARG #设置 Dockerfile 中的环境变量
ENV与ARG区别
起作用的时机不同:
ARG:在 build 过程中,存在的环境变量,可以在Dockerfile中当作变量使用
ENV:是容器创建好后,在容器中生效的环境变量,不能在Dockerfile中当参数使用
案例:
# Dockerfile
FROM centos7:latest
LABEL maintainer="yq@qq.com"
ARG REDIS_SET_PASSWORD=developer
ENV REDIS_PASSWORD $(REDIS_SET_PASSWORD)
RUN echo $(REDIS_SET_PASSWORD) > /root/redis_password
RUN echo $(REDIS_SET_PASSWORD)
VOLUME /data
EXPOSE 6379
CMD ["sh", "-c", "exec redis-server --requirepass \"$REDIS_PASSWORD\""]
ADD #从 src 复制文件到 container 的 dest 路径
ADD <src> <dest>
<src> 是相对被构建的源目录的相对路径,可以是文件或目录的路径,也可以是一个远程的文件 url;
<dest> 是 container 中的绝对路径
src 可以是一个 URL,会自动下载
如果 src 是一个压缩包,会自动解压
两个特性不能同时存在
COPY #从 src复制到 container 的 dest 路径
#注意:不支持 src 为URL、不支持自动解压(仅为一个单纯的拷贝关系)
COPY <src> <dest>
VOLUME #指定挂载点
设置指令,使容器中的一个目录具有持久化存储数据的功能,该目录可以被容器本身使用,也可以共享给其他容器使用。我们知道容器使用的是 AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。当容器中的应用有持久化数据的需求时可以在 Dockerfile中 使用该指令
FROM base
VOLUME ["/tmp/data"]
WORKDIR #切换目录
#设置进入容器后,所在的默认位置(可以写多个)
WORKDIR /usr/local/nginx
#结合 RUN ,可以实现 RUN 中的命令不用每次都指定切换路径
CMD #设置容器启动时,执行的操作
**注意:**设置多个时,谁在最后谁生效
当镜像创建为容器时,CMD定义的命令会执行
当容器从关闭状态到启动,CMD定义的命令会执行
拓展:容器如果需要正常运行,需要有一个前台进程
CMD touch /usr/local/nginx/logs/access.log && /usr/local/nginx/sbin/nginx && tail -f /usr/local/nginx/logs/access.log
ENTRYPOINT #设置容器启动时,执行的操作
**注意:**设置多个时,谁在最后谁生效
若结合CMD,且CMD为完整的可执行命令,谁在最后谁生效
CMD touch /root/1.txt
ENTRYPOINT ls -l
拓展:ENTRYPOINT 与CMD 结合
官方释义:https://docs.docker.com/engine/reference/builder/#cmd
Dockerfile:
FROM centos7:latest
CMD ["p in cmd"] #定义参数
ENTRYPOINT ["echo"] #定义命令
$ docker build -t env:v1 .
$ docker run --name test1 env:v1
p in cmd
$ docker run --name test2 env:v1 p in run
p in run
实验:启动容器时,实现不同命令启动不同服务
信息请点击👉CMD+ENTRYPOINT实现:选择服务启动镜像
Dockerfile 的层级是有行数限制的
Docker overlay
128层
ONBUILD #在子镜像中执行
ONBUILD 指定的命令在构建镜像时并不执行,而是在它的子镜像中执行
**用途:**可以防止别人对此镜像再次封装
可以在别人对此镜像封装时,自动删除不需要的数据
ONBUILD RUN sleep 86400
ONBUILD RUN rm -rf /root/*
STOPSIGNAL #指令设置将发送到容器以退出的系统调用信号
SIGHUP 1 A 终端挂起或者控制进程终止
SIGINT 2 A 键盘中断(如break键被按下)
SIGQUIT 3 C 键盘的退出键被按下
SIGILL 4 C 非法指令
SIGABRT 6 C 由abort(3)发出的退出指令
SIGFPE 8 C 浮点异常
SIGKILL 9 AEF Kill信号
SIGSEGV 11 C 无效的内存引用
SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道
SIGALRM 14 A 由alarm(2)发出的信号
SIGTERM 15 A 终止信号
SIGUSR1 30,10,16 A 用户自定义信号1
SIGUSR2 31,12,17 A 用户自定义信号2
SIGCHLD 20,17,18 B 子进程结束信号
SIGCONT 19,18,25 进程继续(曾被停止的进程)
SIGSTOP 17,19,23 DEF 终止进程
SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键
SIGTTIN 21,21,26 D 后台进程企图从控制终端读
SIGTTOU 22,22,27 D 后台进程企图从控制终端写
SHELL #修改容器的默认解释器
#不建议使用
SHELL ["/usr/local/python"]
RUN /root/a.py
RUN /usr/local/python /root/a.py (√)建议使用
HEALTHCHECK #容器健康状况检查 (废弃,由k8s完美替代)
注意
HEALTHCHECK 命令只能出现一次,如果出现了多次,只有最后一个生效
模板
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
查看容器的健康状态
$ docker inspect –format ‘{{json .State.Health.Status}}’ cID
更多详细信息请点击👉Dockerfile 语法详解-课件