【翻译】Dockerfile参考

Dockerfile参考

来自docker官方网址:https://docs.docker.com/engine/reference/builder/

docker能够从Dockerfile中读取指令并自动构建一个镜像。Dockerfile是一个文本文档,它包含用户可以在命令行上调用的所有命令来组装一个镜像。使用docker构建,用户可以创建一个连续执行多个命令行指令的自动化构建。

这个页面描述了你可以在Dockerfile中使用的命令。读完此页后,请参阅Dockerfile最佳实践(Dockerfile Best Practices)以获得面向tip的指南。

前言

翻译这篇文章前我们先阐述一个重要的概念,那就是上下文(context):docker构建时会将上下文的所有内容(.dockerignore中指定的内容除外)发送到daemon中进行处理。那么如何指定这个上下文呢?我们看一个命令来更容易的理解:

docker build -t xxxxx .

注意这行命令后面有一个.(小点),这个小点的作用不是指定dockerfile的位置,指定dockerfile的位置是用-f参数来指定的,那你以为这个小点是干嘛的?他就是用来指定构建镜像的上下文的。

理解了以上的例子后,我们再看看COPY这个命令的真是含义:

COPY ./package.json /app/

COPY是将源目标复制到镜像中的一个命令,那么上面这个./package.json是指什么路径呢?这并不是要复制执行 docker build 命令所在的目录下的 package.json,也不是复制 Dockerfile 所在目录下的 package.json,而是复制 上下文(context) 目录下的 package.json

用法描述

docker构建命令(docker build)从Dockerfile和上下文构建一个映像。构建的上下文是位于指定位置路径或URL的文件集。路径是本地文件系统上的一个目录。URL是一个Git存储库位置。

上下文会被递归的处理。因此,路径包含任何子目录,URL包含存储库及其子模块。这个例子显示了一个使用当前目录作为上下文的构建命令:

$ docker build .
Sending build context to Docker daemon  6.51 MB
...

构建由Docker守护进程运行,而不是由CLI运行。构建过程要做的第一件事是将整个上下文(递归地)发送给守护进程。在大多数情况下,最好从一个空目录作为上下文开始,并将Dockerfile保存在该目录中。并且只添加构建Dockerfile所需的文件。

警告:不要使用根目录/作为路径,因为它会导致构建将硬盘驱动器的全部内容传输到Docker守护进程。

要在构建上下文中使用文件,Dockerfile引用一条指令中指定的文件,例如一条COPY指令。要提高构建的性能,可以通过向上下文目录添加.dockerignore文件来排除文件和目录。有关如何创建.dockerignore文件的信息,请参阅此页上的文档。 create a .dockerignore file

通常,Dockerfile的文件名称默认就是Dockerfile(首字母D大写),位于上下文的根目录中。在docker build中使用-f标志指向文件系统中任何位置的Dockerfile。

docker build -f /path/to/a/Dockerfile .

您可以指定一个存储库(repository)和用于保存新映像的标记(tag),这会在镜像构建成功之后应用:

 docker build -t shykes/myapp .

要在构建之后将映像标记到多个存储库中,请在运行构建命令时添加多个-t参数:

docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .

在Docker守护进程运行Dockerfile中的指令之前,它对Dockerfile进行初步验证,如果语法不正确,则返回一个错误:

$ docker build -t test/myapp .
Sending build context to Docker daemon 2.048 kB
Error response from daemon: Unknown instruction: RUNCMD

Docker守护进程逐个运行Dockerfile中的指令,如果需要,将每个指令的结果提交到一个新镜像中,最后输出新镜像的ID。Docker守护进程将自动清理您发送的上下文。

注意,每条指令都是独立运行的,并且会创建一个新镜像——因此,运行cd /tmp不会对接下来的指令产生任何影响。

只要有可能,Docker将重用中间镜像(缓存),以显著加快Docker的构建过程。这由控制台输出中的Using cache消息表示。(有关更多信息,请参阅Dockerfile最佳实践指南中的Build cache部分 Build cache section):

$ docker build -t svendowideit/ambassador .
Sending build context to Docker daemon 15.36 kB
Step 1/4 : FROM alpine:3.2
 ---> 31f630c65071
Step 2/4 : MAINTAINER [email protected]
 ---> Using cache
---> 2a1c91448f5f
Step 3/4 : RUN apk update &&      apk add socat &&        rm -r /var/cache/
 ---> Using cache
