Docker和符号链接

时间:2016-09-07 18:22:59

标签: docker symlink

我有一个这样的回购设置:

/config
   config.json
/worker-a
   Dockerfile
   <symlink to config.json>
   /code
/worker-b
   Dockerfile
   <symlink to config.json>
   /code

然而,构建图像失败,因为Docker无法处理符号链接。我应该提到我的项目比这复杂得多,所以重组目录不是一个很好的选择。我该如何处理这种情况?

4 个答案:

答案 0 :(得分:39)

Docker doesn't support symlinking files outside the build context

在容器中使用共享文件的一些不同方法。

分享基本图像

为包含共享配置/文件的基本Dockerfile图片创建worker-config

COPY config.json /config.json

构建图像并将其标记为worker-config

docker build -t worker-config:latest .

为所有工作人员worker-config

提供基本Dockerfile图片
FROM worker-config:latest

构建脚本

使用脚本将公共配置推送到每个工作容器。

./build worker-n

#!/bin/sh
set -uex 
rundir=$(readlink -f "${0%/*}")
container=$(shift)
cd "$rundir/$container"
cp ../config/config.json ./config-docker.json
docker build "$@" .

从URL构建

从所有worker-n版本的公共网址中提取配置。

ADD http://somehost/config.json /

增加图像构建上下文的范围

通过从包含共享文件和特定容器文件的父目录构建,在构建上下文中包含符号链接目标文件。

cd ..
docker build -f worker-a/Dockerfile .

您在Dockerfile中引用的所有源路径也必须更改以匹配新的构建上下文:

COPY workerathing /app

变为

COPY worker-a/workerathing /app

如果您有一个大型构建上下文,则使用此方法可以使所有构建上下文变大,因为它们都会共享。它可以减慢构建速度,尤其是远程Docker构建服务器。

从命名卷

安装配置目录

这样的卷只能作为目录使用,因此您无法像在将文件从主机安装到容器时那样指定文件。

docker volume create --name=worker-cfg-vol
docker run -v worker-cfg-vol:/config worker-config cp config.json /config

docker run -v worker-cfg-vol:/config:/config worker-a

从数据容器

挂载配置目录

同样,目录只是与上面的基本相同。这将自动将文件从目标目录复制到新创建的共享卷中。

docker create --name wcc -v /config worker-config /bin/true
docker run --volumes-from wcc worker-a

从主机

挂载配置文件
docker run -v /app/config/config.json:/config.json worker-a

答案 1 :(得分:2)

docker build CLI命令将指定目录(通常为.)作为“构建上下文”发送到Docker Engine(守护程序)。不要将构建上下文指定为/worker-a,而是将构建上下文指定为根目录,并使用-f参数指定其中一个子目录中Dockerfile的路径。 / p>

docker build -f worker-a/Dockerfile .
docker build -f worker-b/Dockerfile .

你必须稍微修改你的Dockerfiles,将它们指向../config/config.json,但这很难解决。

同时查看此问题/答案,我认为这些问题解决了您遇到的完全相同的问题。

How to include files outside of Docker's build context?

希望这有帮助!干杯

答案 2 :(得分:0)

另一种解决方案是将所有软链接升级为硬链接。

答案 3 :(得分:0)

我也遇到了这个问题,并且想分享另一种上面没有提到的方法。我没有在npm link中使用Dockerfile,而是使用yalc

  1. 在您的容器中安装yalc,例如RUN npm i -g yalc
  2. 在Docker中构建您的库,然后运行yalc publish(如果共享库是私有的,请添加--private标志)。这将在本地“发布”您的图书馆。
  3. 在运行yalc add my-lib之前,在通常会使用npm link的每个存储库中运行npm install。它将在您的Docker容器中创建一个本地.yalc文件夹,在node_modules中创建一个在Docker内部工作的符号链接到该文件夹​​,并重写您的package.json以引用该文件夹,因此您可以安全地运行安装。
  4. (可选)如果执行两阶段构建,请确保还将.yalc文件夹复制到最终映像中。

在示例Dockerfile下,假设您有一个包含三个程序包的mono存储库:模型,gui和服务器,并且必须共享模型存储库并将其命名为my-models

# You can access the container using:
#   docker run -it my-name sh
# To start it stand-alone:
#   docker run -it -p 8888:3000 my-name

FROM node:alpine AS builder
# Install yalc globally (the apk add... line is only needed if your installation requires it)
RUN apk add --no-cache --virtual .gyp python make g++ && \
  npm i -g yalc
RUN mkdir /packages && \
  mkdir /packages/models && \
  mkdir /packages/gui && \
  mkdir /packages/server
COPY ./packages/models /packages/models
WORKDIR /packages/models
RUN npm install && \
  npm run build && \
  yalc publish --private
COPY ./packages/gui /packages/gui
WORKDIR /packages/gui
RUN yalc add my-models && \
  npm install && \
  npm run build
COPY ./packages/server /packages/server
WORKDIR /packages/server
RUN yalc add my-models && \
  npm install && \
  npm run build

FROM node:alpine
RUN mkdir -p /app
COPY --from=builder /packages/server/package.json /app/package.json
COPY --from=builder /packages/server/dist /app/dist
# Make sure you copy the yalc registry too.
COPY --from=builder /packages/server/.yalc /app/.yalc
COPY --from=builder /packages/server/node_modules /app/node_modules
COPY --from=builder /packages/gui/dist /app/dist/public
WORKDIR /app
EXPOSE 3000
CMD ["node", "./dist/index.js"]

希望有帮助...