10.Docker File制作镜像

Posted gmiaomiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.Docker File制作镜像相关的知识,希望对你有一定的参考价值。

Docker File构建镜像

关于DockerFile

在Docker中创建镜像最常用的方式,就是使用Dockerfile。Dockerfile是一个Docker镜像的描述文件,我们可以理解成火箭发射的A、B、C、D…的步骤。Dockerfile其内部包含了一条条的指令,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

技术图片

Dockerfile结构大致分为四个部分:

  1. 基础镜像信息
  2. 维护者信息
  3. 镜像操作指令
  4. 容器启动时执行指令

Dockerfile每行支持一条指令,每条指令可带多个参数,支持使用以#号开头的注释。下面会对上面使用到的一些常用指令做一些介绍。

Dockerfile常用指令

指令 对象 含义
FROM 镜像 指定新镜像所基于的镜像,必须为第一条指令
MAINTAINER 名字 新镜像的维护人信息
RUN 命令 在所基于的镜像上执行命令,并提交到新镜像中
EXPOSE 端口号 指定新镜像加载到Docker时开启的端口号
ENV 环境变量 变量值 设置一个环境变量的值,会被后面的RUN使用
ADD 源文件/目录 目标文件/目录 将源文件复制到目标文件,源文件要与Docker位于同一目录下,或者为一个URL
COPY 源文件/目录 目标文件/目录 将本地主机上的源文件/目录复制到目标地点,源文件/目录要与Dockerfile在同一目录下
VOLUME ["目录"] 在容器中创建一个挂载点
USER 用户名 /UID 指定运行容器时的用户
WORKDIR 路径 为后续的RUN、CMD、ENTRYPOINT指定工作目录
ONBUILD 命令 指定所生成的镜像作为一个基础镜像时所要运行的命令
CMD ["要运行的程序","参数1","参数2"] 指定启动容器时运行的命令或脚本,只能有一条CMD命令,多条时只有最后一条被执行

来一张通俗易懂的全景图:

技术图片

FROM

指明构建的新镜像是来自于哪个基础镜像

FROM <repository>[:<tag>]
#较为安全
FROM <repository>@<digest>
#<repository>:指定作为base image的名称
#<tag>:base image的标签,为可选性,省略时默认为latest
#<digest>:哈希码

例如:

FROM centos:7

MAINTAINER(depreacted)

指明镜像维护着及其联系方式(一般是邮箱地址),已被LABEL所替代

MAINTAINER<author‘s detail>

例如:

MAINTAINER "MiaosenG <MiaosenG@MiaosenG.com>"

不过,MAINTAINER并不推荐使用,更推荐使用LABEL来指定镜像作者,例如:

LABEL maintainer="MiaosenG <MiaosenG@MiaosenG.com>"

RUN

#第一种格式<command>通常是一个shell命令,且以"/bin/sh -c"运行
#此进程在容器的PID不为1,当使用docker stop <container>命令停止容器时,此进程接收不到SIGTERM信号
RUN <command>
#第二种格式中的参数是一个JSON格式数组,其中<executable>为要运行命令,<paramN>为传递命令选项或参数
RUN ["<executable>","<param1>","<param2>"]
#此格式不会以"/bin/sh -c"运行,无法使用变量替换或通配符等shell操作符,可写成
RUN ["/bin/sh" "-c","<exrcutable>","<param1>"]

构建镜像时运行的Shell命令,针对于基础镜像,仅可使用基础镜像环境,和命令;

例如:

RUN ["yum", "install", "httpd"]
RUN yum install httpd

jason数组中,要是用双引号

CMD

#意义等同RUN
CMD <command>
CMD ["<executable>","<param1>","<param2>"]
#第三种用于ENTRYPOINT指令提供默认参数
CMD ["<param1>","<param2>"]

启动容器时执行的Shell命令,针对镜像默认运行命令,多个CMD仅最后一个生效

例如:

CMD ["-C", "/start.sh"] 
CMD ["/usr/sbin/sshd", "-D"] 
CMD /usr/sbin/sshd -D

EXPOSE

