Docker学习⑤

使用Dockerfile创建镜像

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

基本结构

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

一般而言,Dockerfile主体内容分为四部分:

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

例:一个简单的示例

【文档解析】

首行可以通过注释来指定解析器命令,后续通过注释说明镜像的相关信息。主体部分首先使用FROM指定指明所基于的镜像名称,接下来一般是使用LABEL指令说明维护者信息。后面则是镜像操作指令,例如RUN指令对镜像执行跟随的命令。每运行一行RUN指令,镜像添加新的一层,并提交。最后是CMD指令,来指定运行容器时的操作指令。

例:下面是Docker Hub上两个热门镜像nginx和Go的Dockerfile例子

  • 第一个是在debian:jessie基础镜像基础上安装Nginx环境,从而创建一个新的nginx镜像:
FROM debian:jessie

LABEL maintainer docker_user<[email protected]>

ENV NGINX_VERSION 1.10.1-1~jessie

Run apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 \
    && echo "deb http://nginx.org/packages/debian/ jessie nginx" >> /etc/apt/source.list \
        && apt-get update \
        && apt-get install --no-install-recommends --no-install-suggests -y \
        ca-certificates \
        nginx=$(NGINX_VERSION) \
        nginx-module-xslt \
        nginx-module-geoip \
        nginx-module-image-filter \
        nginx-module-perl \
        nginx-module-njs \
        gettext-base \
        && rm -rf /var/lib/apt/lists/*

#forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80 443

CMD ["nginx","-g","daemon off;"]
  • 第二个是基于buildpack-deps:jessie-scm基础镜像,安装Golang相关环境,只做一个Go语言的运行环境镜像:
FROM buildpack-deps:jessie-scm

#gcc for 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_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 cdde5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aeb

RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -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 /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH

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

COPY go-wrapper /usr/local/bin/

指令说明

Dockerfile中指令的一般格式为INSTRUCTION arguments,包括“配置指令”(配置镜像信息)和“操作指令”(具体执行操作),参见表8-1。

  • 配置指令

1、ARG:定义创建镜像过程中使用的变量

格式:ARG <name> [=<default value>]

在执行docker build时,可以通过-build-arg[=]来为变量赋值。当镜像编译成功后,ARG指定的变量将不再存在(ENV指定的变量将在镜像中保留)

2、FROM:指定所创建镜像的基础镜像

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

任何Dockerfile中第一条指令必须为FROM指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令(每个镜像一次)。

为了保证镜像精简,可以使用体积较小的镜像如:

  • Alpine;
  • Debian;

3、LABEL:可以为生成的镜像添加元数据标签信息。这些信息可以用来辅助过滤出特定镜像。

格式:LABEL <key>=<value> <key>=<value> <key>=<value>...

例:

LABEL version="1.0.0-rc3"
LABEL author="yeasy@github" date="2020-01-01"
LABEL description="This text illistrates that label-values can span multiple lines."

4、ERPOSE:声明镜像内服务监听的端口

格式:EXPOSE <port> [<port>/<protocol>...]

【注】

  1. 该指令只是起到声明作用,并不会自动完成端口映射;
  2. 若要映射端口出来,在启动容器时可以使用-P参数(Docker主机会自动分配一个宿主机的临时端口)或-p HOST_PORT:CONTAINER_PORT参数(具体指定所映射的本地端口)

5、ENV

指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在

格式:ENV <key> <value> 或 ENV <key>=<value>...

例:

ENV APP_VERSION=1.0.0
ENV APP_HOME=/usr/local/app
ENV PATH $PATH:/usr/local/bin

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

【注】

注意当一条ENV指令中同时为多个环境变量赋值并且值也是从环境变量读取时,会为变量都赋值后再更新。如下面指令,最终结果为key1=value1 AND key2=value2:

ENV key1=value2
ENV key1=value1 key2=${key1}

6、ENTRYPOINT:指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。

格式:

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

此时,CMD指令指定值将作为根命令的参数。

【注】每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个起效。在运行时候,可被--entrypoint覆盖。

7、VOLUME:创建一个数据挂载点

格式:VOLUME ["/data"]

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

8、USER:指定运行容器时的用户名或UID,后续的RUN等指令也会使用指定的用户身份

格式:USER daemon

当服务不需要管理员权限时,可以通过该命令指定运行用户,并且可以在Dockerfile中创建所需要的用户。

例:

RUN groupadd -r postgres && useradd --no-log-init -r -g postgres postgres

【注】要临时获取管理员权限可以使用gosu命令。

9、WORKDIR:为后续的RUN、CMD、ENTRYPOINT指令配置工作目录

格式:WORKDIR /path/to/workdir

可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。

例:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

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

【注】为了避免出错,推荐WORKDIR指令中只使用绝对路径。

10、ONBUILD:指定当基于所生成镜像创建子镜像时,自动执行的操作指令

格式:ONBUILD [INSTRUCTION]

11、STOPSIGNAL:指定所创建镜像启动的容器接收退出的信号值

格式:STOPSIGNAL signal

12、HEALTHCHECK:配置所启动容器如何进行健康检查(如何判断健康与否)

格式:HEALTHCHECK [OPTIONS] CMD command:根据所执行指令返回值是否为0来判断;

           HEALTHCHECKK NONE:禁止基础镜像中的健康检查;

[OPTIONS]参数解析:

  1. --interval=DURATION (default:30s):过多久检查一次;
  2. --timeout=DURATION (dafalut:30s):每次检查等待结果的超时;
  3. -retries=N (default:3):如果失败了,重试几次才最终确定失败;

13、SHELL:指定其他命令使用shell时的默认shell类型

格式:SHELL ["executable","parameters"]

默认值为["/bin/sh","-c"]

  • 操作指令

1、RUN:运行指定命令

格式:RUN <command>RUN ["executable","param1","param2"]

【注】

  1. 后者指令会被解析为JSON数组,因此必须使用双引号;
  2. 前者默认将在shell终端中运行命令,即/bin/sh -c;
  3. 后者使用exec执行,不会启动shell环境;

指定使用其他终端类型课可以通过第二种方式实现:RUN ["/bin/bash","-c","echo hello"]

2、CMD:用来指定启动容器时默认执行的命令

支持三种格式:

  1. CMD ["executable","param1","param2"]:相当于执行executable param1 param2【推荐】;
  2. CMD command param1 param2:在默认的Shell中执行,提供给需要交互的应用;
  3. CMD ["param1","param2"]:提供给ENTRYPOINT的默认参数;

【注】

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

3、ADD:添加内容到镜像

格式:ADD <src> <dest>

格式解析:这条命令将复制指定的<src>路径下内容到容器中的<dest>路径下;同时,src可以是相对路径、URL、tar文件(自动解压为目录),dest可以是镜像内绝对路径或者相对于工作目录(WORKDIR)的相对路径(支持正则格式)。

4、COPY:复制内容到镜像

格式:COPY <src> <dest>

复制本地主机的<src>(为Dockerfile所在目录的相对路径、文件或目录)下内容到镜像中的<dest>;目标路径不存在时,会自动创建;路径同样支持正则格式。

【注】COPY和ADD指令功能相似,当使用本地目录为源目录时,推荐使用COPY。

  • 创建镜像

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

格式:docker build [OPTIONS] PATH | URL | -

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

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

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

docker build -t builder/first_image:1.0.0 /tmp/docker_builder/

1、命令选项

2、选择父镜像

大部分情况下,生成新的镜像都需要通过FROM指令来指定父镜像。父镜像是生成镜像的基础,会直接影响到所生成镜像的大小和功能。

用户可选择两种镜像作为父镜像:

  1. 基础镜像;
  2. 普通的镜像(由第三方创建,基于基础镜像);

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

例:下面定义了一个简单的基础镜像,将用户提前编译好的二进制可执行文件binary复制到镜像中,运行容器时执行binary指令

FROM scratch
ADD binary /
CMD ["/binary"]
发布了90 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_37160123/article/details/103287146