![](/img/trans.png)
[英]Copy files to a Docker image using entrypoint instead of dockerfile for GitHub actions
[英]Docker: In Dockerfile, copy files temporarily, but not for final image
我有一個想要打包的 Java 服務,最終的 docker 鏡像唯一需要的是 JAR 文件和一個配置文件。 但是,我需要先運行我的gradle
命令來構建 JAR,但我不希望gradle
使用的所有東西都在結果gradle
映像中。
這是我當前的 DockerFile:
RUN apt-get update && apt-get install -y openjdk-7-jdk
COPY . /
RUN ./gradlew shadowJar
CMD ["java", "-jar", "service/build/libs/service.jar", "server", "service/service.yml"]
您可以看到我必須先COPY
所有內容,以便我可以運行./gradlew
(否則它說找不到命令)。 但最后,我需要的只是service.jar
和service.yml
文件。
我可能遺漏了一些東西,但是如何在./gradlew
構建步驟中使所有內容可用,但只有結果圖像包含service.jar
和service.yml
。
Docker 引入了所謂的“多階段構建”。 使用它們,您可以避免在圖像中包含不必要的文件。 您的Dockerfile
將如下所示:
FROM ubuntu AS build
COPY . /src
# run your build
FROM ubuntu
RUN mkdir -p /dist/
COPY --from=build /src/my.object /dist/
原理很簡單。 在第一個FROM
您命名您的構建。 在第二個FROM
您可以使用COPY --from=
-parameter 將文件從第一個構建復制到第二個構建。 第二個構建是稍后產生可用圖像的構建。
如果要測試構建結果而不是生成的圖像,可以使用docker build --target build myimage:build .
. 生成的圖像僅包含Dockerfile
的第一個FROM
。
更多信息: https : //docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
構建圖像的工作如下。
... docker build 命令將使用任何包含 Dockerfile 的目錄作為構建上下文(包括其所有子目錄)。 構建上下文將在構建映像之前發送到 Docker 守護程序,這意味着如果您使用 / 作為源存儲庫,則硬盤驅動器的全部內容將被發送到守護程序...
請參閱https://docs.docker.com/reference/builder/
我看不出有什么辦法可以實現你想要的。 有兩種選擇:
在鏡像中包含所有構建依賴項,並在容器內構建 JAR 文件。 那會膨脹你的形象。
我建議單獨構建您的 JAR,並在構建時ADD
可執行文件和配置文件。 這意味着所有構建依賴項都必須在您的開發環境中可用,但您的映像要盡可能小。
另一種解決方法是使用 Web 服務器來拉入數據。
啟動一個 Web 服務器,為您臨時需要的文件提供服務。 您可以使用
python3 -m http.server 8000 --bind 127.0.0.1 &
要提供當前目錄,請參閱https://docs.python.org/3/library/http.server.html#http-server-cli
在您的Dockerfile
獲取文件,執行操作,在單個RUN
刪除文件
RUN wget http://localhost:8000/big.tar && tar xf big.tar && ... && rm big.tar
使用--network host
構建映像以能夠訪問localhost
有一個實驗性的構建標志--squash
可以將所有內容匯總為一層。
例如, docker build --squash -t <tag> .
文檔https://docs.docker.com/engine/reference/commandline/image_build/#options 。
Github 討論https://github.com/moby/moby/issues/332 。
如何在守護進程中啟用實驗性功能? https://github.com/docker/docker-ce/blob/master/components/cli/experimental/README.md
我采納了各種意見,並使用DOCKER_BUILDKIT
提出了這個解決方案。 我將somefile.tar.gz
臨時復制到階段 0,但該文件不存在於最終圖像中。 整體容器尺寸減小。
# syntax=docker/dockerfile:experimental
# File: Dockerfile
# Build:
# DOCKER_BUILDKIT=1 docker build -t sometag -f Dockerfile $(pwd)
# =============================================================================
# STAGE 0 ---------------------------------------------------------------------
# =============================================================================
FROM somebase as devel
COPY somefile.tar.gz /somemodules/
RUN cd /somemodules && \
tar -xf somefile.tar.gz
# =============================================================================
# STAGE 1 ---------------------------------------------------------------------
# =============================================================================
FROM same_or_another_base
RUN apt-get update -y && \
apt-get install -y --no-install-recommends \
rsync && \
rm -rf /var/lib/apt/lists/*
RUN --mount=from=devel,src=/somemodules,dst=/somemodules \
rsync -I -K -a /somemodules/somefile/* /usr/local/somemodules/
RUN echo "/usr/local/somemodules/lib" >> /etc/ld.so.conf.d/somemodules.conf
ENV PATH=/usr/local/somemodules/bin:$PATH
# a bunch of other stuff . . .
RUN ldconfig
你可以這樣做:
FROM java:7
COPY . /sourcecode
WORKDIR /sourcecode
RUN ./gradlew shadowJar && rm -rf /sourcecode
WORKDIR /
CMD ["java", "-jar", "service/build/libs/service.jar", "server", "service/service.yml"]
這使用 Docker 官方java
映像(請參閱 repo )。
RUN
行應該創建您的service.jar
,然后在創建層之前刪除您COPY
所有源代碼,因此源代碼不會成為最終圖像的一部分。 我假設gradlew
也會將它復制/安裝到 /service/build/libs,否則您應該添加該步驟。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.