---> 21ed6e7fbb73
Step 4/4 : CMD env | grep _TCP= | (sed ‘s/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat -t 100000000 TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/‘ && echo wait) | sh
 ---> Using cache
---> 7ea8aef582cc
Successfully built 7ea8aef582cc

构建缓存仅用于具有本地父链(parent chain)的映像。这意味着这些映像是由以前的构建创建的,或者整个映像链是用docker加载的。如果希望使用特定映像的构建缓存,可以使用--cache-from选项指定它。使用--cache-from指定的镜像不需要父链,可以从其他仓库(registries)获取。

完成构建之后,就可以考虑浏览Pushing a repository to its registry

构建工具BuildKit

从18.09版本开始,Docker支持一个新的moby/buildkit项目提供的后端来执行构建(build)。与旧的实现相比,BuildKit后端提供了许多优点。例如,BuildKit可以:

  • 检测并跳过未使用的构建阶段(stage)
  • 并行化构建独立的构建阶段
  • 在构建之间只会增量地传输构建上下文中更改的文件
  • 检测并跳过在构建上下文中传输未使用的文件
  • 使用带有许多新特性的外部Dockerfile实现
  • 避免API其余部分的副作用(中间镜像和容器)
  • 为自动修剪(prune)设置构建缓存的优先级

要使用BuildKit后端,您需要在调用docker构建之前在CLI上设置一个环境变量DOCKER_BUILDKIT=1。

要了解基于BuildKit的构建可用的实验性Dockerfile语法,请参考BuildKit存储库中的文档: refer to the documentation in the BuildKit repository.

格式

下面是Dockerfile的格式:

# 注释
指令 参数

指令不区分大小写。但是,习惯上它们是大写的,以便更容易地将它们与参数区分开。

Docker按顺序在Dockerfile中运行指令。Dockerfile必须以“FROM”指令开头。它可能会在解析器指令、注释和全局作用域的参数之后。FROM指令指定要从中构建的父映像。FROM之前可能只有一个或多个ARG指令,它们声明在Dockerfile的FROM行中使用的参数。

Docker将以#开头的行作为注释,行中任何位置的#标记都被视为注释,除非该行是有效的解析器指令。这允许这样的语句:

# Comment
RUN echo ‘we are running some # of cool things‘

注释中不支持行延续字符。

解析器指令

解析器指令是可选的,并且影响Dockerfile中后续行的处理方式。解析器指令不向构建中添加层,也不会显示为构建步骤。解析器指令被编写为形式# directive=value中的一种特殊类型的注释。单个指令只能使用一次。

一旦一个注释,空的行和构建指令被执行,Docker就不再寻找解析器指令。相反,它将任何格式化为解析器指令的内容视为注释,并且不尝试验证它是否可能是解析器指令。因此,所有解析器指令必须位于Dockerfile的最顶层。

解析器指令不区分大小写。但是,习惯上它们都是小写的。约定还包括任何解析器指令后面的空行。解析器指令不支持行延续字符。

由于这些规则,下面的例子都是无效的:

  • 由于行延续无效:
# direc tive=value
  • 无效,因为出现两次:
# directive=value1
# directive=value2

FROM ImageName
  • 由于出现在构建指令之后而被视为注释:
FROM ImageName
# directive=value
  • 由于出现在非解析器指令的注释之后,所以被视为注释:
# About my dockerfile
# directive=value
FROM ImageName
  • 未知指令将被视为注释,因为它不被识别。此外,由于出现在注释之后,已知的指令被视为注释,而注释不是解析器指令。
# unknowndirective=value
# knowndirective=value
  • 解析器指令中允许非断行空白。因此,下列各行均被同等对待:
#directive=value
# directive =value
#    directive= value
# directive = value
#      dIrEcTiVe=value
  • 支持以下解析器指令:
  1. syntax
  2. escape

syntax

格式:

# syntax=[remote image reference]
# syntax=docker/dockerfile
# syntax=docker/dockerfile:1.0
# syntax=docker.io/docker/dockerfile:1
# syntax=docker/dockerfile:1.0.0-experimental
# syntax=example.com/user/repo:[email protected]:abcdef...

只有在使用BuildKit后端时该指令才有用。

syntax指令定义用于构建当前Dockerfile的构建器的位置。BuildKit后端允许无缝地使用构建器的外部实现,这些构建器以Docker镜像的形式分发,并在容器沙箱环境中执行。

