Dockerfile中的条件COPY/ADD?

idv4meu8  于 2023-04-20  发布在  Docker
关注(0)|答案(9)|浏览(221)

在我的Dockerfiles中,我想复制一个文件到我的镜像中,如果它存在的话,pip的requirements.txt文件似乎是一个很好的候选者,但如何实现呢?

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
xjreopfe

xjreopfe1#

下面是一个简单的解决方法:

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
0tdrvxhp

0tdrvxhp2#

正如这条评论所述,Santhosh希雷凯鲁尔的答案仍然是复制文件,要实现真正的条件复制,可以使用此方法。

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选择了“分支”时才复制文件。

kyvafyod

kyvafyod3#

2021+,从this answer开始,使用glob pattern,如果找不到任何有效源,Docker COPY不会失败

COPY requiements.tx[t] /destination

2015年:目前还不支持(因为我怀疑这会导致不可复制的镜像,因为相同的Dockerfile会复制或不复制文件,这取决于它的存在)。
issue 13045中,仍然需要使用通配符:《COPY foo/* bar/" not work if no file in foo》(2015年5月)。
它现在(2015年7月)不会在Docker中实现,但另一个构建工具,如**bocker**可以支持它。
二零二一年:
COPY source/. /source/为我工作(即复制目录时,空或不,如在“Copy directory into docker build no matter if empty or not - fails on " COPY failed: no source files were specified "“)
2022
以下是我的建议:

# syntax=docker/dockerfile:1.2

RUN --mount=type=bind,source=jars,target=/build/jars \
 find /build/jars -type f -name '*.jar' -maxdepth 1  -print0 \
 | xargs -0 --no-run-if-empty --replace=source cp --force source >"${INSTALL_PATH}/modules/"

它围绕着:

COPY jars/*.jar "${INSTALL_PATH}/modules/"

但是如果没有找到*.jar,则不复制*.jar,并且不抛出错误。

eivnm1vs

eivnm1vs4#

我想我想出了一个有效的解决方法来处理这个Dockerfile

FROM alpine
COPy always_exist_on_host.txt .
COPY *sometimes_exist_on_host.txt .

always_exist_on_host.txt文件将始终被复制到镜像中,并且当sometimes_exist_on_host.txt文件不存在时,构建不会复制失败。此外,当sometimes_exist_on_host.txt文件存在时,它将复制。
例如:

.
├── Dockerfile
└── always_exist_on_host.txt

构建成功

docker build . -t copy-when-exists --no-cache
[+] Building 1.0s (7/7) FINISHED                                                                                                                            
 => [internal] load .dockerignore                                                                                                                      0.0s
 => => transferring context: 2B                                                                                                                        0.0s
 => [internal] load build definition from Dockerfile                                                                                                   0.0s
 => => transferring dockerfile: 36B                                                                                                                    0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                                                                       1.0s
 => [internal] load build context                                                                                                                      0.0s
 => => transferring context: 43B                                                                                                                       0.0s
 => CACHED [1/2] FROM docker.io/library/alpine@sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a                                 0.0s
 => [2/2] COPY always_exist_on_host.txt *sometimes_exist_on_host.txt .                                                                                 0.0s
 => exporting to image                                                                                                                                 0.0s
 => => exporting layers                                                                                                                                0.0s
 => => writing image sha256:e7d02c6d977f43500dbc1c99d31e0a0100bb2a6e5301d8cd46a19390368f4899                                                           0.0s
.
├── Dockerfile
├── always_exist_on_host.txt
└── sometimes_exist_on_host.txt

构建仍然成功

docker build . -t copy-when-exists --no-cache
[+] Building 1.0s (7/7) FINISHED                                                                                                                            
 => [internal] load build definition from Dockerfile                                                                                                   0.0s
 => => transferring dockerfile: 36B                                                                                                                    0.0s
 => [internal] load .dockerignore                                                                                                                      0.0s
 => => transferring context: 2B                                                                                                                        0.0s
 => [internal] load metadata for docker.io/library/alpine:latest                                                                                       0.9s
 => [internal] load build context                                                                                                                      0.0s
 => => transferring context: 91B                                                                                                                       0.0s
 => CACHED [1/2] FROM docker.io/library/alpine@sha256:c0e9560cda118f9ec63ddefb4a173a2b2a0347082d7dff7dc14272e7841a5b5a                                 0.0s
 => [2/2] COPY always_exist_on_host.txt *sometimes_exist_on_host.txt .                                                                                 0.0s
 => exporting to image                                                                                                                                 0.0s
 => => exporting layers                                                                                                                                0.0s
 => => writing image sha256:4c88e2ffa77ebf6869af3c7ca2a0cfb9461979461fc3ae133709080b5abee8ff                                                           0.0s
 => => naming to docker.io/library/copy-when-exists                                                                                                    0.0s
jk9hmnmh

jk9hmnmh5#

解决方案

我需要基于ENV变量将FOLDER复制到服务器。我取了空的服务器镜像。在本地文件夹中创建了所需的部署文件夹结构。然后在下面添加了一行到DockerFile将文件夹复制到容器。我在最后一行添加了入口点,file.sh在docker启动服务器之前执行init www.example.com。

#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文件

#!/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=测试
这些更改在Docker构建期间将文件夹复制到容器。当我们执行docker-compose up时,它会在服务器启动之前将实际需要的文件夹复制或部署到服务器。

w1jd8yoj

w1jd8yoj6#

复制所有文件到一个一次性目录,手工选择你想要的,丢弃其余的。

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
qlvxas9a

qlvxas9a7#

尝试了其他的想法,但都没有达到我们的要求。这个想法是为子静态Web应用程序创建基本的nginx镜像。出于安全,优化和标准化的原因,基本映像必须能够在子映像添加的目录上执行RUN命令。2基本映像不控制子映像添加哪些目录。假设子映像将COPY资源放在COMMON_DEST_ROOT下的某个位置。
这种方法是一个黑客,但想法是基本图像将支持COPY指令为1到N目录添加的子图像。ARG PLACEHOLDER_FILEENV UNPROVIDED_DEST用于满足<src><dest>要求的任何COPY指令不需要。

#
# base-image:01
#
FROM nginx:1.17.3-alpine
ENV UNPROVIDED_DEST=/unprovided
ENV COMMON_DEST_ROOT=/usr/share/nginx/html
ONBUILD ARG PLACEHOLDER_FILE
ONBUILD ARG SRC_1
ONBUILD ARG DEST_1
ONBUILD ARG SRC_2
ONBUILD ARG DEST_2
ONBUILD ENV SRC_1=${SRC_1:-PLACEHOLDER_FILE}
ONBUILD ENV DEST_1=${DEST_1:-${UNPROVIDED_DEST}}
ONBUILD ENV SRC_2=${SRC_2:-PLACEHOLDER_FILE}
ONBUILD ENV DEST_2=${DEST_2:-${UNPROVIDED_DEST}}

ONBUILD COPY ${SRC_1} ${DEST_1}
ONBUILD COPY ${SRC_2} ${DEST_2}

ONBUILD RUN sh -x \
    #
    # perform operations on COMMON_DEST_ROOT
    #
    && chown -R limited:limited ${COMMON_DEST_ROOT} \
    #
    # remove the unprovided dest
    #
    && rm -rf ${UNPROVIDED_DEST}

#
# child image
#
ARG PLACEHOLDER_FILE=dummy_placeholder.txt
ARG SRC_1=app/html
ARG DEST_1=/usr/share/nginx/html/myapp
FROM base-image:01

这种解决方案有明显的缺点,如虚拟PLACEHOLDER_FILE和支持的硬编码的COPY指令数量。也没有办法摆脱在COPY指令中使用的ENV变量。

omjgkv6w

omjgkv6w8#

我有其他的解决方法。这个想法是在构建上下文中接触文件,并在Dockerfile中使用copy语句。如果文件存在,它只会创建一个空文件,docker构建不会失败。如果已经有一个文件,它只会更改时间戳。

touch requirements.txt

对于Dockerfile

FROM python:3.9
COPY requirements.txt .
krugob8w

krugob8w9#

COPY不再要求至少存在一个源,如果没有匹配,globbing也不会失败,因此您可以

COPY requirements.tx[t] /destination

如果requirements.txt存在,则会复制它,如果它不存在,则不会失败。

相关问题