【docker】 Dockerfile

Dockerfile镜像构建命令

指令:FROM 
功能描述:设置基础镜像 
语法:FROM < image>[:< tag> | @< digest>] 
说明:

  • FROM指定构建镜像的基础源镜像,如果本地没有指定的镜像,则会自动从 Docker 的公共库 pull 镜像下来。
  • FROM必须是 Dockerfile 中非注释行的第一个指令,即一个 Dockerfile 从FROM语句开始。
  • FROM可以在一个 Dockerfile 中出现多次,如果有需求在一个 Dockerfile 中创建多个镜像。
  • 如果FROM语句没有指定镜像标签,则默认使用latest标签。 

指令:COPY
功能描述:COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置
语法:

  • COPY [--chown=<user>:<group>] <源路径>... <目标路径>
  • COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

注意:使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建相关文件都在使用 Git 进行管理的时候

  • 如果<源路径>为文件,则复制文件和元数据 
  • 如果<目标路径>不存在,指令会自动创建<目标路径>和缺失的上级目录

指令:ADD
功能描述:ADD 指令和 COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。
语法:

  • COPY [--chown=<user>:<group>] <源路径>... <目标路径>
  • COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

说明:自动解压缩的功能非常有用,因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD

  • <源路径>为URL时,docker自动下载下载到<目标路径>路径,并且默认权限为600。可以使用RUN命令调整权限。
  • <源路径>为压缩文件时,并且压缩方式为gzip,bzip2或xz时,指令会将其解压为目录 

指令:CMD 
功能描述:Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定默认的容器主进程的启动命令的,在运行时可指定新的命令来替代镜像设置中的默认命令
语法:

  • shell 格式: CMD <命令>
  • exec 格式: CMD ["可执行文件", "参数1", "参数2"...]
  • 参数列表格式: CMD ["参数1", "参数2"...] 。在指定了 ENTRYPOINT 指令后,用 CMD 指定具体的参数。

注意:

  • Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 systemd 或者systemctl去启动后台服务,容器内没有后台服务的概念
  • Dockerfile中只能有一条CMD命令,如果多条则最后一条生效,如果用户启动容器时指定了运行的命令,则会覆盖掉CMD指定的命令。

指令:ENTRYPOINT 
功能描述:指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数
语法:

  • exec方式:ENTRYPOINT [“executable”,”param1”,”param2”] 
  • shell方式:ENTRYPOINT command param1 param2

说明:

  • 入口程序是容器启动时执行的程序,docker run中最后的命令将作为参数传递给入口程序 
  • 入口程序有两种格式:exec、shell,其中shell使用/bin/sh -c运行入口程序,此时入口程序不能接收信号量 
  • 当Dockerfile有多条ENTRYPOINT时只有最后的ENTRYPOINT指令生效 
  • 如果使用脚本作为入口程序,需要保证脚本的最后一个程序能够接收信号量,可以在脚本最后使用exec或gosu启动传入脚本的命令 
  • 通过shell方式启动入口程序时,会忽略CMD指令和docker run中的参数 
  • 为了保证容器能够接受docker stop发送的信号量,需要通过exec启动程序;如果没有加入exec命令,则在启动容器时容器会出现两个进程,并且使用docker stop命令容器无法正常退出(无法接受SIGTERM信号),超时后docker stop发送SIGKILL,强制停止容器 
  • Dockerfile中只能有一条ENTRYPOINT 命令,如果多条则最后一条生效,如果用户启动容器时指定了运行的命令,则会覆盖掉ENTRYPOINT 指定的命令。

例子:FROM ubuntu <换行> ENTRYPOINT exec top -b


指令:MAINTAINER 
功能描述:指定创建镜像的用户 
语法:MAINTAINER < name> 


指令:RUN 
功能描述: 运行构建镜像的命令
语法:

  • shell 格式:RUN < command>    使用/bin/sh -c < command>运行脚本,可以在其中使用 \ 将脚本分为多行以及行首 # 进行注释
  • exec 格式:RUN [“executable”,”param1”,”param2”] 

说明:每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像,后续的RUN都在之前RUN提交后的镜像为基础,镜像是分层的,可以通过一个镜像的任何一个历史提交点来创建,类似源码的版本控制。
例子:


指令:LABEL 
功能描述:用于生成镜像的元数据的标签信息
语法:LABEL < key>=< value> < key>=< value> … 
说明:每条指令都会生成一个镜像层,Docker中镜像最多只能有127层,如果超出Docker Daemon就会报错,如LABEL ..=.. <假装这里有个换行> LABEL ..=..合在一起用空格分隔就可以减少镜像层数量,同样,可以使用连接符\将脚本分为多行,镜像会继承基础镜像中的标签,如果存在同名标签则会覆盖。


指令:EXPOSE 
功能描述:设置镜像暴露端口,声明镜像内服务所监听的端口
语法:EXPOSE < port> [< port> … ]
说明:

  • 容器启动时,Docker Daemon会扫描镜像中暴露的端口,在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口 
  • EXPOSE只是起到声明租用的作用,只有启动容器时使用-P/-p才是端口映射,这个时候才能通过外部访问容器提供的服务

例子:-p <宿主端口>:<容器端口>


