如何通过Dockerfile访问Docker Compose创建的卷并复制文件?
问题
在Docker Compose中创建了一个卷,希望将文件复制到该卷中,需要编写对应的Dockerfile,但不清楚如何通过Dockerfile访问Docker Compose里创建的卷,请问该如何操作?
提供的配置文件如下:
docker-compose.yml
version: '3' services: postgres: image: postgres hostname: postgres restart: always ports: - "5432:5432" environment: POSTGRES_DB: test POSTGRES_USER: test POSTGRES_PASSWORD: test pgadmin: image: dpage/pgadmin4 restart: always ports: - "5433:80" environment: PGADMIN_DEFAULT_EMAIL: test@gmail.com PGADMIN_DEFAULT_PASSWORD: test depends_on: - postgres web: build: context: ../ dockerfile: spring/Dockerfile ports: - "8080:8080" depends_on: - postgres volumes: - ./test-volume:/opt/_LIB/
Dockerfile
FROM ... RUN rm -rf /var/lib/jetty/webapps/* COPY spring/target/*.war /var/lib/jetty/webapps/ EXPOSE 8080 #CMD ["java", "-jar", "$JETTY_HOME/start.jar"]
解决方案
首先明确:Dockerfile构建镜像的阶段无法直接访问Docker Compose定义的卷,因为镜像构建是独立于容器运行的流程,挂载卷是容器启动时才会执行的操作。下面提供几种可行的实现方式:
方式一:容器启动时复制文件到卷目录
利用容器启动命令,先将镜像内的目标文件复制到卷挂载的目录(/opt/_LIB/),再启动应用。
修改Dockerfile的CMD指令,添加复制步骤:
FROM ... RUN rm -rf /var/lib/jetty/webapps/* COPY spring/target/*.war /var/lib/jetty/webapps/ EXPOSE 8080 CMD ["sh", "-c", "cp /var/lib/jetty/webapps/*.war /opt/_LIB/ && java -jar $JETTY_HOME/start.jar"]
如果需要更复杂的启动逻辑,可以编写一个启动脚本:
- 在项目目录下创建
startup.sh脚本:
#!/bin/sh # 复制文件到卷目录 cp /var/lib/jetty/webapps/*.war /opt/_LIB/ # 启动Jetty服务 java -jar $JETTY_HOME/start.jar
- 修改Dockerfile,将脚本复制到镜像并设置执行权限:
FROM ... RUN rm -rf /var/lib/jetty/webapps/* COPY spring/target/*.war /var/lib/jetty/webapps/ # 复制并配置启动脚本 COPY spring/startup.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/startup.sh EXPOSE 8080 CMD ["startup.sh"]
方式二:提前将文件复制到宿主机绑定目录
你当前使用的是绑定挂载(将宿主机./test-volume目录挂载到容器/opt/_LIB/),可以直接在宿主机上将需要的文件复制到./test-volume目录,容器启动后会自动读取该目录下的文件。
比如在构建镜像的脚本中添加一步:
cp spring/target/*.war ./test-volume/
方式三:改用命名卷利用自动初始化特性
如果将绑定挂载改为Docker命名卷,当卷为空时,Docker会自动将镜像中对应挂载目录的内容复制到卷中。
修改docker-compose.yml:
version: '3' services: # ... 其他服务保持不变 web: build: context: ../ dockerfile: spring/Dockerfile ports: - "8080:8080" depends_on: - postgres volumes: - test-volume:/opt/_LIB/ # 添加命名卷定义 volumes: test-volume:
此时需要确保镜像中/opt/_LIB/目录有需要的文件,所以可以修改Dockerfile将war包复制到该目录:
FROM ... RUN rm -rf /var/lib/jetty/webapps/* COPY spring/target/*.war /var/lib/jetty/webapps/ # 同时复制到/opt/_LIB/,供命名卷初始化使用 COPY spring/target/*.war /opt/_LIB/ EXPOSE 8080 CMD ["java", "-jar", "$JETTY_HOME/start.jar"]
注意:这个特性仅在命名卷第一次创建且为空时生效,后续启动不会覆盖卷内已有内容。
内容的提问来源于stack exchange,提问作者user19763876
相关产品推荐
相关产品推荐