自定义Dockerfile的实现允许你:

  • 在不用更新后台守护程序的情况下自动的获取错误修正
  • 确保所有用户使用相同的实现来构建Dockerfile
  • 在不升级后台守护程序的情况下获取最新的功能
  • 尝试新的实验性或第三方特性

官方的版本

escape

环境的替换

.dockerignore文件

.dockerignore文件的主旨是要“排除”一些发网daemon的文件,但是里面也有一些逻辑是不排除的,你要先明确这一点。

在docker CLI将上下文发送到docker守护进程之前,它在上下文的根目录中查找一个名为.dockerignore的文件。如果该文件存在,CLI将修改上下文以排除与其中模式匹配的文件和目录。这有助于避免不必要地向守护进程发送大型或敏感的文件和目录,并可能使用ADD或COPY将它们添加到映像中。

CLI将.dockerignore文件解释为一个新行分隔的模式列表,类似于Unix shell的文件globs。为了进行匹配,上下文的根被认为是工作目录和根目录。例如,模式/foo/bar和foo/bar都排除了路径的foo子目录或位于URL的git存储库根目录中名为bar的文件或目录。两者都不排斥其他任何东西。

如果.dockerignore文件中的一行以第1列中的#开始,那么这一行将被视为注释,并在CLI解释之前被忽略。

# comment
*/temp*
*/*/temp*
temp?

该文件导致以下构建行为:

规则 行为
# comment 忽略掉.
*/temp* 排除在根目录的任何直接子目录中名称以temp开头的文件和目录。例如,排除了普通文件/somedir/temporary.txt,以及/somedir/temp目录。
*/*/temp* 从根目录下两层的任何子目录中排除以temp开头的文件和目录。例如,/somedir/subdir/temporary.txt被排除。
temp? 排除根目录中名称为temp的单字符扩展名的文件和目录。例如,排除/tempa和/tempb。

使用Go语言的filepath的Match方法来匹配规则。预处理步骤删除开头和结尾的空白并使用Go语言的filepath.Clean方法消除.和. .。预处理后为空的行将被忽略。

依赖于filepath.Match提供的规则,Docker使用一个特殊的通配符**来匹配任意数量的目录,比如:**/*.go这个会匹配所有目录中.go扩展名的文件,包括构建的根目录。

以!(感叹号)开始的行可用于排除的例外情况。下面是一个例子,.dockerignore文件使用这个机制:

  *.md
    !README.md

除了README.md外所有的markdown文件都被排除在上下文外了。

放置!的地方影响如下行为:.dockerignore中与特定文件匹配的最后一行决定它是被包含还是被排除。考虑下面的例子:

 *.md
 !README*.md
  README-secret.md

首先所有的markdown文件都被排除了。

在!README*.md下面还有一行 README-secret.md那么结果就是除了这个README-secret.md的所有README开头的markdown文件不会被排除。

在来看下面这个例子:

 *.md
    README-secret.md
    !README*.md

首先所有的markdown文件都被排除了

然后第二行README-secret.md这个可以不写,因为第一行已经指定了规则,它也符合第一行的规则。

第三行又将所有README开头的markdown文件包含了进来,也就是说第二行根本不会起作用了,它指定的这个文件因为第三行的规则会被包括进去。

甚至可以使用.dockerignore文件来排除Dockerfile和.dockerignore文件。这些文件仍然被发送到守护进程,因为守护进程需要它们来完成自己的工作。但是ADD和COPY指令不会将它们复制到镜像。

最后,你可能希望指定要在上下文中包含哪些文件,而不是要排除哪些文件。要实现这一点,将*指定为第一个模式,然后是一个或多个模式!例外模式。

note:作为历史原因你应该了解,.模式被忽略了。

FROM

原文地址:https://www.cnblogs.com/pangjianxin/p/11793894.html

时间: 2024-10-19 18:43:11

【翻译】Dockerfile参考的相关文章

Dockerfile参考

Dockerfile参考 用法 docker build命令Dockerfile根据上下文构建image.构建的上下文是指定位置PATH或的文件URL.这PATH是本地文件系统上的目录.URL是一个Git存储库位置. 递归处理上下文.因此,a PATH包括所有子目录,URL包括存储库及其子模块.此示例显示了使用当前目录作为上下文的构建命令: $ docker build . Sending build context to Docker daemon 6.51 MB ... 构建由Docker守

英文翻译中的点与坑

