Докер и символические ссылки

У меня есть репо, настроенное следующим образом:

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

Однако создание изображений не удается, поскольку Docker не может обрабатывать символические ссылки. Я должен упомянуть, что мой проект намного сложнее, чем это, поэтому каталоги реструктуризации - отличный вариант. Как я могу справиться с этой ситуацией?

Ответ 1

Docker не поддерживает символические ссылки вне контекста сборки.

Некоторые методы использования общего файла в контейнере.

Поделиться базовым изображением

Создайте Dockerfile для 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 "[email protected]" .

Построить из URL

Вытяните конфигурацию из общего URL-адреса для всех worker-n сборников.

ADD http://somehost/config.json /

Увеличить масштаб контекста сборки изображения.

Включите целевые файлы symlink в контексте сборки, создав из родительского каталога, который включает как общие файлы, так и конкретные файлы контейнеров.

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

Ответ 2

docker build команды CLI посылает указанный каталог (обычно .) Как "построить контекст" в Докер Engine (демон). Вместо указания контекста сборки как /worker-a укажите контекст сборки как корневой каталог и используйте аргумент -f чтобы указать путь к Dockerfile в одном из дочерних каталогов.

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

Вам придется немного переделать файлы Dockerfiles, чтобы указать их на ../config/config.json, но это довольно тривиально, чтобы исправить.

Также проверьте этот вопрос/ответ, который, я думаю, касается той же самой проблемы, с которой вы сталкиваетесь.

Как включить файлы вне контекста сборки Docker?

Надеюсь это поможет! ура

Ответ 3

Альтернативным решением является обновление всех ваших программных ссылок на жесткие ссылки.

Ответ 4

Я также столкнулся с этой проблемой и хотел бы поделиться другим методом, который не был упомянут выше. Вместо использования npm link в моем Dockerfile я использовал yalc.

  1. Установите yalc в свой контейнер, например, RUN npm я -g yalc.
  2. Создайте свою библиотеку в Docker и запустите yalc publish (добавьте флаг --private если ваша общая библиотека является частной). Это будет "публиковать" вашу библиотеку локально.
  3. Запустите yalc add my-lib в каждом репо, который обычно использует npm link перед запуском npm install. Он создаст локальную папку .yalc в вашем контейнере Docker, создаст символическую ссылку в node_modules которая работает внутри Docker на эту папку, и перепишет ваш package.json чтобы он тоже ссылался на эту папку, чтобы вы могли безопасно запустить install.
  4. По желанию, если вы делаете двухэтапную сборку, убедитесь, что вы также скопировали папку .yalc в ваше окончательное изображение.

Ниже приведен пример Dockerfile, предполагая, что у вас есть Dockerfile с тремя пакетами: модели, Dockerfile и сервер, а хранилище моделей должно быть общим и называться 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"]

Надеюсь, это поможет...