我有两个容器,其中一个在另一个容器中提供了我需要的文件,我想让第一个容器将该文件写入卷,然后让第二个容器访问该卷并读取文件。 / p>
我有以下docker-compose.yml
文件:
version: '3'
volumes:
web_data:
services:
build_jar:
build:
context: .
dockerfile: Dockerfile-gradle
volumes:
- web_data:/workdir
generate_html:
depends_on:
- build_jar
ports:
- "8080:80"
build: .
volumes:
- web_data:/workdir
Dockerfile-gradle
FROM gradle:latest AS builder
USER root
RUN mkdir /workspace
ADD . /workspace
RUN cd /workspace && gradle shadowJar --no-daemon
RUN mkdir /workdir
RUN cp /workspace/build/libs/datainfrastructure-1.0-SNAPSHOT-all.jar /workdir/stat.jar
Dockerfile
FROM openjdk:8-jre-slim AS java
USER root
RUN java -jar /workdir/stat.jar
首先,我假设已经在docker-compose.yml
中创建了该卷,而无需手动创建即可自动获得目录/workdir
,而事实并非如此。因此,我使用mkdir
创建了它,并确实保存了数据:我可以在主机上访问var/lib/docker/volumes
并找到包含容器写入的数据的相应卷。很好。
好吧,第二,现在我需要将该卷与另一个容器一起使用,该容器也没有workdir
目录。因此,如果我尝试访问/workdir/stat.jar
,则该目录不存在;如果手动创建/workdir
,则该目录为空。如何获得第一个容器放在该卷上的文件?我是否在Dockerfiles或docker-compose.yml
中丢失了某些内容?
答案 0 :(得分:0)
构建Docker映像时,Dockerfile无法访问Docker网络,卷或Docker生态系统的任何其他部分。认为docker build
就像Maven或Gradle一样是不合理的:它会生成可复制到其他系统并在其他地方运行的映像,但是在构建时,它无法访问最终会出现的数据。您运行它。
相应地,作为一般规则,Docker映像应该是独立的。映像通常应包含其语言运行时以及运行应用程序所需的任何代码或构件;通过卷共享代码(或jar文件)通常不是最佳实践。 (需要特别注意的是,如果成功完成此操作,则Docker始终会优先使用两个容器中卷中的旧jar文件,而不是使用镜像中内置的jar文件。)
在这种情况下,似乎您正在寻找multi-stage build。您可以将这两个Dockerfile组合在一起,然后COPY
将jar文件从第一个映像复制到第二个映像。导致
FROM gradle:latest AS builder
WORKDIR /workspace
COPY . .
RUN gradle shadowJar --no-daemon
FROM openjdk:8-jre-slim AS java
WORKDIR /workdir
COPY --from=builder /workspace/build/libs/datainfrastructure-1.0-SNAPSHOT-all.jar stat.jar
CMD java -jar /workdir/stat.jar
在docker-compose.yml
文件中,您可以删除卷以及进行构建的无操作容器:
version: '3.8'
services:
generate_html:
ports:
- "8080:80"
build: .
答案 1 :(得分:0)
我假设已经在docker-compose.yml中创建了卷,那么我将自动获得目录/ workdir,而无需手动创建
这是不应该的,当您为某些服务声明卷映射时,您仅在将来的容器中声明卷与路径之间的映射。您的容器映像应保证该路径上存在某些东西。
我需要将此卷与另一个容器一起使用,该容器也不存在workdir目录
您的困惑很可能与您期望卷在构建时间内正常工作的事实有关。