Dockerfile文件与常用指令详解(2) Marathon

Dockerfile

1.基本结构

Dockerfile由一行行命令语句组成,并支持以#开头的注释行,如:

# This dockerfile uses the ubuntu image

# base image to use, set as the first line
FROM ubuntu:18.04

# maintainer info, username<email address>
MAINTAINER daviswen<daviswen@docker.com>

# commands to update the image
RUN echo "it's a dockerfile print..."

# if RUN cmd followed by several cmd, please merge to one RUN 
# cmd, and seperate with ";" or "&&"
RUN echo "1st print" && echo "2nd print"

# cmds when creating a new container
CMD /usr/sbin/nginx

其中,

  • FROM, 开始必须指定基于镜像的名称
  • MAINTAINER, 维护者的信息
  • RUN, 镜像的操作指令,对镜像执行跟随的命令,每运行RUN,镜像就增加一层,并commit
  • CMD, 指定运行容器的操作命令

接下来先来看看来自docker hub上的热门Dockerfile

基于buildpack-deps:jessie-scm基础镜像,制作一个GO语言的运行环境

FROM buildpack-deps:jessie-scm

# gcc fo cgo
RUN apt-get update && apt-get install -y --no-install-recommends g++ gcc libc6-dev make && rm -rf /var/lib/apt/lists*

ENV GOLANG_VERSION 1.6.3
ENV GOLANG_DOWNLOAD_RUL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 cdd5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aeb

RUN curl -fssL "$GOLANG_DOWNLOAD_RUL" -o golang.tar.gz && \
echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && tar -C /usr/local -xzf golang.tar.gz && rm golang.tar.gz

ENV GOPATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/bin" && chmod -R 777 "$GOPATH"
WORKDIR $GOPATH

COPY go-wrapper /usr/local/bin

2.指令说明

指令的一般格式为 INSTRUNCTION args, 指令包括FROM,MAINTAINER,RUN等,具体指令说明如下:

2.1 FROM

指定所创建镜像的基础镜像

指定所创建的镜像的基础镜像,如果本地不存在,则默认会去Docker Hub下载指定镜像。
  格式为:FROM,或FROM:,或FROM@
  任何Dockerfile中的第一条指令必须为FROM指令。并且,如果在同一个Dockerfile文件中创建多个镜像,可以使用多个FROM指令(每个镜像一次)。

2.2 MAINTAINER

指定维护者信息

e.g. MAINTAINER image_creator@docker.com

该信息将会写入生成镜像的Author属性域中。

2.3 RUN

运行命令,尽量合并层级

运行指定命令。
  格式为:RUN或RUN [“executable”,“param1”,“param2”]
注意:
后一个指令会被解析为json数组,所以必须使用双引号。
前者默认将在shell终端中运行命令,即/bin/sh -c;后者则使用exec执行,不会启动shell环境。
指定使用其他终端类型可以通过第二种方式实现,例如:
RUN ["/bin/bash","-c",“echo hello”]
每条RUN指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可以使用\换行。

例如:

RUN apt-get update && apt-get install -y libsnappy-dev zliblg-dev libbz2-dev && rm -rf /var/cache/apt

2.4 CMD

指定启动容器时默认执行的命令,多个CMD只执行最后一个,有多个,可合并

支持三种格式:

1.CMD ["executable","param1","param2"] 使用exec执行,是推荐使用的方式;
2.CMD param1 param2 在/bin/sh中执行,提供给需要交互的应用;
3.CMD ["param1","param2"] 提供给ENTRYPOINT的默认参数。

每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一条会被执行。入股用户启动容器时指定了运行的命令(作为run的参数),则会覆盖掉CMD指定的命令。

2.5 LABEL

指定生成镜像的元数据标签信息

例如:

LABEL version="1.0"

2.6 EXPOSE

声明镜像内服务所监听的端口

格式为:EXPOSE […]
  例如:

EXPOSE 22 80 443 3306

注意:

该命令只是起到声明,并不会自动完成端口映射。
在容器启动时需要使用-P(大写P),Docker主机会自动分配一个宿主机未被使用的临时端口转发到指定的端口;使用-p(小写p),则可以具体指定哪个宿主机的本地端口映射过来。

2.7 ENV

指定环境变量

在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在。
  格式为:ENV 或ENV=…。

例如:

ENV GOLANG_VERSION 1.6.3
ENV GOLANG_DOWNLOAD_RUL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 cdd5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aeb

RUN curl -fssL "$GOLANG_DOWNLOAD_RUL" -o golang.tar.gz

另一种写法:

ENV GOLANG_VERSION=1.6.3

指令指定的环境变量在运行时可以被覆盖掉,如docker run --env = built_image。

2.8 ADD

复制指定的路径下的内容到容器中的路径下,可以为URL;如果为tar文件,会自动解压到路径下

ADD *.c /code/

ADD app.tar.gz /app/app

# ADD <src> <dest>
# src部分是是你Dockerfile的相对路径

2.9 COPY

复制本地主机的路径下的内容到容器中的路径下;一般情况下推荐使用COPY而不是ADD

目标路径不存在时,会自动创建。路径同样支持正则。当使用本地目录为源目录时,推荐使用COPY。

如果COPY的是压缩包不会帮你解压。

2.10 ENTRYPOINT

指定镜像的默认入口

该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。
  支持两种格式:

1.ENTRYPOINT ["executable","param1","param2"] (exec调用执行);
2.ENTRYPOINT command param1 param2(shell中执行)。

此时,CMD指令指定值将作为根命令的参数。
  每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个有效。
  在运行时可以被–entrypoint参数覆盖掉,如docker run --entrypoint。