EXPOSE <port>[/<protocol>][ <port>[/<protocol>]...]
#<protocol>用于指定传输层协议,可为tcp或udp,默认为TCP

声明容器运行的(待暴露)默认服务端口,但运行容器时不会暴露该端口;需要配合docker run -P命令,会暴露DockerFile内写定的全部端口

例如:

EXPOSE 11211/udp 11211/tcp

ENV

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

设置环境内环境变量,可被文件中位于其后的其他指令所调用

例如:

#单一变量赋值
ENV mysql_ROOT_PASSWORD 123456
#多变量赋值
ENV JAVA_HOME=/usr/local/jdk1.8.0_45

#使用
ENV DOC_ROOT=/data/web/html/     WEB_SERVER_PACKAGE="nginx-1.15.2"
COPY index.html ${DOC_ROOT:-/data/web/html}	#设定默认值
ADD ${WEB_SERVER_PACKAGE}.tar.gz /usr/local/src/

第一种格式,<key>之后所有内容均被视为<value>

第二种格式,<value>中包含空格,可以利用进行转义或换行,也可以加""进行表示

可配合docker run -e设定变量值使用,在初始化运行容器时改变默认设定变量

ADD

拷贝文件或目录到镜像中,例如:

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

支持URL路径,用法同COPY

#展开文件
ADD nginx-1.15.2.tar.gz /usr/local/src/
#仅下载不解压
ADD http://nginx.org/download/nginx-1.15.2.tar.gz /usr/local/src/

如果<src>为URL

  • <dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<dest>;
  • <dest>以/结尾,则文件名URL指定的文件将被直接下载并保存为<dest>/<filename>

如果<src>是一个

  • 本地系统上的压缩格式的tar文件;他将会被展开为一个目录,类似于tar -x
  • URL获取的tar文件;将不会被展开

如果<src>为多个,或期间使用了通配符,则<dest>必须是一个以/的目录路径;

如果不以/结尾,则其被视作一个普通文件,<src>的内容将被直接写入到<dest>

COPY

拷贝主机文件或目录到镜像中

COPY <src>...<dest>
COPY ["<src>"..."<dest>"]
#<src>:需要复制的源文件,支持通配符
#<dest>:目标路径;建议使用绝对路径;否则,COPY指定则以WORKDIR为其其实路径

用法同ADD,只是不支持自动下载和解压,例如:

COPY index.html /data/web/html
COPY yum.repos.d /etc/yum.repos.d

<src>必须是build上下文中的路径,不能是其父目录中的文件

如果<src>是目录,则其内部文件或子目录会被递归复制,但<src>目录自身不会被复制

如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且必须以/结尾

如果<dest>实现不存在,他将会被自动创建,这包括其父目录路径

ENTRYPOINT

ENTRYPOINT <command>
ENTRYPOINT ["<executable>","<param1>","<param2>"]

启动容器时执行的Shell命令,同CMD类似,只是由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序,例如:

ENTRYPOINT ["/bin/bash", "-C", "/start.sh"]
ENTRYPOINT /bin/bash -C ‘/start.sh‘

PS:Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效。

除非使用docker run --entrypoint string才可强制覆盖dockerfile内有ENTRYPOINT命令

当CMD与ENTRYPOINT同时出现在Dockerfile中;CMD使用第三种写法,为ENTRYPOINT指令提供默认参数

CMD ["/bin/httpd","-f","-h","/data/web/html"]
ENTRYPOINT ["/bin/sh","-c"]

但当使用docker run对容器内部传参或输入指令,会对CMD进行覆盖,而不会覆盖ENTRYPOINT

VOLUME

VOLUME <mountpoint>
VOLUME ["<mountpoint>"]

指定容器挂载点到宿主机自动生成的目录或其他容器

例如:

VOLUME ["/data/mysql/"]

PS:一般不会在Dockerfile中用到,更常见的还是在docker run的时候指定-v数据卷。

USER

USER <UID>|<UserName>

为RUN、CMD和ENTRYPOINT执行Shell命令指定运行用户,默认容器中使用root用户

例如:

USER <user>[:<usergroup>]
USER <UID>[:<UID>]
USER miaoseng