最近由IDF实验室翻译出版了一本名叫<Kali渗透测试技术实战>(<Hacking with Kali:Practical Penetration Testing Techniques>)的书,看似薄薄的一本书,实际上是由IDF实验室的五名成员张世会.童进.封畅.李秀烈及成明遥共同翻译完成,而实际上这些成员已在IDF博译有道中独立或参与了多篇外文的翻译.在国外的安全资讯潮水般的涌进国内时,恰恰是这些默默无闻的翻译们让国内的信息安全从业人员得以尽快了解国外的技术与产业更新,在1-2年

JavaScript 编程精解 中文第三版 翻译完成

原书:Eloquent JavaScript 3rd edition 译者:飞龙 自豪地采用谷歌翻译 部分参考了<JavaScript 编程精解(第 2 版)> 在线阅读 PDF格式 EPUB格式 MOBI格式 代码仓库 赞助我 协议 CC BY-NC-SA 4.0 原文地址:https://www.cnblogs.com/wizardforcel/p/9125631.html

python 修饰器

因困扰自己多时,打算整理一下修饰器到底是什么? 参考资料:http://python.jobbole.com/82344/ 修饰器 1. 定义2个函数 2. 基本实现 3. 问题:实现后, 要修改原来代码中的变量名, funcB()改为funcA(funcB) 4. 解决方法:让funcB赋值等于funcA(funcB),用时就是funcB(), 不用修改原来代码, 这个要求需funcA(funcB)返回的是一个函数     a) 所以要返回一个函数,则加一个函数 wrapper(),然后ret

编写Dockerfiles的最佳做法

编写Dockerfiles的最佳做法 Docker可以通过从Dockerfile包含所有命令的文本文件中读取 指令,自动构建图像,以便构建给定图像所需的顺序.Dockerfile坚持一个具体的格式,并使用一组具体的说明.您可以在Dockerfile参考页面上了解基础知识 .如果你是新来Dockerfile的,你应该从那里开始. 本文档介绍了Docker,Inc.和Docker社区推荐的最佳做法和方法,以创建易于使用,有效 Dockerfile的.我们强烈建议您遵循这些建议(实际上,如果您正在创建

ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse

ROS机器人程序设计(原书第2版)补充资料 (柒) 第七章 3D建模与仿真 urdf Gazebo V-Rep Webots Morse 书中,大部分出现hydro的地方,直接替换为indigo或jade或kinetic,即可在对应版本中使用. 提供ROS接口的3D软件比较多,本章以最典型的Gazebo介绍为主,从Player/Stage/Gazebo发展而来,现在独立的机器人仿真开发环境,目前2016年最新版本Gazebo7.1配合ROS(kinetic)使用. 补充内容:http://blo

浏览器扩展系列————异步可插入协议(pluggable protocol)的实现

原文:浏览器扩展系列----异步可插入协议(pluggable protocol)的实现 IE中有很多我们比较熟悉的协议,如http,https,mailto,ftp等.当然你也可以实现自己定义的协议,稍微谈一下这里所说的协议,从我的理解来说这里的协议只有当你的网页引用某个资源时才会调用,而不是随便在某个属性的值前面加上某个协议的名称就可以了.常见的协议调用如img的src属性中,很多元素style中的background-image属性中,还有a标签的href属性中. 言归正传,前面说到的实现

分布式系统中的概念--第一篇 一致性协议、一致性模型、拜占庭问题、租约

1,一致性协议 两阶段提交协议与Raft协议.Paxos协议 ①两阶段提交协议 在分布式系统中,每个节点虽然可以知晓自己的操作时成功或者失败,却无法知道其他节点的操作的成功或失败.当一个事务跨越多个节点时,为了保持事务的ACID特性,需要引入一个作为协调者的组件来统一掌控所有节点(称作参与者)的操作结果并最终指示这些节点是否要把操作结果进行真正的提交(比如将更新后的数据写入磁盘等等).因此,二阶段提交的算法思路可以概括为: 参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与

数据库sql的join多表

摘录文章 SQL join 用于根据两个或多个表中的列之间的关系,从这些表中查询数据.注意,join后的数据记录数不一定就是左或右表的简单连接,图表只代表集合关系,在数量上并不准确,如这个条件后结果,数量大于左表总数. 图解SQL Join 我认为 Ligaya Turmelle 关于 SQL Join 的文章是一篇非常棒的新手入门指南.由于 SQL Join 似乎被默认为基础,同时利用文氏图表来解释它,乍一看似乎是很自然的选择.然而,就像她的文章下面评论里说的,我也发现在实际测试中,文氏图并没