指令:ENV 
功能描述:设置镜像中的环境变量 
语法:

  • ENV <key> <value>
  • ENV <key1>=<value1> <key2>=<value2>...

说明:环境变量在整个编译周期都有效,通过${变量名}或者 $变量名使用变量,使用方式${变量名}时可以用${变量名:-default} ${变量名:+cover}设定默认值或者覆盖值,ENV设置的变量值在整个编译过程中总是保持不变的,但指令指定的环境变量在运行时可以被覆盖掉,如docker run --env <key>=<value> built_image

例子:

ENV VERSION=1.0 DEBUG=on \
    NAME="Happy Feet"

指令:VOLUME 
功能描述:设置容器的挂载点 
语法:

  • VOLUME ["<路径1>", "<路径2>"...]
  • VOLUME <路径>

说明:启动容器时,Docker Daemon会新建挂载点,并用镜像中的数据初始化挂载点,可以将主机目录或数据卷容器挂载到这些挂载点,一般用来存放数据库和需要保存的数据等。


指令:USER 
功能描述:指定当前用户
语法:USER <用户名>[:<用户组>]


指令:WORKDIR 
功能描述:设置RUN CMD ENTRYPOINT ADD COPY指令的工作目录 
语法:WORKDIR <工作目录路径>
说明:如果工作目录不存在,则Docker Daemon会自动创建 
          Dockerfile中多个地方都可以调用WORKDIR,如果后面跟的是相对位置,则会跟在上条WORKDIR指定路径后(如WORKDIR /A   WORKDIR B   WORKDIR C,最终路径为/A/B/C)


指令:ARG 
功能描述:指定一些镜像内使用的参数(例如版本号信息等)
语法:ARG < name>[=< defaultValue>] 
说明:ARG 所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。

  • Dockerfile 中的 ARG 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖
  • ARG从定义它的地方开始生效而不是调用的地方,在ARG之前调用编译变量总为空,在编译镜像时,可以通过docker build --build-arg < var>=< value>设置变量,如果var没有通过ARG定义则Daemon会报错 
  • 可以使用ENV或ARG设置RUN使用的变量,如果同名则ENV定义的值会覆盖ARG定义的值,与ENV不同,ARG的变量值在编译过程中是可变的,会对比使用编译缓存造成影响(ARG值不同则编译过程也不同) 

指令:ONBUILD 
功能描述:ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUNCOPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行
语法:ONBUILD [INSTRUCTION] 
提示:从该镜像生成子镜像,在子镜像的编译过程中,首先会执行父镜像中的ONBUILD指令,所有编译指令都可以成为钩子指令


指令:STOPSIGNAL 
功能描述:指定所创建镜像启动的容器接收退出的信号值,设置容器退出时,Docker Daemon向容器发送的信号量 
语法:STOPSIGNAL signal 
提示:信号量可以是数字或者信号量的名字,如9或者SIGKILL。 


指令:HEALTHCHECK 
功能描述:健康检查
语法:

  • HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
  • HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

说明:当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为 starting,在 HEALTHCHECK 指令检查成功后变为 healthy,如果连续一定次数失败,则会变为 unhealthy

  • --interval=<间隔>:两次健康检查的间隔,默认为 30 秒;
  • --timeout=<时长>:健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
  • --retries=<次数>:当连续失败指定次数后,则将容器状态视为 unhealthy,默认 3 次。

 

 镜像构建

1.全流程都在同一个Dockerfile中构建

2.分为多个Dockerfile+脚本构建

3.多阶段构建

只构建某一阶段的镜像

我们可以使用 as 来为某一阶段命名,例如

FROM golang:1.9-alpine as builder

例如当我们只想构建 builder 阶段的镜像时,增加 --target=builder 参数即可

$ docker build --target builder -t username/imagename:tag .

构建时从其他镜像复制文件

上面例子中我们使用 COPY --from=0 /go/src/github.com/go/helloworld/app . 从上一阶段的镜像中复制文件,我们也可以复制任意镜像中的文件。

$ COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

 

常见问题 

1.CMD ENTRYPOINT和RUN的区别

    RUN指令是设置编译镜像时执行的脚本和程序,镜像编译完成后,RUN指令的生命周期结束

    容器启动时,可以通过CMD和ENTRYPOINT设置启动项,其中CMD叫做容器默认启动命令,如果在docker run命令末尾添加command,则会替换镜像中CMD设置的启动程序;ENRTYPOINT叫做入口程序,不能被docker run命令末尾的command替换,而是将command当作字符串,传递给ENTRYPOINT作为参数

FROM ubuntu
ENTRYPOINT ["ps"]

//通过命令docker run --rm test启动容器,打印ps的输出
//通过命令docker run --rm test -ef启动容器,打印ps -ef的输出

在docker run中,可以通过–entrypoint替换镜像中的入口程序,在Dockerfile中,应该至少有一条CMD或者ENTRYPOINT指令,如果同时定义了CMD和ENTRYPOINT则CMD会作为参数传递给ENTRYPOINT

FROM ubuntu
ENTRYPOINT ["ps"]
CMD ["-ef"]

//通过命令docker run --rm test启动容器,打印ps -ef的输出

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章