使用Dockerfile创建镜像

使用Dockerfile创建镜像

Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像。

Dockerfile指令及说明
指令 说明
ARG 定义创建镜像过程中使用的变量
FROM 指定所创建镜像的基础镜像
LABEL 为 生成的镜像添加元数据标签信息
EXPOSE 声明镜像内服务监听的端口
ENV 指定环境变量
ENTRYPOINT 指定镜像的默认入口命令
VOLUME 创建一个数据卷挂载点
USER 指定运行容器时的用户名或UID
WORKDIR 配置工作目录
ONBUILD 创建子镜像时指定自动执行的操作指令
STOPSIGNAL 指定退出的信号值
HEALTHCHECK 配置所启动容器如何进行健康检查
SHELL 指定默认shell类型
RUN 运行指定命令
CMD 启动容器时指定默认执行的命令
ADD 添加内容到镜像
COPY 复制内容到镜像
  1. ARG
    格式为ARG [=]。
    当镜像编译成功后,ARG指定的变量将不再存在(ENV指定的变量将在镜像中保留。)
    Docker内置了一些镜像创建变量,用户可以直接使用而无须声明,包括HTTP_PROXY,HTTPS_PROXY,FTP_PROXY,NO_PROXU。

  2. FROM
    格式为FROM [ AS ]或FROM : [ AS ]或FROM @ [ AS ]
    任何Dockerfile中的第一条指令必须为FROM指令。并且,如果在同一个Dockerfile中创建多个竟像时,可以使用多个FROM指令。

  3. LABEL
    为生成的镜像添加元数据标签,这些可以辅助过滤出特定镜像。
    格式为LABEL =
    例如:
    LABEL author=“xxxxxx”

  4. EXPOSE
    格式为EXPOSE [/]
    例如:
    EXPOSE 22 80 443
    该指令只是起到声明作用,并不会自动完成端口映射。

  5. ENV
    格式为 ENV 或 ENV =
    例如:
    ENV APP_VERSION=1.0.0
    ENV PATH $PATH:/usr/local/bin

  6. ENTRYPOINT
    指定镜像的默认入口命令,该入口命令会在启动容器时作为跟命令来执行,所有传入值作为该命令的参数。
    支持两种格式:

    ENTRYPOINT [“executable”,“param1”,“param2”] :exec调用执行。

    ENTRYPOINT command param1 param2: shell执行
    此时,CMD指令指定值将作为跟命令参数
    每个Dockerfile中只能由一个ENTRYPOINT,当指定多个时,只有最有一个起效。

  7. VOLUME
    创建一个数据挂载点
    格式为VALUME ["/data"]
    运行容器时可以从本地主机或其他容器挂载数据卷。

  8. USER
    格式为 USER daemon
    当服务不需要管理员权限时,可以通过该命令指定运行用户,并且可以在Dockerfile中创建所需要的用户。例如:
    RUN groupadd -r postgres && useradd --no-log-init -r -g postgres postgres
    要临时获取管理员权限可以使用gosu命令

  9. WORKDIR
    配置工作目录
    格式 WORKDIR /path/to/workdir
    可以使用多个WORKDIR指令,后续命令如果参数时相对路径,则会基于之前命令指令的路径。
    例如:
    WORKDIR /a
    WORKDIR b
    WORKDIR c
    RUN pwd
    最终路径为 /a/b/c
    因此,为了避免出错,推荐WORKDIR使用绝对路径

  10. ONBUILD
    配置当所创建的镜像作为其他镜像的基础镜像的时候,所执行创建操作指令。
      格式为:ONBUILD [INSTRUCTION]。
      例如Dockerfile使用如下的内容创建父镜像ParentImage,指定ONBUILD指令:

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

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

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

    由于ONBUILD是隐式执行的,推荐在使用它的标签中进行标注,例如ruby:2.1-onbuild

  11. STOPSIGNAL
    指定所创建镜像启动的容器接收退出的信号值。例如:
    STOPSIGNAL singnal

  12. HEALTHCHECK
    配置所启动容器如何进行健康检查(如何判断是否健康),自Docker 1.12开始支持。
    格式有两种:

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

[OPTION]支持如下参数:

