Докер и символические ссылки
У меня есть репо, настроенное следующим образом:
/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.
- Установите
yalc
в свой контейнер, например, RUN npm я -g yalc
. - Создайте свою библиотеку в Docker и запустите
yalc publish
(добавьте флаг --private
если ваша общая библиотека является частной). Это будет "публиковать" вашу библиотеку локально. - Запустите
yalc add my-lib
в каждом репо, который обычно использует npm link
перед запуском npm install
. Он создаст локальную папку .yalc
в вашем контейнере Docker, создаст символическую ссылку в node_modules
которая работает внутри Docker на эту папку, и перепишет ваш package.json
чтобы он тоже ссылался на эту папку, чтобы вы могли безопасно запустить install. - По желанию, если вы делаете двухэтапную сборку, убедитесь, что вы также скопировали папку
.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"]
Надеюсь, это поможет...