docker 实践六:dockerfile 详解

本篇开始来学习关于 dockerfile 的知识。

注:环境为 CentOS7,docker 19.03。

dockerfile 是?个?本格式的配置?件, ?户可以使? dockerfile 来快速创建?定义的镜像。

指令系统

dockerfile 主要是通过一个指令来实现想要的功能的。dockerfile 支持的指令如下

ARG

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

ARG<name>[=<default value>]

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

Docker内置了?些镜像创建变量, ?户可以直接使???须声明, 包括(不区分??写) HTTP_PROXY、 HTTPS_PROXY、 FTP_PROXY、NO_PROXY。`

FROM busybox
ARG user1
ARG buildno=1
USER &user1
...

注:不要使用构建时变量来传递 github 密钥,用户凭据等重要信息。使用 docker history 命令可以查看构建时的变量信息。

FROM

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

  • FROM[AS]
  • FROM: [AS]
  • FROM@[AS]

任何 dockerfile中 第?条指令必须为FROM指令。 并且, 如果在同?个 dockerfile 中创建多个镜像时, 可以使?多个FROM指令(每个镜像?次)。
为了保证镜像精简, 可以选?体积较?的镜像如Alpine或Debian作为基础镜像。 例如:

ARG VERSION=9.3
FROM debian:${VERSION}

LABEL

LABEL指令可以为?成的镜像添加元数据标签信息。 这些信息可以?来辅助过滤出特定镜像。格式为 LABEL<key>=<value><key>=<value><key>=<value>

LABEL version="1.0.0-rc3"
LABEL author="[email protected]" date="2020-01-01"
LABEL description="This text illustrates     that label-values can span multiple lines."

EXPOSE

声明镜像内服务监听的端口。格式为 EXPOSE<port>[<port>/<protocol>...]

EXPOSE 22 80 8443/udp

注意该指令只是起到声明作?, 并不会?动完成端?映射

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指令中同时为多个环境变量赋值并且值也是从环境变量读取时, 会为变量都赋值后再更新。

ENTRYPOINT

指定镜像的默认??命令, 该??命令会在启动容器时作为根命令执?, 所有传?值作为该命令的参数。?持两种格式:

  • ENTRYPOINT["executable", "param1", "param2"]: exec调?执?;
  • ENTRYPOINT command param1 param2: shell中执?。

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

VOLUME

创建?个数据卷挂载点。格式为 VOLUME["/data"]
运?容器时可以从本地主机或其他容器挂载数据卷, ?般?来存放数据库和需要保持的数据等。

USER

指定运?容器时的?户名或UID, 后续的RUN等指令也会使?指定的?户?份。格式为 USER daemon

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

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

要临时获取管理员权限可以使?gosu命令。

WORKDIR

为后续的RUN、 CMD、 ENTRYPOINT指令配置?作?录。格式为 WORKDIR/path/to/workdir

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

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

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

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

ONBUILD

指定当基于所?成镜像创建?镜像时, ?动执?的操作指令。格式为 ONBUILD [INSTRUCTION]

例如, 使?如下的Dockerfile创建?镜像ParentImage, 指定 ONBUILD 指令:

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

使? docker build 命令创建?镜像 ChildImage 时(FROM ParentImage),会?先执?ParentImage中配置的ONBUILD指令:

# Dockerfile for ChildImage
FROM ParentImage

等价于在 ChildImage 的 dockerfile 中添加了如下指令:

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

由于ONBUILD指令是隐式执?的, 推荐在使?它的镜像标签中进?标注, 例如ruby: 2.1-onbuild。

ONBUILD指令在创建专门?于?动编译、 检查等操作的基础镜像时,?分有?。

STOPSIGNAL

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

STOPSIGNAL signal

HEALTHCHECK
配置所启动容器如何进?健康检查(如何判断健康与否),? docker1.12 开始?持。
格式有两种:

  • HEALTHCHECK[OPTIONS]CMD command: 根据所执?命令返回是否为0来判断;
  • HEALTHCHECK NONE: 禁?基础镜像中的健康检查。

OPTION?持如下参数:

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

SHELL

指定其他命令使? shell 时的默认 shell 类型:

SHELL `["executable", "parameters"]` 

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

对于Windows系统,Shell路径中使?了“”作为分隔符, 建议在 dockerfile 开头添加 #escape=‘来指定转义符。

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 zlib1g-dev libbz2-dev     && rm -rf /var/cache/apt     && rm -rf /var/lib/apt/lists/*

CMD

CMD 指令?来指定启动容器时默认执?的命令。
?持三种格式:

  • CMD ["executable", "param1", "param2"]: 相当于执? executableparam1 param2, 推荐?式;
  • CMD command param1 param2: 在默认的Shell中执?, 提供给需要交互的应?;
  • CMD ["param1", "param2"]: 提供给ENTRYPOINT的默认参数。

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

ADD

添加内容到镜像。格式为 ADD <src> <dest>

该命令将复制指定的 路径下内容到容器中的路径下。其中可以是Dockerfile所在?录的?个相对路径(?件或?录);也可以是?个URL; 还可以是?个tar?件(?动解压为?录)可以是镜像内绝对路径, 或者相对于?作?录(WORKDIR) 的相对路径。

路径?持正则格式, 例如:

ADD *.c /code/

COPY

复制内容到镜像。格式为 COPY <src> <dest>

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

COPY与ADD指令功能类似, 当使?本地?录为源?录时, 推荐使?COPY。

创建镜像

创建镜像使用命令 docker [image] build, 格式为 docker build [OPTIONS] PATH | URL| -

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

docker build 支持以下的选项:


关于父镜像

dockerfile 使用 FROM 指令指定父镜像,一般我们使用系统镜像来作为父镜像,但是我们也可以使用基础镜像(scratch)来作为父镜像:

FROM scratch
ADD binary /
CMD ["/binary"]

docker 中镜像存在继承关系,用一张图来说明:

.docerignore 文件

如同 git 有 .gitignore 文件一样,docker 也有 .dockerignore 文件来让Docker忽略匹配路径或?件, 在创建镜像时候不将?关数据发送到服务端

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

dockerignore?件中模式语法?持Golang风格的路径正则格式:

  • “*”表?任意多个字符;
  • “? ”代表单个字符;
  • “!”表?不匹配(即不忽略指定的路径或?件) 。

多步骤创建

?17.05版本开始, Docker?持多步骤镜像创建(Multi-stage build) 特性, 可以精简最终?成的镜像??。例如我们先指定一个编译的环境镜像进行编译,在指定一个运行的镜像来运行编译的代码。
以 Go 语言为例,创建一个空目录,在目录中创建 Go 代码文件 main.go

package main

import "fmt"

func main() {
    fmt.Println("Hello World")
}

编写 dockerfile

FROM golang:1.9 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
WORKDIR /root/
COPY --from=builder /go/src/test/app .
CMD ["./app"]

执行创建镜像

# docker build -t xingyys/test -f dockerfile .
Sending build context to Docker daemon  38.91kB
Step 1/9 : FROM golang:1.9 as builder
 ---> ef89ef5c42a9
...
Successfully built 73b66909a48d
Successfully tagged xingyys/test:latest
# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
xingyys/test        latest              73b66909a48d        8 minutes ago       7.44MB

使用多步骤发现生成的镜像很精简,当也可以用多个 dockerfile 实现这个功能,但需要两个 dockerfile,维护成本提高了。

dockerfile 要点

  • 编写 dockerfile 存在注意的点,遵守这些点可以生成更精简的镜像:
  • 精简镜像?途: 尽量让每个镜像的?途都?较集中单?, 避免构造??复杂、 多功能的镜像;
  • 选?合适的基础镜像: 容器的核?是应?。 选择过?的?镜像(如Ubuntu系统镜像) 会造成最终?成应?镜像的臃肿, 推荐选?瘦?过的应?镜像(如node: slim) , 或者较为?巧的系统镜像(如alpine、 busybox或debian) ;
  • 提供注释和维护者信息: Dockerfile也是?种代码, 需要考虑?便后续的扩展和他?的使?;
  • 正确使?版本号: 使?明确的版本号信息, 如1.0, 2.0, ??依赖于默认的latest。 通过版本号可以避免环境不?致导致的问题;
  • 减少镜像层数: 如果希望所?成镜像的层数尽量少, 则要尽量合并RUN、 ADD和COPY指令。 通常情况下, 多个RUN指令可以合并为?条RUN指令;
  • 恰当使?多步骤创建(17.05+版本?持) : 通过多步骤创建, 可以将编译和运?等过程分开, 保证最终?成的镜像只包括运?应?所需要的最?化环境。 当然, ?户也可以通过分别构造编译镜像和运?镜像来达到类似的结果, 但这种?式需要维护多个Dockerfile。
  • 使?.dockerignore?件: 使?它可以标记在执?docker build时忽略的路径和?件, 避免发送不必要的数据内容, 从?加快整个镜像创建过程。
  • 及时删除临时?件和缓存?件: 特别是在执?apt-get指令后, /var/cache/apt下?会缓存了?些安装包;
  • 提??成速度: 如合理使?cache, 减少内容?录下的?件, 或使?.dockerignore?件指定等;
  • 调整合理的指令顺序: 在开启cache的情况下, 内容不变的指令尽量放在前?, 这样可以尽量复?;
  • 减少外部源的?扰: 如果确实要从外部引?数据, 需要指定持久的地址, 并带版本信息等, 让他?可以复??不出错。

原文地址:https://www.cnblogs.com/xingyys/p/11405501.html

时间: 2024-07-28 17:42:52

docker 实践六:dockerfile 详解的相关文章

iOS网络编程(六) NSURLSession详解

昨夜浏览Demo的时候,看到别人请求网络数据用的是NSURLSession,当时就在想这里什么,怎么没有用过,引起了我的好奇心,遂去百度-谷歌-官方文档一一查看,有了一定的了解,原来NSURLSession是iOS7中新的网络接口,它与咱们熟悉的NSURLConnection是并列的. 查找资料,写了一个小Demo,大家可以看看,有什么不足的地方,可以留言帮我指出来. // // HMTRootViewController.m // // // Created by HMT on 14-6-7.

JBPM学习(六):详解流程图

概念: 流程图的组成: a. 活动 Activity / 节点 Node b. 流转 Transition / 连线(单向箭头) c. 事件 1.流转(Transition) a) 一般情况一个活动中可以指定一个或多个Transition i. 开始活动(Start)中只能有一个Transition. ii. 结束活动(End)中没有Transition. iii. 其他活动中有一条或多条Transition b) 如果Transition只有一个,则可以不指定名称(名称是null):如果有多个

Docker基础 :网络配置详解

本篇文章将讲述 Docker 的网络功能,包括使用端口映射机制来将容器内应用服务提供给外部网络,以及通过容器互联系统让多个容器之间进行快捷的网络通信,有兴趣的可以了解下. 大量的互联网应用服务包含多个服务组件,这往往需要多个容器之间通过网络通信进行相互配合.Docker 目前提供了映射容器端口到宿主主机和容器互联机制来为容器提供网络服务.接下来我们将讲述 Docker 的网络功能,包括使用端口映射机制来将容器内应用服务提供给外部网络,以及通过容器互联系统让多个容器之间进行快捷的网络通信. 端口映

Docker:网络模式详解

Docker作为目前最火的轻量级容器技术,牛逼的功能,如Docker的镜像管理,不足的地方网络方面. Docker自身的4种网络工作方式,和一些自定义网络模式 安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络). none .host.Container host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口. Container:创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP.端口范围. None:该模式关

Dockerfile详解(二)

Dockerfile文件详解 什么是dockerfile? Dockerfile是一个包含用于组合映像的命令的文本文档.可以使用在命令行中调用任何命令. Docker通过读取Dockerfile中的指令自动生成映像. docker build命令用于从Dockerfile构建映像.可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile. 例: docker build -f /path/to/a/Dockerfile Dockerfile的基本结构 Dock

Dockerfile详解,以及构建自定义镜像

Dockerfile使用 前面的操作我们一直下载下载官方已经构建好的镜像,直接下载后就可以run,如果我们想要在镜像中添加自己的应用,比如在tomcat中添加自己的app,构建一个自定义的镜像,那么我们应该怎么做,这个时候就用到了Dockerfile.Dockerfile是由一系列命令和参数构成的脚本,Docker可以根据这个脚本基于某个基础镜像创建一个新的定制化的镜像,大大提高了我们部署的效率,使用Dockfile最终的结果是帮助我们定制化自己的镜像. Dockerfile初体验 下面就基于t

面向对象编程(十六)——内部类详解

一.内部类(innerclasses) 一般情况,我们把类定义成独立的单元.有些情况下,我们把一个类放在另一个类的内部定义,称为内部类. 在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.广泛意义上的内部类一般来说包括这四种:成员内部类.局部内部类.匿名内部类和静态内部类. 1. 内部类的作用 内部类提供了更好的封装,只能让外部类直接访问,不允许同一个包中的其他类直接访问. 内部类可以直接访问外部类的私用属性.内部类被当成其外部类的成员.但是外部类不能访问内部类的

Docker Dockerfile详解

dockerfike快速创建自定义的Docker镜像 一.目录 1.docker典型结构 2.指令介绍 3.创建docker镜像 二.结构 DockerFile分为四部分组成:基础镜像信.维护者信息.镜像操作指令和容器启动时执行指令.例如: #第一行必须指令基于的基础镜像 From ubutu #维护者信息 MAINTAINER docker_user [email protected] #镜像的操作指令 apt/sourcelist.list RUN apt-get update &&

Docker 使用指南 (五)—— Dockerfile 详解

版权声明:本文由田飞雨原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/97 来源:腾云阁 https://www.qcloud.com/community 制作Docker image 有两种方式:一是使用 Docker container,直接构建容器,再导出成 image 使用:二是使用 Dockerfile,将所有动作卸载文件中,再 build 成 image.Dockerfile 的方式非常灵活,推荐使用. 本次