Подтвердить что ты не робот

Условная COPY/ADD в Dockerfile?

Внутри моих Dockerfiles я хотел бы скопировать файл в мое изображение, если он существует, и, как представляется, хорошим вариантом является файл require.txt для pip, но как этого добиться?

COPY (requirements.txt if test -e requirements.txt; fi) /destination
...
RUN  if test -e requirements.txt; then pip install -r requirements.txt; fi

или же

if test -e requirements.txt; then
    COPY requiements.txt /destination;
fi
RUN  if test -e requirements.txt; then pip install -r requirements.txt; fi
4b9b3361

Ответ 1

В настоящее время это не поддерживается (поскольку я подозреваю, что это приведет к невоспроизводимому изображению, так как тот же файл Docker будет копировать или не файл в зависимости от его существования).

По-прежнему запрашивается проблема 13045 с использованием подстановочных знаков: "COPY foo/* bar/" not work if no file in foo" (май 2015 г.).
Он не будет реализован на данный момент (июль 2015 г.) в Docker, но другой инструмент построения, например bocker, может поддерживайте это.

Ответ 2

Вот простой способ:

COPY foo file-which-may-exist* /target

Убедитесь, что существует foo, так как COPY требуется хотя бы один допустимый источник.

Если присутствует file-which-may-exist, он также будет скопирован.

Примечание: Вы должны позаботиться о том, чтобы ваш подстановочный знак не собирал другие файлы, которые вы не собираетесь копировать. Чтобы быть более осторожным, вы можете использовать file-which-may-exist? вместо этого (? соответствует только одному символу).

Или даже лучше, используйте класс символов, подобный этому, чтобы гарантировать соответствие только одного файла:

COPY foo file-which-may-exis[t] /target

Ответ 3

Как указано в этом комментарии, ответ Santhosh Hirekerur по-прежнему копирует файл, для архивирования истинной условной копии вы можете использовать этот метод.

ARG BUILD_ENV=copy

FROM alpine as build_copy
ONBUILD COPY file /file

FROM alpine as build_no_copy
ONBUILD RUN echo "I don't copy"

FROM build_${BUILD_ENV}
# other stuff

Инструкции ONBUILD гарантируют, что файл будет скопирован, только если BUILD_ENV выбрал "ветвь". Установите эту переменную, используя небольшой скрипт перед вызовом docker build

Ответ 4

Работа над решением

У меня было требование по копированию FOLDER на сервер на основе переменных ENV. Я взял пустой образ сервера. создала требуемую структуру папок развертывания в локальной папке. затем добавьте строку ниже DockerFile, скопируйте папку в контейнер. я n в последней строке добавлена ​​точка входа для запуска init file.sh, прежде чем докер начнет сервер.

#below lines added to integrate testing framework
RUN mkdir /mnt/conf_folder
ADD install /mnt/conf_folder/install
ADD install_test /mnt/conf_folder/install_test
ADD custom-init.sh /usr/local/bin/custom-init.sh
ENTRYPOINT ["/usr/local/bin/custom-init.sh"]

Затем создайте файл custom-init.sh в локальном каталоге с помощью script, как показано ниже

#!/bin/bash
if [ "${BUILD_EVN}" = "TEST" ]; then
    cp -avr /mnt/conf_folder/install_test/* /mnt/wso2das-3.1.0/
else
    cp -avr /mnt/conf_folder/install/* /mnt/wso2das-3.1.0/
fi;

В файле docker-compose ниже строк.

окружающая среда:     - BUILD_EVN = TEST

Эти изменения копируют папку в контейнер во время сборки докеров. когда мы выполняем docker-compose up, он копирует или разворачивает фактическую требуемую папку на сервер до запуска сервера.

Ответ 5

Скопируйте все файлы в одноразовый каталог, вручную выберите нужный файл, откажитесь от остальных.

COPY . /throwaway
RUN cp /throwaway/requirements.txt . || echo 'requirements.txt does not exist'
RUN rm -rf /throwaway

Вы можете добиться чего-то подобного, используя этапы сборки, основанные на том же решении, используя cp для условного копирования. Используя этап сборки, ваше окончательное изображение не будет включать весь контент из исходного COPY.

FROM alpine as copy_stage
COPY . .
RUN mkdir /dir_for_maybe_requirements_file
RUN cp requirements.txt /dir_for_maybe_requirements_file &>- || true

FROM alpine
# Must copy a file which exists, so copy a directory with maybe one file
COPY --from=copy_stage /dir_for_maybe_requirements_file /
RUN cp /dir_for_maybe_requirements_file/* . &>- || true
CMD sh

Ответ 6

Возможно, вам просто не нужно! Верните свой код еще раз:

COPY (requirements.txt if test -e requirements.txt; fi) /destination
RUN  if test -e requirements.txt; then pip install -r requirements.txt; fi

Возможно, вы можете просто переключиться на:

COPY requirements.txt /requirements.txt
RUN  if test -e /requirements.txt; then pip install -r /requirements.txt; fi

Теперь у вас есть это:

  • Если файл существует, он будет скопирован с помощью COPY и обработан PIP в RUN
  • Если файл не существует, COPY будет терпеть неудачу (предположительно, молча), и PIP не будет запущен из-за условия