​ --inerval=DURATION (默认为:30s):多久检查一次;
​ --timeout=DURATION (默认为:30s):每次检查等待结果的超时时间;
​ --retries=N    (默认为:3):如果失败了,重试几次才最终确定失败。

  1. SEHELL指定其他命令使用shell时的默认shell类型。
    格式为: SHELL [“executable”,“parameters”]
    默认值为 [“bin/sh”,"-c"]。
    注意:
    对于Windows系统,Shell路径中使用了""作为分隔符,建议在Dockerfile开头添加# escape=`来指定转义符。

  2. 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/lib/apt/lists/*
    
  3. CMD
    CMD指令用来指定启动容器时默认执行的命令。它支持三种格式:

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

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

  4. ADD该指令将复制指定的路径下的内容到容器中的路径下。
    格式为:ADD
    其中可以使Dockerfile所在目录的一个相对路径(文件或目录),也可以是一个URL,还可以是一个tar文件(如果是tar文件,会自动解压到路径下)。可以使镜像内的绝对路径,或者相当于工作目录(WORKDIR)的相对路径。路径支持正则表达式,例如:

    ADD *.c /code/
    
  5. COPY
    复制本地主机的(为Dockerfile所在目录的一个相对路径、文件或目录)下的内容到镜像中的下。目标路径不存在时,会自动创建。路径同样支持正则。
      格式为:COPY
      当使用本地目录为源目录时,推荐使用COPY。

创建镜像

​ 编写完成 Docker企le 之后,可以通过 docker [image] build 命令来创建镜像 。

​ 基本的格式为 docker build [OPTIONS] PATH | URL I - 。

​ 该命令将读取指定路径下(包括子目录)的 Dock巳rfile ,并将该路径下所有数据作为上下文( Context)发送给 Docker 服务端 。 Docker 服务端在校验 Dockerfile 格式通过后,逐条执行其中定义的指令,碰到 ADD 、 COPY 和 RUN 指令会生成一层新的镜像。 最终如果创建镜像成功,会返回最终镜像的 ID 。

​ 如果上下文过大, 会导致发送大量数据给服务端,延缓创建过程 。 因此除非是生成镜像所必需的文件,不然不要放到上下文路径下 。 如果使用非上下文路径下的 Dockerfile ,可以通过 -f 选项来指定其路径 。

​ 要指定生成镜像的标签信息,可以通过 - t 选项 。 该选项可以重复使用多次为镜像一次添加多个名称 。

​ 例如,上下文路径为/tmp/docker_builder/,并且希望生成镜像标签为 builder/first_image:1.0.0,可以使用下面的命令 :

​ docker build -t builder/first_image:l.0.0 /tmp/docker_builder/

选择父镜像

​ 大部分情况下,生成新的镜像都需要通过 FROM 指令来指定父镜像。 父镜像是生成镜像的基础 ,会直接影响到所生成镜像的大小和功能 。用户可 以选择两种镜像作为父镜像,一种是所谓的基础镜像( baseimage),另外一种是普通的镜像(往往由第三方创建,基于基础镜像) 。

​ 基础镜像 比较特殊,其 Dockerfile 中往往不存在 FROM 指令,或者基于 scratch 镜像(FROM scratch ),这意味着其在整个镜像树中处于根的位置 。

​ 下面的 Dockerfile 定义了一个简单的基础镜像,将用户提前编译好的二进制可执行文件binary 复制到镜像中,运行容器时执行 binary 命令:
​ FROM scratch
​ ADD binary /
​ CMD ["binary "]

​ 普通镜像也可以作为父镜像来使用, 包括常见的 busybox 、 debian 、 ubuntu 等

使用 .dockerignore 文件

可 以通过 .dockerignore 文件(每一行添加一条匹配模式)来让 Docker 忽略匹配路径或文件,在创建镜像时候不将无关数据发送到服务端。

例如下面的例子中包括了 6 行忽略的模式(第一行为注释):

/temp
//temp*
tmp?
-*
Dockerfile
!README.md

  • dockerignore文件中模式语法支持Golang风格的路径正则格式:
  • "* "表示任意多个字符
  • "?"代表单个字符
  • "!"表示不匹配

多步骤创建

自17.05版本开始,Docker支持多步骤创建(Multi-stage build)特性,可以精简最终生成的镜像大小。

对于需要编译的应用(如 C、Go或Java语言等)来说,通常情况下至少需要准备两个环境的Docker镜像:

  • 编译环境镜像:包括完整的编译引擎、依赖库等,往往比较庞大。作用是编译应用为二进制文件
  • 运行环境镜像:利用编译好的二进制文件,运行应用,由于不需要编译环境,体积较小

使用多步骤创建,可以保证最终生成的运行环境镜像保持精简的情况下,使用单一的Dockerfile,降低维护复杂度。

以Go语言应用为例。创建干净目录,进入到目录中,创建main.go文件,内容为:

//main.go will output "hello,Docker"

package main

import (
	"fmt"
)
func main() {
    	fmt.Println("Hello,Docker")
}

闯进Dockerfile,使用golang:1.9镜像编译应用二进制文件为app,使用精简的镜像alpine:latest作为运行环境。Dockerfile完整内容为:

FROM golang:1.9 as builder # defin stage name as builder
RUN mkdir -p /go/src/test
WORKDIR /go/src/test
COPY main.go .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/test/app . #copy file from the builder stage
CMD ["./app"]

执行如下命令创建容器

[root@study ~ 20:13:39]# docker build -t yeasy/test-multistage:latest .
Sending build context to Docker daemon  470.8MB
Step 1/10 : FROM golang:1.9 as builder
 ---> ef89ef5c42a9
Step 2/10 : RUN mkdir -p /go/src/test
 ---> Using cache
 ---> 66feda4edc16
Step 3/10 : WORKDIR /go/src/test
 ---> Using cache
 ---> 5945c2d35d88
Step 4/10 : COPY main.go .
 ---> Using cache
 ---> 0fc82e8f2861
Step 5/10 : RUN CGO_ENABLED=0 GOOS=linux go build -o app .
 ---> Using cache
 ---> a7afbb419a38
Step 6/10 : FROM alpine:latest
 ---> 961769676411
Step 7/10 : WORKDIR /root/
 ---> Using cache
 ---> 396b73284595
Step 8/10 : RUN apk --no-cache add ca-certificates
 ---> Using cache
 ---> dfd7ebe9441f
Step 9/10 : COPY --from=builder /go/src/test/app .
 ---> Using cache
 ---> 7b724eed6dfa
Step 10/10 : CMD ["./app"]
 ---> Using cache
 ---> a9363c670d62
Successfully built a9363c670d62
Successfully tagged yeasy/test-multistage:latest

[root@study ~ 20:15:06]# docker images | grep "yeasy/test-multistage"
yeasy/test-multistage         latest              a9363c670d62        About a minute ago   7.99MB
[root@study ~ 20:15:10]# docker run --rm yeasy/test-multistage
Hello,Docker

你可能感兴趣的:(docker)