125

另一个 Docker 符号链接问题。我有一堆文件要复制到我所有的 Docker 构建中。我的目录结构是:

parent_dir
    - common_files
        - file.txt
    - dir1
        - Dockerfile  
        - symlink -> ../common_files

在上面的示例中,当我在 dir1 中构建 docker 时,我希望将 file.txt 复制过来。但我不想维护file.txt 的多个副本。根据此链接,从 docker version 0.10 开始,docker build 必须

按照容器根目录中的符号链接获取 ADD 构建说明。

但是当我在 Dockerfile 中使用以下任一行构建时,我没有得到这样的文件或目录:

ADD symlink /path/dirname或者 ADD symlink/file.txt /path/file.txt

安装选项不会为我解决它(跨平台......)。我试过tar -czh . | docker build -t没有成功。

有没有办法让 Docker 遵循符号链接并将 common_files/file.txt 复制到构建的容器中?

4

9 回答 9

83

这是不可能的,也不会实施。请查看关于 github 问题 #1676 的讨论

我们不允许这样做,因为它不可重复。您机器上的符号链接与我的机器不同,相同的 Dockerfile 会产生两种不同的结果。还具有指向 /etc/paasswd 的符号链接会导致问题,因为它会链接主机文件而不是本地文件。

于 2015-08-07T19:25:19.967 回答
27

如果有人仍然有这个问题,我在 superuser.com 上找到了一个非常好的解决方案:

https://superuser.com/questions/842642/how-to-make-a-symlinked-folder-appear-as-a-normal-folder

它基本上建议使用 tar 取消引用符号链接并将结果提供给 docker build:

$ tar -czh . | docker build -
于 2020-07-15T13:09:19.757 回答
12

一种可能性是在父目录中运行构建,其中:

$ docker build [tags...] -f dir1/Dockerfile .

(或者等效地,在子目录中,)

$ docker build  [tags...] -f Dockerfile ..

必须将 Dockerfile 配置为使用适当的路径进行复制/添加。根据您的设置,您可能希望.dockerignore父级中的 a 省略您不想放入上下文中的内容。

于 2018-06-24T20:21:16.593 回答
5

我知道它破坏了 docker build 的可移植性,但是您可以使用硬链接而不是符号链接:

ln /some/file ./hardlink
于 2020-06-14T01:18:42.763 回答
3

我只需要在相同的上下文中解决这个问题。我的解决方案是使用分层 Docker 构建。换句话说:

parent_dir
  - common_files
    - Dockerfile
    - file.txt

- dir1
    - Dockerfile (FROM common_files:latest)

缺点是你必须记住在 dir1 之前构建 common_files。优点是,如果您有许多相关图像,那么由于使用公共层,它们都会变小一些。

于 2021-01-28T11:43:25.693 回答
3

我感到非常沮丧,以至于我制作了一个小型 NodeJS 实用程序来帮助解决这个问题:file-syncer

给定现有的目录结构:

parent_dir
    - common_files
        - file.txt
    - my-app
        - Dockerfile
        - common_files -> symlink to ../common_files

基本用法:

cd parent_dir

// starts live-sync of files under "common_files" to "my-app/HardLinked/common_files"
npx file-syncer --from common_files --to my-app/HardLinked

然后在你的Dockerfile

[regular commands here...]

# have docker copy/overlay the HardLinked folder's contents (common_files) into my-app itself
COPY HardLinked /

问/答

  • 这比在 Docker 运行之前复制parent_dir/common_files到更好吗?parent_dir/my-app/common_files

这意味着放弃常规的符号链接,这将是一种损失,因为符号链接很有帮助,并且可以与大多数工具一起正常工作。例如,这意味着您无法common_files从我的应用程序内副本中查看/编辑源文件,这有一些缺点。(见下文)

  • 这比在 Docker 运行之前复制parent_dir/common-filesparent_dir/my-app/common_files_Copy,然后让 Dockerparent_dir/my-app/common_files在构建时将其复制到更好吗?

有两个优点:

  1. file-syncer不会“复制”常规意义上的文件。相反,它从源文件夹的文件创建硬链接。这意味着如果您编辑 下parent_dir/my-app/HardLinked/common_files的文件,parent_dir/common_files则会立即更新下的文件,反之亦然,因为它们引用相同的文件/inode。(这对于调试目的和跨项目编辑很有帮助[特别是如果您正在同步的文件夹是您正在积极编辑的符号链接节点模块],并确保您的文件版本始终同步/相同-到源文件)
  2. 因为file-syncer只更新被更改的确切文件的硬链接文件,所以像TiltSkaffold之类的文件监视工具会检测最小文件集的更改,这可能意味着比您更快的实时更新推送时间基本的“在文件更改时复制整个文件夹”工具会。
  • 这比 Syncthing 之类的常规文件同步工具有什么好处?

其中一些工具可能是可用的,但大多数都有这样或那样的问题。最常见的是该工具要么无法生成现有文件的硬链接,要么无法为已经硬链接的文件“推送更新”(因为硬链接文件不会通知文件观察者他们的如果edited-at 和watch-at 路径不同,则会自动更改)。另一个是这些同步工具中的许多不是为即时响应而设计的,和/或没有运行标志,使它们易于在受限构建工具中使用。(例如,对于 Tilt,--async标志file-syncer使其能够local(...)在项目的调用中使用Tiltfile

于 2021-08-13T00:23:30.647 回答
2

而不是使用simlinks,可以通过将文件从sites_available移动到sites_enabled而不是复制或制作simlinks来管理问题

因此,如果站点配置停止或其他内容,则站点配置将仅在 site_available 文件夹中的一个副本中,如果应该使用站点配置,则将在站点启用中

于 2019-06-07T10:44:44.140 回答
-1

使用一个小的包装脚本将所需的目录复制到 Dockerfile 的位置;

  • build.sh;

.

#!/bin/bash
[ -e bin ] && rm -rf bin
cp -r ../../bin .
docker build -t "sometag" .
于 2021-08-31T00:05:22.957 回答
-3

如果您使用的是 mac,请记住 brew install gnu-tar 使用 gtar 而不是 tar。似乎两者之间存在一些差异。

gtar 至少对我有用。

于 2021-09-11T06:57:33.140 回答