Docker笔记-07 Dockerfile

Dockerfile是用于构建Docker镜像的文本文件,包含了一系列的指令来告诉Docker如何构建镜像。本文详细讲解了Dockerfile的基本结构、指令说明、创建镜像的过程以及多阶段构建等,旨在帮助理解Dockerfile的使用和最佳实践。通过示例和解释,介绍了FROM、CMD、RUN、ADD、COPY等常用指令的用法,以及如何优化构建过程,减少镜像层数,提升效率。

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

1 基本结构

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

一般而言,Dockerfile分为四部分:

  • 基础镜像信息
  • 维护者信息
  • 镜像操作指令
  • 容器启动时执行指令
#第一行必须指定基于的基础镜像
FROM ubuntu:xeniel

#维护者信息
MAINTAINER docker_user  docker_user@email.com

#镜像的操作指令
RUN echo "deb http://archive.ubuntu.com/ubuntu/ raring main universe ">> /etc/apt/sources.list
RUN apt-get update && apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf

#容器启动时执行指令
CMD /usr/bin/nginx

每运行一条RUN指令,镜像添加新的一层,并提交。最后CMD指令,来指定运行容器时的操作命令。

1.1 nginx的Dockerfile

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

FROM debian:jessie 

LABEL maintainer docker_user<docker_user@email.com> 

ENV NGINX VERSION 1.10.1-1-jessie 

RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3DBFBC641079A6ABABF5BDB27BD9BF62 \ 
        && echo "deb http://nginx.org/packages/debian/ jessie nsuginx" >> /etc/apt/sources.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 callector
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;"]

1.2 Go的Dockerfile

基于buildpack-deps:jessie-scm基础镜像,安装Golang相关环境, 制作一个Go语言的运行环境镜像。

FROM buildpack-deps:jessie-scm 

# gee for ego

RUN apt-get update && apt-get install -y --no-install-recommends \
    g++ \ 
    gcc \ 
    libe6-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/

2 指令说明

指令的一般格式为INSTRUCTION arguments,指令包括"配置指令(配置镜像信息)“和"操作指令(具体执行操作)”。

分类 指令 说明
配置指令 ARG 定义创建镜像过程中使用的变量
配置指令 FROM 指定所创建镜像的基础镜像
配置指令 LABEL 为生成的镜像添加元数据标签信息
配置指令 EXPOSE 声明镜像内服务监听的端口
配置指令 ENV 指定环境变量
配置指令 ENTRYPOINT 指定镜像的默认入口命令
配置指令 VOLUME 创建一个数据卷挂载点
配置指令 USER 指定运行容器时的用户名或UID
配置指令 WORKDIR 配置工作目录
配置指令 ONBUILD 创建子镜像时指定自动执行的操作指令
配置指令 STOPSIGNAL 指定退出的信号值
配置指令 HEALTHCHECK 配置所启动容器如何进行健康检查
配置指令 SHELL 指定默认shell类型
操作指令 RUN 运行指定命令
操作指令 CMD 启动容器时指定默认执行的命令
操作指令 ADD 添加内容到镜像
操作指令 COPY 复制内容到镜像

2.1 配置指令

2.1.1 ARG

定义创建镜像过程中使用的变量。格式为

ARG <name>[=<default value>]

在执行docker build时, 可以通过-build-arg[=]来为变量赋值。

ARGENV的效果一样,都是设置环境变量。所不同的是,ARG所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用ARG保存密码之类的信息,因为docker history还是可以看到所有值的。

灵活的使用ARG指令,能够在不修改Dockerfile的情况下,构建出不同的镜像。

ARG指令有生效范围,如果在FROM指令之前指定,那么只能用于FROM指令中。

ARG DOCKER_USERNAME=library

FROM ${DOCKER_USERNAME}/alpine

RUN set -x ; echo ${DOCKER_USERNAME}

使用上述Dockerfile会发现无法输${DOCKER_USERNAME}变量的值,要想正常输出,你必须在FROM之后再次指定ARG

# 只在 FROM 中生效
ARG DOCKER_USERNAME=library

FROM ${DOCKER_USERNAME}/alpine

# 要想在 FROM 之后使用,必须再次指定
ARG DOCKER_USERNAME=library

RUN set -x ; echo ${DOCKER_USERNAME}

对于多阶段构建,尤其要注意这个问题

# 这个变量在每个 FROM 中都生效
ARG DOCKER_USERNAME=library

FROM ${DOCKER_USERNAME}/alpine

RUN set -x ; echo 1

FROM ${DOCKER_USERNAME}/alpine

RUN set -x ; echo 2

对于上述Dockerfile两个FROM指令都可以使用${DOCKER_USERNAME},对于在各个阶段中使用的变量都必须在每个阶段分别指定:

ARG DOCKER_USERNAME=library

FROM ${DOCKER_USERNAME}/alpine

# 在FROM 之后使用变量,必须在每个阶段分别指定
ARG DOCKER_USERNAME=library

RUN set -x ; echo ${DOCKER_USERNAME}

FROM ${DOCKER_USERNAME}/alpine

# 在FROM 之后使用变量,必须在每个阶段分别指定
ARG DOCKER_USERNAME=library

RUN set -x ; echo ${DOCKER_USERNAME}

Docker内置了一些镜像创建变量,用户可以直接使用而无须声明,包括(不区分大小写)HTTP_PROXYHTTPS_PROXYFTP_PROXYNO_PROXY

2.1.2 FROM

指定所创建镜像的基础镜像。格式为:

FROM <image> [AS <name>] 
或 
FROM <image>:<tag> [AS <name>] 
或
FROM <image>@<digest> [AS <name>] 。

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

为了保证镜像精简,可以选用体积较小的镜像如Alpine或Debian作为基础镜像。 例如:

ARG VERSION=9.3 
FROM debian:${VERSION}

在Docker Hub上有非常多的高质量的官方镜像:

  • 有可以直接拿来使用的服务类的镜像,如nginxredismongomysqlhttpdphptomcat等;
  • 也有一些方便开发、构建、运行各种语言应用的镜像,如nodeopenjdkpythonrubygolang等。

可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。

如果没有找到对应服务的镜像,官方镜像中还提供了一些更为基础的操作系统镜像,如ubuntudebiancentosfedoraalpine等,这些操作系统的软件库为我们提供了更广阔的扩展空间。

除了选择现有镜像为基础镜像外,Docker还存在一个特殊的镜像,名为scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。

FROM scratch
...

如果你以scratch为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。

不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,对于Linux下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接FROM scratch会让镜像体积更加小巧。使用Go语言开发的应用很多会使用这种方式来制作镜像,这也是为什么有人认为Go是特别适合容器微服务架构的语言的原因之一。

2.1.3 LABEL

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

LABEL <key>=<value> <key>=<value> <key>=<value> ...

例如:

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

具体可以参考https://github.com/opencontainers/image-spec/blob/master/annotations.md

2.1.4 EXPOSE

声明镜像内服务监听的端口。格式为:

EXPOSE <port> [<port>/<protocol>... ]

例如:

EXPOSE 22 80 8443 

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

2.1.5 ENV

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

ENV <key> <value>
或
ENV <key1>=<value1> <key2>=<value2>...

例如:

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指令中同时为多个环境变量赋值并且值也是从环境变量读取时,会为变量都赋值后再更新。如下面的指令,最终结果为keyl=valuel key2=value2:

ENV k
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值