Условная 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
Ответы
Ответ 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 не будет запущен из-за условия