Dockerfile
配置容器化应用
• MariaDB:
• 命令行选项
• 配置文件
• 容器化方式运行MariaDB
• 启动容器
• exec -it
• 配置容器化应用
• docker run
• 通过自定义要运行的命令,并向传递命令行参数;
• 自定义镜像,将修改好的配置文件直接焙进镜像
• 环境变量
• docker run -e
• 存储卷
• 容器:一个进程;
• 进程终止,必将导致容器终止;
• 传递终止信号:SIGTERM,SIGKILL
• 进程没终止:running
• 健康状态检测
• 通过重启自愈
关于Dockerfile
•dockerfile只是构建docker映像的源代码
•Docker可以通过读取Dockerfile中的指令自动生成镜像
•dockerfile是一个文本文档,包含用户可以在命令行上调用的所有命令,以组合镜像
•使用Docker Build,用户可以创建一个自动生成,它连续执行多个命令行指令
Dockerfile格式
- 格式
- #注释
- 指令参数
- 指令不区分大小写
- 然而,惯例是它们必须是大写,以便更容易将它们与论点区分开来
- Docker按顺序在Dockerfile中运行指令
- 第一条指令必须是“from”,以便指定要从中生成的基础图像
环境置换
•环境变量(用env语句声明)也可以在某些指令中用作dockerfile要解释的变量
•Dockerfile中也注明了环境变量使用{variable_name}
•{variable:-word}表示如果设置了variable,则结果就是该值。如果未设置变量,则结果为word。
•${variable:+word}表示如果设置了变量,则结果将是word,否则结果是空字符串。
#NAME变量有值则显示原有值,没有值则显示tom
${NAME:-tom}
#NAME变量不为空则值为tom,否则值为空
${NAME:+tom}
.dockeringnore文件
•在docker cli将上下文发送给docker守护进程之前,它会在上下文的根目录中查找名为.dockerignore的文件
•如果该文件存在,cli将修改上下文以排除与其中模式匹配的文件和目录
•cli将.dockerignore文件解释为换行分隔的模式列表,类似于unix shell的文件glob
FROM
• FROM指令是最重的一个且必须为Dockerfile文件开篇的第一个非注释行,用于
为映像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运
行环境
•实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件
• 如果找不到指定的镜像文件,docker build会返回一个错误信息
FROM <repository>[:<tag>]或 #使用名字是tag可省
FROM <resository>@<digest> #仓库中的镜像的hash码来进行拉取
<reposotiry>:制定作为base image的名称
<tag>:base image的标签,为可选项,省略时默认为latest
MAINTANIER (depreacted)
•用于让Dockerfile制作者提供本人的详细信息
• Dockerfile并不限制MAINTAINER指令可在出现的位置,但推荐将其放置于FROM指令之后
MAINTAINER <authtor's detail>
<author's detail>可是任何文本信息,但约定俗成地使用作者名称及邮件地址
MAINTAINER "magedu <mage@magedu.com>"
- 示例:
#Description: test image
FROM nginx:latest
#基于父镜像构建其他docker镜像,父镜像:可以通过docker pull 命令获得,也可以自己制作
MAINTAINER cary.liu<xxx@126.com>
#Docker file维护者信息
LABEL
•label指令将元数据添加到镜像中
语法:label<key>=<value><key>=<value><key>=<value>…
label指令将元数据添加到镜像中。
标签是键值对。
要在标签值中包含空格,请使用引号和反斜杠,就像在命令行解析中一样。
一个镜像可以有多个标签。
可以在一行上指定多个标签。
- 一个镜像可以有多个label。要指定多个labels[Docker推荐尽可能地把多个labels合并到一个LABEL指令中去。每一个LABEL指令会生成一个新的镜像层,如果你使用多个label,将导致构建出一个低效的镜像。这个示例只生成单个镜像层。
- label是累积的,包括FROM镜像的lable。如果Docker遇到一个label/key已经存在,那么新的值将覆盖这个label/key。
要查看一个镜像的label,使用docker inspect命令。
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
# 可写为一下格式
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
#docker inspect 查看
"Labels": {
"com.example.vendor": "ACME Incorporated"
"com.example.label-with-value": "foo",
"version": "1.0",
"description": "This text illustrates that label-values can span multiple lines.",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
}
COPY
•用于从Docker主机复制文件至创建的新映像文件
• COPY <src> ... <dest> 或
• COPY ["<src>",... "<dest>"]
• <src>:要复制的源文件或目录,支持使用通配符
• <dest>:目标路径,即正在创建的image的文件系统路径;建议为<dest>使用绝对路径,否则,COPY指定则以WORKDIR为其起始路径;
• 注意:在路径中有空白字符时,通常使用第二种格式
•文件复制准则
• <src>必须是build上下文中的路径,不能是其父目录中的文件
• 如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制
• 如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾
• 如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径
COPY yum.repos.d /etc/yum.repos.d/
[root@localhost img1]# ls
Dockerfile index.html
[root@localhost img1]# cat index.html
test
[root@localhost img1]# cat Dockerfile
#Description: test image
FROM nginx:latest
MAINTAINER "wsl <wsl@qq.com>"
COPY index.html /data/web/www/html/
[root@localhost img1]# docker build -t mynginx:test ./
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM nginx:latest
---> 5a3221f0137b
Step 2/3 : MAINTAINER "wsl <wsl@qq.com>"
---> Running in 3c1a4872fc92
Removing intermediate container 3c1a4872fc92
---> df22d9badea1
Step 3/3 : COPY index.html /data/web/www/html/
---> 2c69f2815bcc
Successfully built 2c69f2815bcc
Successfully tagged mynginx:test
[root@localhost img1]# docker run --name test1 --rm mynginx:test cat /data/web/www/html/index.html
test
ADD
• ADD指令类似于COPY指令,ADD支持使用TAR文件和URL路径
• ADD <src> ... <dest> 或
• ADD ["<src>",... "<dest>"]
• 操作准则
• 同COPY指令
• 如果<src>为URL且<dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<dest>
;如果<dest>以/结尾,则文件名URL指定的文件将被直接下载并保存为<dest>/<filename>
• 如果<src>是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于“tar -x”命令;然而,通过URL获取到的tar文件将不会自动展开;
• 如果<src>有多个,或其间接或直接使用了通配符,则<dest>必须是一个以/结尾的目录路径 ;如果<dest>不以/结尾,则其被视作一个普通文件,<src>的内容将被直接写入到<dest>;
ADD http://nginx.org/download/nginx-10.1.0.tar.gz (只会下载,不会解压)
WORKDIR /usr/local/src/
ADD nginx-0.1.0.tar.gz ./ (会自动解压成目录,nginx-0.1.0.tar.gz为宿主机文件)
VOLUME
• 用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的 卷
• VOLUME <mountpoint> 或
• VOLUME ["<mountpoint>"]
• 如果挂载点目录路径下此前在文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
VOLUME /data/mysql/ (只能指定docker卷,不能指定宿主机)
ENV
• 用于为镜像定义所需的环境变量,并可被Dockerfile文件中位于其后的其它指令 (如ENV、ADD、COPY等)所调用
• 调用格式为{variable_name}
• ENV <key> <value> 或
• ENV <key>=<value> ...
• 第一种格式中,<key>之后的所有内容均会被视作其<value>的组成部分,因此,一次只能设置一个变量;
• 第二种格式可用一次设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果 <value>中包含空格,可以以反斜线()进行转义,也可通过对<value>加引号进行标识;另 外,反斜线也可用于续行;
• 定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能
ENV DOC_ROOT=/data/web/ \
WEB_SERVER_PACKGE="nginx-1.15.2"
COPY index.html ${DOC_ROOT:-/data/web/} (:-设置默认值)
WORKDIR /usr/local/
ADD ${WEB_SERVER_PACKGE}.tar.ge ./src/
# 根据-e 改变之前的变量
[root@localhost ~]# docker run -itd -e DOC_ROOT="test" --name mynginx -P mynginx:latest
RUN
• 用于指定docker build过程中运行的程序,其可以是任何命令
• RUN <command> 或
• RUN ["<executable>", "<param1>", "<param2>"]
• 第一种格式中,<command>通常是一个shell命令,且以“/bin/sh -c”来运行它,这意味着此进程 在容器中的PID不为1,不能接收Unix信号,因此,当使用docker stop <container>命令停止容器 时,此进程接收不到SIGTERM信号;
• 第二种语法格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的 <paramN>为传递给命令的选项或参数;然而,此种格式指定的命令不会以“/bin/sh -c”来发起 ,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令 依赖于此shell特性的话,可以将其替换为类似下面的格式。
• RUN ["/bin/sh", "-c", "<executable>", "<param1>"] • 注意:json数组中,要使用双引号
RUN cd /usr/local/src/ && \
rm -rf ./*
CMD
• 类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者 的运行时间点不同
• RUN指令运行于映像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新映像 文件启动一个容器时
• CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也 将终止;不过,CMD指定的命令其可以被docker run的命令行选项所覆盖
• 在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效
• CMD <command> 或
• CMD [“<executable>”, “<param1>”, “<param2>”] 或 • CMD ["<param1>","<param2>"]
• 前两种语法格式的意义同RUN
• 第三种则用于为ENTRYPOINT指令提供默认参数
CMD ["/bin/httpd","-f","-h","/data/web/html/"]
CMD /bin/httpd -f -h /data/web/html/
ENTRYPOINT
• 类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个 单独的可执行程序
• 与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的 参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定 指定的程序
• 不过,docker run命令的--entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序
• ENTRYPOINT <command>
• ENTRYPOINT ["<executable>", "<param1>", "<param2>"]
• docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到 ENTRYPOINT命令最后做为其参数使用
• Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效
ENTRYPOINT /bin/httpd -f -h /data/web/html/
#docker run --name mynginx -it --rm -P mynginx:latest ls /data/web/html
#上述启动方式相当于默认启动程序为 /bin/httpd -f -h /data/web/html/ ls /data/web/html
#docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到
ENTRYPOINT命令最后做为其参数使用说得就是上面这个意思
# --entrypoint string Overwrite the default ENTRYPOINT of the image
CMD ["/bin/httpd","-f","-h","/data/web/html/"]
ENTRYPOINT ["bin/sh","-c"]
#docker run --name mynginx -it --rm -P mynginx:latest "ls /data/web/html"
#此时会覆盖掉CMD的参数,除非使用--entrypoint
示例:
FROM nginx:1.14
LABEL maintainer="wsl <wsl@qq.com>"
ENV NGX_DOC_ROOT='/data/web/html/'
ADD index.html ${NGX_DOC_ROOT}
ADD entrypoint.sh /bin/
CMD ["usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
#############################
#!/bin/sh
#
cat > /etc/nginx/conf.d/www.conf << EOF
server {
server_name ${HOSTNAME};
listen ${IP:-0.0.0.0}:${PORT:-80};
root ${NGX_DOC_ROOT:-/usr/share/nginx/html};
}
EOF
exec "$@" #(将参数覆盖当前进程作为一个第一进程启动)
###############
docker run --name mynginx -e "PORT=8080" -it --rm -P mynginx:latest
#可以将PORT作为环境变量传入,并作用在nginx配置文件中
USER
• 用于指定运行image时的或运行Dockerfile中任何RUN、CMD或ENTRYPOINT 指令指定的程序时的用户名或UID
• 默认情况下,container的运行身份为root用户
• USER <UID>|<UserName>
• 需要注意的是,<UID>可以为任意数字,但实践中其必须为/etc/passwd中某用户的有效 UID,否则,docker run命令将运行失败
USER nginx
HEALTHCHECK
• healthcheck指令告诉docker如何测试容器以检查它是否仍在工作。
• 这可以检测到一些情况,例如web服务器陷入无限循环,无法处理新连接,即使服务器进程仍在运行。
• 健康检查指令有两种形式:
• HEALTHCHECK [OPTIONS] CMD命令(通过在容器内运行命令检查容器运行状况)
• HEALTHCHECK NONE(禁用从基本映像继承的任何healthcheck)
HEALTHCHECK 健康监测
--interval=DURATION(defailt:30s) 默认30秒监测一次,参数可以是5m
--timeout=DURATION(defailt:30s) 默认30秒超时
--start-period=DURATION(defailt:0s) 默认运行0秒后开始监测
--retries=N(defailt:3) 默认失败3次
响应值:
0表示健康
1表示不健康
2表示预留的没什么意义
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit1
ARG
• ARG指令定义了一个变量,用户可以通过使用-BuildAdgBuild命令使用BuildARGE.VARNAMEX==Value>标志,在生成时传递给生成器。
• 如果用户指定在DOCKFILE文件中未定义的生成参数,则生成将发出警告。
• 语法:arg<name>[=<default value>]
• dockerfile可以包含一个或多个arg指令。
• ARG指令可以可选地包括默认值:
• arg版本=1.14
• arg用户=magedu
ARG author="wsl <wsl@qq.com>"
LABEL maintainer = ${author}
docker build --build-arg author="yhf <yhf@qq.com>"
SHELL
• shell指令允许重写用于命令的shell形式的默认shell。
• Linux上的默认shell为[“/bin/sh”、“-c”],Windows上的默认shell为[“cmd”、“/s”、“/c”]。
• shell指令必须以json格式写入dockerfile中。
• 语法:shell[“executable”,“parameters”]
• shell指令可以多次出现。
• 每一条shell指令都会覆盖所有先前的shell指令,并影响所有后续指令。
STOPSIGNAL
• stopsignal指令设置将发送到容器以退出的系统调用信号。
• 这个信号可以是一个有效的无符号数,它匹配内核的SysCurl表中的一个位置,例如9,或者格式签名中的一• 个信号名,例如SIGKEY。
• 语法:STOPSIGNAL signal
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指令应该格外小心,因为新构建过程的上下文在缺少指 定的源文件时会失败
• 在别人基于你的镜像做镜像时会触发