对两个Docker容器使用相同的卷

对两个Docker容器使用相同的卷,docker,docker-compose,Docker,Docker Compose,我有两个容器,其中一个在另一个容器中提供我需要的文件,我想让第一个容器将该文件写入一个卷,然后让第二个容器访问该卷并读取该文件 我有以下docker compose.yml文件: version: '3' volumes: web_data: services: build_jar: build: context: . dockerfile: Dockerfile-gradle volumes: - web_data:/workd

我有两个容器,其中一个在另一个容器中提供我需要的文件,我想让第一个容器将该文件写入一个卷,然后让第二个容器访问该卷并读取该文件

我有以下
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
,它就是一个空目录。如何获取第一个容器所在卷上的文件?我是否在docker文件或docker compose.yml中缺少某些内容?

构建docker映像时,docker文件无法访问docker网络、卷或docker生态系统的任何其他部分。将docker build想象成Maven或Gradle一样是合理的:它生成一个映像,您可以复制到其他系统并在其他地方运行,但在构建时它无法访问运行时最终出现的数据

相应地,作为一般规则,Docker图像应该是自包含的。图像通常应包含其语言运行时以及运行应用程序所需的任何代码或工件;通过卷共享代码(或jar文件)通常不是最佳做法。(特别要注意的是,如果您成功地做到了这一点,Docker将始终在卷中、两个容器中使用旧的jar文件,而不是映像中内置的文件。)

在这种情况下,你更像是在寻找一个新的选择。您可以将这两个DockerFile组合在一起,然后将jar文件从第一个映像复制到第二个映像。这导致

来自gradle的
:最新版本为builder
WORKDIR/工作区
复制
运行gradle shadowJar--没有守护进程
来自openjdk:8-jre-slim作为java
WORKDIR/WORKDIR
复制--from=builder/workspace/build/libs/datainfrastructure-1.0-SNAPSHOT-all.jar stat.jar
CMD java-jar/workdir/stat.jar
docker compose.yml
文件中,您可以删除卷以及执行生成的无操作容器:

版本:“3.8”
服务:
生成html:
端口:
- "8080:80"
生成:。
我假设在docker-compose.yml中创建卷后,我将自动获取目录/workdir,而无需手动创建它

这是不应该的,当您为某些服务声明卷映射时,您只声明将来容器中卷和路径之间的映射。您的容器映像应该保证该路径上存在某些内容

我需要将此卷与另一个容器一起使用,该容器也不存在workdir目录


您的困惑可能与您期望卷在构建时工作这一事实有关,但不幸的是,这一事实并非如此。

谢谢!我知道多阶段构建,但问题是:我想在10分钟内运行第二个容器一次(我听说在docker compose中使用ofelia可以实现这一点?),但我不想运行Gradle容器,因为构建一个jar需要很长时间,所以我想有一种方法来运行它一次,保留jar,然后在循环中运行第二个容器。Idk,如果这是可能的话。所以,如果我使用多阶段构建,我也必须运行Gradle,这很慢,也有点不必要?jar本身总是一样的,你不必每次都重建图像。同样,通过与Gradle并行,您只需重新运行映像,而无需重建映像,就像运行
java-jar…
而无需重建jar文件一样
docker compose up
将使用现有图像(如果有);即使您指定
--build
,如果源文件没有更改,它也会运行得非常快。Java应用程序在Docker之外构建jar文件,然后
将其复制到映像中,而不是尝试在Docker中构建所有内容,这似乎也是相当常见的。如果jar文件很少更改,这可以简化您的工作。