6.Docker dockerfile语法简介

Dockerfile是由一系列命令和参数构成的脚本,一个Dockerfile里面包含了构建整个image的完整命令。Docker通过docker build执行Dockerfile中的一系列命令自动构建image。

1. FROM

FROM  <image>[:<tag> | @<digest>] [AS <name>]

FROM指定一个基础镜像,且必须为Dockerfile文件开篇的每个非注释行,至于image则可以是任何合理存在的image镜像

FROM可以在一个Dockerfile中出现多次,以便于创建混合的images。如果没有指定tag,latest将会被指定为要使用的基础镜像版本。

AS name,可以给新的构建阶段赋予名称。该名称可用于后续FROM 和 COPY --from=<name | index>说明可以引用此阶段中构建的镜像

FROM scratch #制作base image
FROM centos #使用base image
FROM ubuntu:14.04

FROM 是Dockerfile 最开头的关键字,它制定了我们要Build 的Docker image 的Base image 是什么,就是我们想在哪个image 之上去Build 我们的image ,如最开始的 Hello-world,它没有依赖任何Base image ,这样的话我们就选FROM scratch ,从头制作一个Base image ,更多的情况是使用已有的Base image,比如说官方的centos 的已有的Base image ,然后FROM centos ,这样的话可以在centos 的基础之上去Build image,同样也可以选择一些其他的Linux 发行版,如:ubntu

注意:
  • 为了安全,FROM 尽量使用官方的image 作为base image

2. LABEL

为镜像生成元数据标签信息

LABEL <KEY>=<VALUE> \
    <KEY>="XXXX"
LABEL maintainer="xxxx@xxx.com"
LABEL version="1.0"
LABLE description="This is description"
注意:
  • 多个标签写成一行,避免在镜像中额外增加layer
  • 对于image来讲 Metadata 不可少,LABEL 就像我们平常了解的注释一样

3. RUN

接受命令作为参数并用于创建镜像,在之前的commit层上形成新的层。

RUN \<command\>(如同执行shell命令 /bin/sh -c)
RUN ["executable", "param1", "param2"] #exec格式,必须使用“”,不能使用单引号

RUN 指令将在当前image中执行任意合法命令并提交执行结果。命令执行提交后,就会自动执行Dockerfile中的下一个指令。
分层RUN指令和生成提交符合Docker的核心概念,其中提交很轻量,可以从image将用于Dockerfile中的下一步。
exec形式使得可以避免shell字符串变化,以及使用不包含指定的shell可执行文件的基本image来运行RUN命令。
在shell形式中,可以使用\(反斜杠)将单个RUN指令继续到下一行。例如:

RUN yum update && \
    yum install -y vim 

4. WORKDIR

用于为Dockerfile中所有RUN、CMD、ENTRYPOINT、COPY和ADD指令设定工作目录

WORKDIR <dirpath>

类似于linux下的 cd 命令

WORKDIR /test   #如果没有会自动创建test目录
WORKDIR demo    #同上
RUN pwd       # 输出 /test/demo
注意:
  • 尽量使用WORKDIR 不要使用 RUN cd
  • 尽量使用绝对路径,跳转到哪个目录更清晰

5. ADD 和 COPY

COPY

当复制一个目录时,并不会复制目录本身,而是会递归复制其下子目录 至目标目录下

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] #这种适合有空格的路径

文件复制准则

  • <src>必须是build上下言文中的路径,不能是其父目录中的文件
  • 如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制
  • 如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾
  • 如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径。
ADD

ADD指令类似于COPY指令,ADD支持使用TAR文件和URL路径

ADD <src>...<dest>
ADD ["<src>",..."<dest>"]

操作准则

  • <src>必须在context目录下,不能ADD ../something /something,因为第一步docker build已经把context的内容发送到docker daemon了。
  • 假如<src>是URL且<dest>没有/结尾,src的文件直接拷贝到dest
  • 假如<src>是URL且<dest>有/结尾,src的文件拷贝到dest/filename
