Dockerfile基础指令

一、Dockerfile简介

Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令,Docker程序将这些Dockerfile指令翻译真正的Linux命令;Dockerfile有自己书写格式和支持的命令,Docker程序解决这些命令间的依赖关系,类似于Makefile,Docker程序将读取Dockerfile,根据指令生成定制的image。

Dockerfile的指令是忽略大小写的,建议使用大写,使用#作为注释,每一行只支持一条指令,每条指令可以携带多个参数。

Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层, 因此每一条指令的内容,就是描述该层应当如何构建。

二、dockerfile指令详解

1. FROM

功能为指定基础镜像,并且必须是第一条指令。

除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为scratch。这个镜像 是虚拟的概念,并不实际存在,它表示一个空白的镜像。
如果你以scratch为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始构建。

不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,比如swarm、coreos/etcd 。对于Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 FROM scratch 会让镜像体积更加小 巧。使用Go语言开发的应用很多会使用这种方式来制作镜像,这也是为什么有人认为 Go 是特别适合容器微服务架构的语言的原因之一。

2. MAINTAINER

格式为 MAINTAINER ,指定维护者信息。

3. RUN

用来执行命令行命令

  • shell格式:RUN <命令> ,就像直接在命令行中输入的命令一样
  • exec格式:RUN [“可执行文件”, “参数1”, “参数2”],这更像是函数调用中的格式

使用 && 符连接多个命令; \ 符进行换行。

为防止镜像臃肿,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉(编译构建所需要的软件,所有下载、展开的文件,apt缓存文件等)。

4. CMD

  • shell格式:CMD <命令>
  • exec 格式:CMD [“可执行文件”, “参数1”, “参数2”…]
  • 参数列表格式:CMD [“参数1”, “参数2”…],提供给 ENTRYPOINT 的默认参数

指定启动容器时执行的命令,每个 Dockerfile 只能有一条 CMD 命令。如果指定了多条命令,只有最后一条会被执行。

如果用户启动容器时候指定了运行的命令,则会覆盖掉 CMD 指定的命令。

Docker不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用upstart/systemd去启动后台服务,容器内没有后台服务的概念。

CMD service nginx start ,如果这样写会出现容器执行后立即退出了,这主要是因为没搞明白前台和后台的概念,没有区分容器和虚拟机的差异,对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,进而退出,其他辅助进程不是他关心的内容。 上述命令可以理解为 CMD[ “sh”, “-c”, “service nginx start”] ,因此主进程是sh ,sh结束,主进程退出,自然容器也会退出。正确的做法是 CMD [ “nginx”, “-g”, “daemon off;” ]

5. ENTRYPOINT

两种格式:

  • ENTRYPOINT [“executable”, “param1”, “param2”]
  • ENTRYPOINT command param1 param2(shell中执行)

配置容器启动后执行的命令,ENTRYPOINT 在运行时也可以替代,不过比CMD要略显繁琐,需要通过docker run的参数 -entrypoint来指定。

当指定了ENTRYPOINT后,CMD的含义就发生了改变:

如果CMD中不是完整的命令,则将CMD的内容作为参数传给ENTRYPOINT指令,换句话说实际执行时,将变为 ENTRYPOINT CMD。

如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效。

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

6. EXPOSE

  • EXPOSE <端口1> [<端口2>…]

功能为暴漏容器运行时的监听端口给外部,但是EXPOSE并不会使容器访问主机的端口,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -P参数。

-P:大写P为自动映射,会将EXPOSE暴露出来的端口随机映射到宿主机的端口上,如果没有暴露端口,就不会有映射。
-p:小写p为手动映射,需要自己指定宿主机的端口和容器的端口,形式为:
-p 宿主机端口:容器端口

(1)无论有没有暴露端口、自动映射或者手动映射,宿主机都可以通过容器ip+port(port随容器内部服务监听端口改变而改变)端口访问服务;

(2)要通过宿主机ip+端口的方式访问服务,宿主机的端口必须与容器端口有映射关系;

(3)如果没有暴露端口,-P自动映射不会映射任何端口,-p可以指定宿主机端口和容器端口形成映射。

7. ENV

  1. ENV <键> <值>
  2. ENV <键>=<值> …

两者的区别就是第一种是一次设置一个,第二种是一次设置多个

下列指令可以支持环境变量展开:
ADD、COPY 、ENV、EXPOSE 、LABEL 、USER 、WORKDIR 、VOLUME 、STOPSIGNAL、ONBU ILD

使用环境变量方式: $环境变量

8. COPY

将从构建上下文目录中<源路径>的文件或者目录复制到新的一层的镜像内的<目标路径>位置。
<目标路径>可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用WORKDIR指令来指定)。目标路径不需要事先创建,如果目录不存在会在复制文件前先行创建缺失目录。

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

  • COPY:<源路径>… <目标路径>
  • COPY: ["<源路径1>",… “<目标路径>”]
COPY src1 \
     src2 \
     WORKDIR/     

执行上述操作会发现将src1 src2 下的文件全部复制到WORKDIR下,并没有复制目录src1 src2,官方对于COPY解释是:

Note: The directory itself is not copied, just its contents.

即:COPY指令拷贝一个文件夹只会拷贝文件夹的内容。

上述指令可以这样写:

COPY src1 \
     src2 \
     WORKDIR/src

这样将COPY的文件,放在了新创建的src目录下。

9. ADD

ADD指令和COPY的格式和性质基本一致,不过<源文件>可以是一个URL,同时如果源文件是一个压缩文件,ADD会自动执行解压缩。

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

10. VOLUME

  • VOLUME ["<路径1>", “<路径2>”…]

容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存 动态数据的应用,其数据库文件应该保存于卷(volume)中。

为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

如何使用:
在Dockerfile中定义匿名卷,运行容器时,使用参数 -v 宿主机目录:匿名卷 进行挂载,实现了数据持久化。

11. WORKDIR

  • WORKDIR <工作目录路径>

使用WORKDIR指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

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

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd  

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

12. USER

  • USER <用户名>

USER是改变之后层的执行RUN ,CMD以及ENTRYPOINT这类命令的身份。USER只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。

13. ONBUILD

  • ONBUILD <其它指令>

ONBUILD是一个特殊的指令,它后面跟的是其它指令,比如RUN ,COPY等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。
Dockerfile中的其它指令都是为了定制当前镜像而准备的,唯有ONBUILD是为了帮助别人定制自己而准备的。


交个朋友吧,希望这里有你想要的

青夕的github,欢迎Star

青夕的博客,欢迎访问

青夕的公众号,欢迎关注

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值