ADD
ADD
ADD有两种形式:
对于包含空格的路径,需要使用后一种形式。
NOTE:
--chown功能仅在用于构建Linux容器的Dockerfiles上受到支持,在Windows容器上不起作用。由于用户和组所有权概念无法在Linux和Windows之间进行转换,因此使用/etc/passwd和/etc/group将用户名和组名转换为ID限制了该功能,使得该功能仅适用于基于Linux OS的容器。
ADD指令从复制新文件,目录或远程文件URL,并将它们添加到镜像文件系统中的路径中。
每个都可以包含通配符,并且匹配根据Go的filepath.Match规则进行。例如:
要添加所有以"hom"开头的文件:
在下面的示例中,?可以被替换为任何单个字符,例如"home.txt"。
是绝对路径,或相对于WORKDIR的路径,源文件将被复制到目标容器所在文件系统的路径中。
下面的示例使用相对路径,并将"test.txt“添加到 /relativeDir/:
而此示例使用了绝对路径,并向/absoluteDir/添加了"test.txt"
在添加包含特殊字符的文件或目录(如 [和]) 时,需要按照Golang规则对这些路径进行转义,以防止它们被视为匹配模式。例如,要添加名为arr[0].txt的文件,请使用以下文件:
附go代码示例:
所有新文件和目录均以值为0的UID和GID创建,除非通过可选的--chown指定用户名、组名或UID/GID组合,来为添加的内容指定所有权(ownership)。--chown允许使用用户名和组名字符串的格式,或直接使用整数形式的UID和GID。如果使用不带组名的用户名或不带GID的UID的形式,则会使用与UID相同的值来作为GID。如果提供了用户名或组名,则会根据容器根文件系统中的/etc/passwd和/etc/group文件来将用户名和组名从name的形式转换为整数的形式。以下示例显示了--chown的有效定义:
示例:
通过上述Dockerfile构建镜像时,会产生下面这样的错误。
虽然我们对ADD指令的定义没有任何问题,但是我们忽略了一个问题。由于我们在指令中使用的用户名和组名,以及用户ID和组ID在系统中并不存在,所以构建镜像时,无法从/etc/passwd和/etc/group中找到相关记录(在Linux中创建用户和组时,用户的记录会被保存在/etc/passwd中,而组的记录会被保存在/etc/group文件中),因此构建失败。
如何解决上述问题?
通过在ADD指令之前,创建好ADD指令所需的用户和组,就能够解决上述问题。这里我们通过RUN指令来执行这些创建任务。
如果容器的根文件系统不包含/etc/passwd和/etc/group文件,并且以用户或组名的形式使用--chown,那么关于ADD构建的操作将会失败。使用数值ID形式的用户或组,则不需要查询且不会去依赖容器根文件系统的内容。
如果是一个URL形式的远端文件,目标文件将拥有600的文件权限。如果被检索的远端文件拥有一个HTTP Last-Modified头部,那么来自头部的时间戳将被用于设置目标文件的mtime。然而,像在ADD期间被处理的任意其他文件那样,mtime不会被用来决定文件是否被更改和缓存是否应该被更新。
NOTE:
在构建镜像时,如果通过标准输入来传递Dockerfile(docker build - < somefile),则不会存在构建上下文,因此Dockerfile中只能使用基于URL的ADD指令。我们也可以通过标准输入传递一个压缩文件:(docker build - < archive.tar.gz), 在压缩文件根目录下的Dockerfile和余下的一些文件将被作为构建上下文。
如果URL文件需要进行身份认证,那么我们需要使用RUN wget,RUN curl或者使用容器内部的其他工具来获取文件,因为ADD指令不支持身份认证功能。
NOTE:
如果<src>中的内容被更改了,在构建镜像时,遇到的第一个ADD指令会使后续指令的缓存失效。这其中还包含了RUN指令的缓存。查看Dockerfile Best Practice guide - Leverage build cache来获取更多信息。
ADD指令遵照以下规则:
<src>路径必须包含在构建上下文之中;不能使用ADD ../something /something, 因为docker build的第一步就是将上下文目录(及其子目录)发送给docker守护进程。
如果<src>是一个URL,并且<dest>并没有以斜线结尾,那么将会从URL下载一个文件然后拷贝<dest>。
如果<src>是一个URL,并且<dest>以斜线结尾,那么docker会根据URL推断出文件名,然后文件会下载到<dest>/<filename>。例如,ADD http://example.com/foobar / 将创建一个/foobar文件。URL必须包含一个资源路径,以便可以通过这个路径找到适当的文件名。(http://example.com将无法执行)。
NOTE:
目录本身并不会被拷贝,仅仅只是拷贝目录中的内容。
如果<src>是一个能够被识别的本地压缩文件(例如identity,gzip,bzip2或xz),那么它会被解压成一个目录。来自远端URL的资源无法被解压。当一个目录被拷贝或者解压时,它与tar -x命令有着相同的行为。
NOTE:
文件是否被识别为压缩格式的文件仅基于文件的内容,而不是文件的名称。例如,如果一个空文件碰巧以.tar.gz结尾,这个文件不会被识别为压缩文件,也不会生成任何类型的减压错误消息,而是将这个文件简单地复制到目的地。
如果<src>是任意其他类型的文件,它和它的元数据会被单独拷贝。在这种情况下,如果<dest>以斜线结尾,它会被当作目录,<src>的内容会被写入到<dest>/base(<src>)。
如果通过直接或使用通配符的方式指定了多个<src>资源,那么<dest>必须是一个目录,并且必须以斜线结尾。
如果<dest>没有以斜线结尾,那么它会被当成一个正常的文件,而<src>的内容会被写入到这个文件中。
如果<dest>不存在,那么会在它的路径下创建所有缺失的目录。
Last updated