UID可以为任意数字,但实践中其必须为/etc/passwd(容器)中某用户的有效UID,否则docker run命令将失败

WORKDIR

WORKDIR <dirpath>

为RUN、CMD、ENTRYPOINT以及COPY和AND设置工作目录,理解为cd命令

例如:

WORKDIR /usr/local/src/
ADD nginx-1.15.2.tar.gz ./
#等效于
ADD nginx-1.15.2.tar.gz /usr/local/src/

HEALTHCHECK

HEALTHCHECK [options] CMD command

告诉Docker如何测试容器以检查它是否仍在工作,即健康检查,例如:

HEALTHCHECK --interval=5m --timeout=3s --retries=3     CMD curl -f http:/localhost/ || exit 1

其中,一些选项的说明:

  • --interval=DURATION (default: 30s):每隔多长时间探测一次,默认30秒
  • -- timeout= DURATION (default: 30s):服务响应超时时长,默认30秒
  • --start-period= DURATION (default: 0s):服务启动多久后开始探测,默认0秒
  • --retries=N (default: 3):认为检测失败几次为宕机,默认3次

  一些返回值的说明:

  • 0:容器成功是健康的,随时可以使用
  • 1:不健康的容器无法正常工作
  • 2:保留不使用此退出代码

SHELL

修改shell类型

#Linux
SHELL ["/bin/sh","-c"]
#Windows
SHELL ["cmd","/S","/C"]

STOPSIGNAL

定义停止信号

STOPSIGNAL signal

ARG

AGE <name>[=<default value>]

在构建镜像时,指定一些参数,例如:

FROM centos:7
ARG author="MiaosenG <miaosen@MiaosenG.com>"
LABEL maintainer="${author}"

这时,我们在docker build时可以带上自定义参数user了,如下所示:

docker build --build-arg author=Tony Dockerfile .

ONBUILD

ONBUILD <INSTRUCTION>

用于在Dockerfile中定义一个触发器,延迟触发;当其他用户,基于含有ONBUILD镜像构建新镜像,再次构建并运行build时执行命令;留下后门

ONBUILD不可自我嵌套,且不会触发FROM和MAINTAINER指令;通常使用RUN和ADD,使用ADD,COPY时可能缺少指定文件;无法拷贝

CMD与RUN区别

指令 CMD RUN
区别 基于Dockerfile构建出新映像文件启动一个容器时 运行于映像文件构建过程中
可被docker run命令选项进行覆盖,针对镜像默认运行命令 使用基础镜像环境,和命令
可存在多个CMD仅最后一个生效 可运行多个

例如:

Dockerfile1

vim Dockerfile
FROM busybox
LABEL maintainer="MiaosenG <miaoseng@miaoseng.com>" app="http"

ENV WEB_DOC_ROOT="/data/web/html/"

RUN mkdir -p $ENV WEB_DOC_ROOT && echo ‘<h1>hello busybox httpd server</h1>‘ > $ENV WEB_DOC_ROOT/indec.html

CMD /bin/httpd -f -h ${WEB_DOC_ROOT}

运行后查看容器内PID=1进程为/bin/httpd -f -h /data/web/html/

Dockerfile2

vim Dockerfile
FROM busybox
LABEL maintainer="MiaosenG <miaoseng@miaoseng.com>" app="http"

ENV WEB_DOC_ROOT="/data/web/html/"

RUN mkdir -p $ENV WEB_DOC_ROOT && echo ‘<h1>hello busybox httpd server</h1>‘ > $ENV WEB_DOC_ROOT/indec.html

CMD ["/bin/httpd","-f","-h","${WEB_DOC_ROOT}"]

运行后报错httpd:can‘t change directory to ‘${WEB_DOC_ROOT}‘: No such file or directory

以上是关于10.Docker File制作镜像的主要内容,如果未能解决你的问题,请参考以下文章

10.Docker技术入门与实战 --- 为镜像添加SSH服务

Docker 标准化镜像制作

10.Docker-----安装初步使用镜像Dockerfile常用指令通过Dockerfile文件封装nginx镜像并优化

PHP常用代码片段

mac上制作u盘启动盘

python 用于在终端中运行的sublime text 3的简单代码片段制作工具