如何将文件从一个Docker容器复制到另一个容器?

16

这是我想做的:

  1. 进行 docker-compose 构建
  2. 运行 docker-compose $COMPOSE_ARGS run --rm task1
  3. 运行 docker-compose $COMPOSE_ARGS run --rm task2
  4. 运行 docker-compose $COMPOSE_ARGS run --rm combine-both-task2
  5. 运行 docker-compose $COMPOSE_ARGS run --rm selenium-test

同时还需要一个像这样的 docker-compose.yml 文件:

task1:
  build: ./task1
  volumes_from:
    - task1_output
  command: ./task1.sh

task1_output:
  image: alpine:3.3
  volumes:
    - /root/app/dist
  command: /bin/sh

# essentially I want to copy task1 output into task2 because they each use different images and use different tech stacks... 
task2:
  build: ../task2
  volumes_from:
    - task2_output
    - task1_output:ro
  command: /bin/bash -cx "mkdir -p task1 && cp -R /root/app/dist/* ."

现在所有需要的文件都在task2容器中了...那我该如何启动一个Web服务器并暴露一个端口,以便使用task2中的内容?

我卡在这里了...我该如何在我的combine-tasks/Dockerfile中访问task2_output中的内容?

combine-both-task2:
  build: ../combine-tasks
  volumes_from:
     - task2_output
2个回答

24

在最近版本的docker中,命名卷替代数据容器成为容器之间共享数据的简单方式。

docker volume create --name myshare
docker run -v myshare:/shared task1
docker run -v myshare:/shared -p 8080:8080 task2
...

这些命令将设置一个本地卷,-v myshare:/shared 参数将使该共享文件夹作为 /shared 文件夹在每个容器内可用。

要在compose文件中表达:

version: '2'
services:
  task1:
    build: ./task1
  volumes:
    - 'myshare:/shared'

  task2:
    build: ./task2
  ports:
    - '8080:8080'
  volumes:
    - 'myshare:/shared'

volumes:
  myshare:
    driver: local 

为了测试这个,我做了一个小项目:

- docker-compose.yml (above)
- task1/Dockerfile
- task1/app.py
- task2/Dockerfile

我在任务2的 Dockerfile 文件中使用了 Node 的 http-server:

FROM node
RUN npm install -g http-server
WORKDIR /shared
CMD http-server

task1/Dockerfile 则使用了 python:alpine,以展示两个不同的堆栈进行读写。

FROM python:alpine
WORKDIR /app
COPY . .
CMD python app.py

这里是task1/app.py

import time

count = 0
while True:
  fname = '/shared/{}.txt'.format(count)
  with open(fname, 'w') as f:
    f.write('content {}'.format(count))
    count = count + 1
  time.sleep(10)

拿着这四个文件,在带有docker-compose.yml的目录中通过 docker compose up 命令运行它们,然后访问 $DOCKER_HOST:8080 查看一个不断更新的文件列表。

另外,我正在使用 Docker 版本为 1.12.0,Compose 版本为 1.8.0,但这应该适用于几个版本前的 Docker。

别忘了查看 Docker 文档以获取可能被省略的详细信息:
https://docs.docker.com/engine/tutorials/dockervolumes/


我尝试了您的示例,让task1创建hello.txt文件,然后在task2中尝试查找该文件,以下是输出结果: 步骤1:FROM ubuntu ---> f8d79ba03c00 步骤2:RUN echo "hello" > hello.txt ---> 使用缓存 ---> 3f2e4e8df3ec 成功构建3f2e4e8df3ec 构建task2 步骤1:FROM ubuntu ---> f8d79ba03c00 步骤2:WORKDIR /shared ---> 使用缓存 ---> bc2f077838ce 步骤3:RUN ls hello.txt ---> 运行中 ls: 无法访问'hello.txt':没有那个文件或目录 错误:服务'task2'构建失败:命令'/bin/sh -c ls hello.txt' - Tin Ng
混淆可能在于构建时间与运行时间。卷共享仅在docker run期间存在,而不是在docker build期间存在。因此,RUN ls hello.txt未连接到共享以进行读取,而RUN echo "hello" > hello.txt仅在本地写入第一个映像。我将添加完整的Python Dockerfile,以便您可以复制我的示例的所有部分。 - Jett Jones
谢谢Jett。我认为你说得非常正确,这是构建时间与运行时间的问题。本质上,我希望task1能够生成一些工件,例如npm run dist(生成js、图像等文件),然后task2将这些文件复制到其镜像中,然后启动tomcat。然后,task3对task2运行selenium。非常感谢你迄今为止的帮助。 - Tin Ng
很高兴能帮上忙。接下来的步骤似乎是创建一个脚本,用于读取或写入卷,并将这些脚本作为容器的“CMD”指令。在我的示例中,“app.py”和“http-server”就是这样使用卷的。 - Jett Jones

4

对于我来说,从或者到容器中拷贝文件的最佳方式是使用 docker cp,例如:

如果你想要从 apacheNutch 容器中拷贝 schema.xml 文件到 solr 容器,则可以执行以下操作:

  1. docker cp apacheNutch:/root/nutch/conf/schema.xml /tmp/schema.xml server/solr/configsets/nutch/

  2. docker cp /tmp/schema.xml solr:/opt/solr-8.1.1/server/solr/configsets/nutch/conf


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接