无法在多阶段 docker 构建中从一个阶段复制到另一个阶段
cannot copy from one stage to another in multi stage docker build
我想针对应用程序创建和执行性能测试。目前,我的想法是在第一阶段使用多阶段构建来构建应用程序,在第二阶段使用多阶段构建 - 构建性能测试并在同一个容器中启动应用程序和性能测试。
我的Dockerfile
看起来像这样
# build stage
FROM gradle:jdk11
ARG ARTIFACT_PATH=json-comparison-application/build/libs
ARG ARTIFACT_NEW=app.jar
ARG ARTIFACT_OLD=json-comparison-application-0.0.1-SNAPSHOT.jar
RUN echo ${ARTIFACT_PATH}
RUN apt-get install git && git clone https://github.com/xxxx/json-comparison.git
WORKDIR json-comparison
RUN chmod +x gradlew && \
./gradlew clean build -x pmdMain -x spotbugsMain -x checkstyleMain --no-daemon && \
cd ${ARTIFACT_PATH} && mv ${ARTIFACT_OLD} ${ARTIFACT_NEW}
# performance test stage
FROM ubuntu:18.04
# simplified adoptopenjdk/11 without CMD entry point, probably better move to some external dockerfile
ARG ESUM='6dd0c9c8a740e6c19149e98034fba8e368fd9aa16ab417aa636854d40db1a161'
ARG BINARY_URL='https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.5%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.5_10.tar.gz'
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8'
ENV JAVA_VERSION jdk-11.0.5+10
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates fontconfig locales \
&& echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \
&& locale-gen en_US.UTF-8 \
&& rm -rf /var/lib/apt/lists/*
RUN set -eux; \
curl -LfsSo /tmp/openjdk.tar.gz ${BINARY_URL}; \
echo "${ESUM} */tmp/openjdk.tar.gz" | sha256sum -c -; \
mkdir -p /opt/java/openjdk; \
cd /opt/java/openjdk; \
tar -xf /tmp/openjdk.tar.gz --strip-components=1; \
rm -rf /tmp/openjdk.tar.gz;
ENV JAVA_HOME=/opt/java/openjdk \
PATH="/opt/java/openjdk/bin:$PATH"
# custom part of the stage
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y python default-jre-headless python-tk python-pip python-dev \
libxml2-dev libxslt-dev zlib1g-dev net-tools && \
pip install bzt
WORKDIR /home/tmp
ARG ARTIFACT_PATH=json-comparison/json-comparison-application/build/libs
ARG ARTIFACT_NEW=app.jar
RUN echo ${ARTIFACT_PATH}
COPY --from=0 /${ARTIFACT_PATH}/${ARTIFACT_NEW} .
# prototype for test
CMD ["bzt", "quick_test.yml"]
但在 build
期间失败并出现错误
Step 23/24 : COPY --from=0 /${ARTIFACT_PATH}/${ARTIFACT_NEW} .
COPY failed: stat /var/lib/docker/overlay2/f227e7b77fba105ba0769aa355458900d202add59c98583f0fd0936cbf4dfc11/merged/json-comparison/json-comparison-application/build/libs/app.jar: no such file or directory
有什么问题?
乍一看,问题出在您的两个阶段中 .jar
的(绝对与相对)路径。
你能确认它们是一样的吗?
例如,您可以将第一阶段的最后一个命令替换为
RUN […] && \
cd ${ARTIFACT_PATH} && mv ${ARTIFACT_OLD} ${ARTIFACT_NEW} && readlink -f ${ARTIFACT_NEW}
并重新启动构建。如果你没有获得
/json-comparison/json-comparison-application/build/libs/app.jar
但是路径更长,那么你就会知道在第二阶段放入ARTIFACT_PATH
的正确路径…
或者,您可以去掉第一阶段的相对路径,将 WORKDIR json-comparison
替换为:
WORKDIR /json-comparison
顺便说一句,按以下方式命名构建阶段可能很有用:
FROM gradle:jdk11 as builder
[…]
FROM ubuntu:18.04 as test
[…]
然后,这允许您仅通过 运行:
构建第一阶段
$ docker build --target builder -t $IMAGE_NAME .
我想针对应用程序创建和执行性能测试。目前,我的想法是在第一阶段使用多阶段构建来构建应用程序,在第二阶段使用多阶段构建 - 构建性能测试并在同一个容器中启动应用程序和性能测试。
我的Dockerfile
看起来像这样
# build stage
FROM gradle:jdk11
ARG ARTIFACT_PATH=json-comparison-application/build/libs
ARG ARTIFACT_NEW=app.jar
ARG ARTIFACT_OLD=json-comparison-application-0.0.1-SNAPSHOT.jar
RUN echo ${ARTIFACT_PATH}
RUN apt-get install git && git clone https://github.com/xxxx/json-comparison.git
WORKDIR json-comparison
RUN chmod +x gradlew && \
./gradlew clean build -x pmdMain -x spotbugsMain -x checkstyleMain --no-daemon && \
cd ${ARTIFACT_PATH} && mv ${ARTIFACT_OLD} ${ARTIFACT_NEW}
# performance test stage
FROM ubuntu:18.04
# simplified adoptopenjdk/11 without CMD entry point, probably better move to some external dockerfile
ARG ESUM='6dd0c9c8a740e6c19149e98034fba8e368fd9aa16ab417aa636854d40db1a161'
ARG BINARY_URL='https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.5%2B10/OpenJDK11U-jdk_x64_linux_hotspot_11.0.5_10.tar.gz'
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' LC_ALL='en_US.UTF-8'
ENV JAVA_VERSION jdk-11.0.5+10
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates fontconfig locales \
&& echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen \
&& locale-gen en_US.UTF-8 \
&& rm -rf /var/lib/apt/lists/*
RUN set -eux; \
curl -LfsSo /tmp/openjdk.tar.gz ${BINARY_URL}; \
echo "${ESUM} */tmp/openjdk.tar.gz" | sha256sum -c -; \
mkdir -p /opt/java/openjdk; \
cd /opt/java/openjdk; \
tar -xf /tmp/openjdk.tar.gz --strip-components=1; \
rm -rf /tmp/openjdk.tar.gz;
ENV JAVA_HOME=/opt/java/openjdk \
PATH="/opt/java/openjdk/bin:$PATH"
# custom part of the stage
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y python default-jre-headless python-tk python-pip python-dev \
libxml2-dev libxslt-dev zlib1g-dev net-tools && \
pip install bzt
WORKDIR /home/tmp
ARG ARTIFACT_PATH=json-comparison/json-comparison-application/build/libs
ARG ARTIFACT_NEW=app.jar
RUN echo ${ARTIFACT_PATH}
COPY --from=0 /${ARTIFACT_PATH}/${ARTIFACT_NEW} .
# prototype for test
CMD ["bzt", "quick_test.yml"]
但在 build
期间失败并出现错误
Step 23/24 : COPY --from=0 /${ARTIFACT_PATH}/${ARTIFACT_NEW} .
COPY failed: stat /var/lib/docker/overlay2/f227e7b77fba105ba0769aa355458900d202add59c98583f0fd0936cbf4dfc11/merged/json-comparison/json-comparison-application/build/libs/app.jar: no such file or directory
有什么问题?
乍一看,问题出在您的两个阶段中 .jar
的(绝对与相对)路径。
你能确认它们是一样的吗?
例如,您可以将第一阶段的最后一个命令替换为
RUN […] && \
cd ${ARTIFACT_PATH} && mv ${ARTIFACT_OLD} ${ARTIFACT_NEW} && readlink -f ${ARTIFACT_NEW}
并重新启动构建。如果你没有获得
/json-comparison/json-comparison-application/build/libs/app.jar
但是路径更长,那么你就会知道在第二阶段放入ARTIFACT_PATH
的正确路径…
或者,您可以去掉第一阶段的相对路径,将 WORKDIR json-comparison
替换为:
WORKDIR /json-comparison
顺便说一句,按以下方式命名构建阶段可能很有用:
FROM gradle:jdk11 as builder
[…]
FROM ubuntu:18.04 as test
[…]
然后,这允许您仅通过 运行:
构建第一阶段$ docker build --target builder -t $IMAGE_NAME .