2.11 VOLUME

创建数据挂载点

格式为:

VOLUME ["/data"]

VOLUME ["/data","/data/etc"]

  可以从本地主机或者其他容器挂载数据卷,一般用来存放数据库和需要保存的数据等。

在启动容器的时候Docker会在/var/lib/docker/的下一级目录下创建一个卷,以保存你在容器中产生的数据。若没有申明则不会创建。(可以把此指令看成shell中的mkdir)此指令不是独立数据卷,数据会随着容器的停止而消失,如果想数据持久化,请参考docker 简单命令 在run启动容器是加-V 参数!

2.12 USER

指定运行容器时的用户名或UID

后续的RUN等指令也会使用特定的用户身份。
  格式为:USER daemon
  当服务不需要管理员权限时,可以通过该指令指定运行用户,并且可以在之前创建所需要的用户。例如:

RUN groupadd -r nginx && useradd -r -g nginx nginx

要临时获取管理员权限可以用gosu或者sudo。

2.13 WORKDIR

配置工作目录

为后续的RUN、CMD和ENTRYPOINT指令配置工作目录。
  格式为:WORKDIR /path/to/workdir。
  可以使用多个WORKDIR指令,后续命令如果参数是相对的,则会基于之前命令指定的路径,可以理解为shell的cd。例如:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

# 最终路径为/a/b/c

2.14 ARG

指定镜像内使用的参数(例如版本号信息等)

这些参数在执行docker build命令时才以–build-arg=格式传入。
  格式为:ARG[=]。
  则可以用docker build --build-arg=来指定参数值。

2.15 ONBUILD

配置当前所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作的命令格式为:ONBUILD [INSTRUCTION]。
  例如Dockerfile使用如下的内容创建了镜像image-A:

[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

如果基于image-A镜像创建新的镜像时,新的Dockerfile中使用FROM image-A指定基础镜像,会自动执行ONBUILD指令的内容,等价于在后面添加了两条指令:

FROM image-A

# Automatically run the following
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src

使用ONBUILD指令的镜像,推荐在标签中注明,例如:ruby:1.9-onbuild。

2.16 STOPSIGNAL

容器退出的信号

例如:

STOPSIGNAL singnal

2.17 HEALTHCHECK

如何进行健康检查

格式有两种:

1.HEALTHCHECK [OPTIONS] CMD command    :根据所执行命令返回值是否为0判断;
2.HEALTHCHECK NONE              :禁止基础镜像中的健康检查。

2.18 SHELL

指定使用SHELL时的默认SHELL类型

格式为: SHELL [“executable”,“parameters”]
  默认值为 [“bin/sh”,"-c"]。

3.创建镜像

编写Dockerfile之后,可以通过docker build命令来创建镜像。
  基本的docker build [选项] 内容路径,该命令将读取指定路径下(包括子目录)的Dockerfile,并将该路径下的所有内容发送给Docker服务端,由服务端来创建镜像。因此除非生成镜像需要,否则一般建议放置Dockerfile的目录为空目录。

1.如果使用非内容路径下的Dockerfile,可以通过-f选项来指定其路径;

2.要指定生成镜像的标签信息,可以使用-t选项。

例如:指定Dockerfile所在路径为 /tmp/docker_builder/,并且希望生成镜像标签为build_repo/first_image,可以使用下面的命令:

docker build -t build_repo/first_image /tmp/docker_builder

4.其他tips

4.1 使用 .dockerignore文件

以通过 .dockeringore文件(每一行添加一条匹配模式)来让Docker忽略匹配模式路径下的目录和文件。例如:

# comment
    */tmp*
    */*/tmp*
    tmp?
    ~*

4.2 Dockerfile编写小结

从需求出发,定制适合自己需求、高效方便的镜像,可以参考他人优秀的Dockerfile文件,在构建中慢慢优化Dockerfile文件:

1.精简镜像用途:                 尽量让每个镜像的用途都比较集中、单一,避免构造大而复杂、多功能的镜像;
2.选用合适的基础镜像:            过大的基础镜像会造成构建出臃肿的镜像,一般推荐比较小巧的镜像作为基础镜像;
3.提供详细的注释和维护者信息:     Dockerfile也是一种代码,需要考虑方便后续扩展和他人使用;
4.正确使用版本号:               使用明确的具体数字信息的版本号信息,而非latest,可以避免无法确认具体版本号,统一环境;
5.减少镜像层数:                减少镜像层数建议尽量合并RUN指令,可以将多条RUN指令的内容通过&&连接;
6.及时删除临时和缓存文件:        这样可以避免构造的镜像过于臃肿,并且这些缓存文件并没有实际用途;
7.提高生产速度:                合理使用缓存、减少目录下的使用文件,使用.dockeringore文件等;
8.调整合理的指令顺序:           在开启缓存的情况下,内容不变的指令尽量放在前面,这样可以提高指令的复用性;
9.减少外部源的干扰:             如果确实要从外部引入数据,需要制定持久的地址,并带有版本信息,让他人可以重复使用而不出错

5.启动Dockerfile创建新镜像

在编写好Dockerfile文件后,我们可以通过docker build命令来创建新的镜像。通常我们在某个文件夹下放置 Dockerfile 文件,进入当前的文件夹:

# docker build .
# "."表示在当前目录下读取Dockerfile文件信息

或者,我们也可以指定新镜像及tag标签信息,使用 -t 参数
# docker build -t newImage:tag dockerfile_path
# 指定绝对或相对路径

以我用Dockerfile创建镜像为例:

整理自:https://blog.csdn.net/weixin_43551152/article/details/85702315

原文地址:https://www.cnblogs.com/davis12/p/14312256.html