ADD hom* /mydir/               # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/           # ?匹配单个字符,如 "home.txt"
ADD test relativeDir/          # 添加test到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/         # 添加test到/absoluteDir/
注意: 如果想添加远程文件、目录,请使用 RUN + curl/weget
ADD http://example.com/1.tar.gz /apps/
RUN tar xf /apps/1.tar.gz -C /apps/ && \
    /bin/sh -c /apps/***.sh

简单操作

RUN mkdir -p /iyunwen/server/ && \
        curl -SL http://example.com/1.tar.gz \
        | tar -xzC /iyunwen/server/ && \
        /bin/sh -c /apps/***.sh

6. ENV

ENV指令可以用于docker容器设置环境变量

ENV <key> <value>
ENV <key>=<value> ...

指定一个环境变量,会被后续RUN指令使用,并在容器运行时保留。

ENV MYSQL_VERSION 5.7   # 设置常量 MYSQL_VERSION  值是 5.7
RUN apt-get install -y mysql-server = “${MYSQL_VERSION}”  #引用常量

ENV设置的环境变量,可以使用 docker inspect 命令来查看。同时还可以使用 docker run --env <key>=<value>来修改环境变量

7. EXPOSE

用来指定端口,使容器内的应用可以通过端口和外界交互。

EXPOSE <port> [<port>...]

告诉Docker服务端容器对外映射的本地端口,需要在docker run 的时候使用-p 或者 -P 选项生效。

EXPOSE 80/tcp

8. VOLUME

可实现挂载功能,容器告诉Docker在主机上创建一个目录(默认情况下是在/var/lib/docker),然后将其挂载到指定的路径。当删除使用该Volume的容器时,Volume本身不会受到影响,它可以一直存在下去。

FROM centos
#将该镜像的存储内容挂载到test文件夹下。这样即使删除了该镜像,再重新创建后,也不会影响数据
VOLUME /test  
CMD echo "hello docker"

9. CMD

设置容器启动后默认执行的命令和参数

CMD <command>   //支持命令展开,但是不支持传递信号 
CMD ["<executable>","<param1>","<param2>"]  //相当于容器的第一个命令,可以接受信号
CMD ["param1","param2"]
前两种语法格式的意义同RUN
第三种则用于为ENTRYPOINT指令提供默认参数

类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同

  • RUN 指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新镜像文件启动一个容器时。
  • CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD指定的命令其可以被docker run的命令行选项所覆盖
  • 在Dockerfile中可以存在多个CMD指令,但仅最后一个生效
FROM centos
CMD echo "hello docker"

docker run [image] 输出就是 hello docker
docker run [image] /bin/bash 默认进入了当前container

10. ENTRYPOINT

类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一具单独的可执行程序
与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定的程序。不过,docker run 命令的--entrypoint 选项的参数可覆盖ENTRYPOINT指令指定的程序

ENTRYPOINT <command>    //这种方式能接受shell命令行展开
ENTRYPOINT ["<executable>","param1"]  //展开不了,但能接收到信号

docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用。Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效
我们来看一段命令

Dockerfile1:

FROM centos
ENV name hello-Docker
ENTRYPOINT echo "${name}" 
输出是 hello-world

Dockerfile2

FROM centos
ENV name hello-Docker
ENTRYPOINT ["bin/echo","${name}"]  
输出是 ${name}

出现两种不同输出的原因是因为 我们第一个Dockerfile 是shell格式执行命令时,默认就是 在linux的shell里执行。

但是第二个Dockerfile 我们使用的是Exec格式,我们去执行的是 echo这个命令而不是在linux的shell下执行命令,因此输出不一样。

11. USER

用于指定运行image时的或运行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序时的用户名或UID
默认情况下,container的运行身份为root用户
Syntax:

USER <UID>|<UserName> 

需要注意的是,<UID>可以为任意数字,但实践中其必须为/etc/passwd中某用户的有效UID,否则,docker run命令将运行失败

12. ONBUILD

用于在Dockerfile中定义一个触发器
Dockerfile用于build映像文件,此映像文件亦可作为base image被另一个Dockerfile用作FROM指令的参数,并以之构建新的映像文件
在后的这个Dockerfile中的FROM指令在build过程中被执行时,将会“触发”创建其base image的Dockerfile文件中的ONBUILD指令定义的触发器

ONBUILD <INSTRUCTION>

注意:
尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令
使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,例如ruby:2.0-onbuild
在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程和上下文在缺少指定的源文件时会失败。

13. HEALTHCHECK

Docker 1.12版本后引入的判断容器状态是否正常

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

在没HEALTHCHECK指令前,Docker只能通过容器内主进程是否退出来判断容器是否状态异常。很多情况下这没问题,但是如果程序进入死锁状态,或者死循环状态,应用进程并不退出,但是该容器已经无法提供服务了。虽然后端的程序可以通过前端的检测工具来检查状态信息。但是最前端的服务就需要本身的检测机制加上监控,就可以做到出现问题解决问题。

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

HEALTHCHECK支持下列选项:

--interval=<间隔> : 两次健康检查间隔,默认30秒
--timeout=<时长> : 健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认为30秒
--retries=<次数> :当连续失败指定次数后,则将容器状态视为unhealthy,默认3次。
和CMD、ENTRYPOINT一样,HEALTHCHECK只可以出现一次,如果写了多个,只有最后一个生效。CMD 后面的命令也分为shell和exec格式。命令的返回值决定了该次检查的成功与否: 0表示成功;1表示失败;2保留。

HEALTHCHECK --interval=5s --timeout=3s \
  CMD curl -fs http://localhost/ || exit 1

14. MAINTAINER

作者信息,写在FROM后

MAINTAINER "auth <email>"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348