【问题标题】:Running a Command Line Command in One Docker Container from Another and Sharing Files Back从另一个 Docker 容器中运行命令行命令并返回共享文件
【发布时间】:2016-05-07 11:16:41
【问题描述】:

在主机命令行上运行 docker,我可以在下载一组文件的容器中运行命令,并通过共享卷将这些文件共享回主机:

docker run --rm --volume "${PWD}":/contentmine --tty --interactive psychemedia/contentmine getpapers -q aardvark -o /contentmine/aardvark -x

我想做的是能够从使用 docker-compose.yaml 文件创建的 Jupyter 容器中运行相同的命令,该文件的格式为:

notebook:
  image: jupyter/notebook
  ports:
    - "8899:8888"
  volumes:
    - ./notebooks:/notebooks
    - /var/run/docker.sock:/var/run/docker.sock
  privileged: true 

在 Jupyter 笔记本代码单元中,我尝试运行:

#Make sure docker is available in the Jupyter container
!apt-get update
!apt-get install -y docker.io

!mkdir -p downloads
#Run a download command in another container and share the downloaded files back
! docker run --rm --volume "${PWD}/downloads":/contentmine --tty --interactive psychemedia/contentmine getpapers -q aardvark -o /contentmine/aardvark -x 

我可以看到文件在某处下载,但我不知道在哪里?它们是否已下载到 Jupyter 容器外部的 docker VM 上下文中?如何将我的 notebook 容器中的目录挂载到我用来运行文件下载命令行容器的临时容器中?

作为问题的第 2 部分,我还希望能够使用 downloads 目录中的文件作为在另一个容器中运行的另一个命令行命令的输入,并再次将结果的副本保留在notebook 容器downloads 目录:

docker run --rm --volume "${PWD}/downloads":/contentmine --tty --interactive psychemedia/contentmine norma --project /contentmine/aardvark -i fulltext.xml -o scholarly.html --transform nlm2html

大概,如果对问题的第一部分有快速修复,那么同样的修复也适用于这部分?

【问题讨论】:

标签: docker docker-compose jupyter-notebook


【解决方案1】:

我认为您正在寻找的答案涉及创建一个命名容器并将其指定为downloads/ 的挂载点,然后在创建时将其挂载到以后会话中使用它的任何容器中。

【讨论】:

  • 我已经在这家公司转了一圈,但找不到让它工作的方法?
【解决方案2】:

为了回答我自己的问题,我认为在命名链接数据卷容器时犯了一个错误。

这似乎有效 - 来自notebookdockercli/docker-compose.yml

notebook:
  image: jupyter/notebook
  ports:
    - "8899:8888"
  volumes_from:
    - contentmineshare

  volumes:
    - ./notebooks:/notebooks
    - /var/run/docker.sock:/var/run/docker.sock
  privileged: true 

contentmineshare:
  image: psychemedia/contentmine 
  volumes:
    - /contentmine

然后我可以在笔记本代码单元中运行:

!apt-get update
!apt-get install -y docker.io

然后运行 ​​docker CLI 命令:

! docker run --rm --volumes-from notebookdockercli_contentmineshare_1 --tty --interactive psychemedia/contentmine getpapers -q rhinocerous -o /contentmine/rhinocerous -x

然后我可以看到文件:

!ls  /contentmine/rhinocerous/

我遇到的问题是使用了错误的volumes-from 名称..(我不确定如何自动获取名称?)

为了创建一个 Docker IPython 魔法,使用 docker-py 创建一个数据卷容器可能会更简洁,供笔记本在与命令行容器同步文件时使用。

上述路由定义了一个命名数据卷容器,在启动时通过 docker compose 链接到笔记本容器。没有这个要求更灵活。

如果我们知道我们所在的笔记本容器的名称,并且我们知道共享目录的挂载点,我们可以在调用命令行容器时找到可以挂载为卷的目录的路径

import docker
def getPath(container,mountdir):
    cli = Client(base_url='unix://var/run/docker.sock')
    if cli.containers(filters={'name':container}):
        return [x['Source'] for x in cli.inspect_container(container ['Mounts'] if 'Destination' in x and  x['Destination']==mountdir ]
    return []

pp=getPath('/notebookdockercli_notebook_1','/notebooks')
DD='{}{}'.format(pp[0],'/testN')
! docker run -v {DD}:/contentmineTest --tty --interactive psychemedia/contentmine getpapers -q rhinocerous -o /contentmineTest/rhinocerous -x

这会将笔记本容器中的指定目录挂载到命令行容器的输出文件夹中。

由于某种原因,我无法让docker-py 为这条路线工作?我希望能够做到这一点:

cli = docker.Client(base_url='unix://var/run/docker.sock')
container_id = cli.create_container(image='psychemedia/contentmine',
                                volumes='{}{}:{}'.format(pp[0],'/test6','/contentmineTest'),
                                command='getpapers -q rhinocerous -o /contentmineTest/rhinocerous -x')
cli.start(container_id)

但它似乎没有安装在笔记本容器中?

然后我觉得这是一种更快的方法,尽管有将所有笔记本容器内容暴露给命令行容器的风险:将适当的卷从笔记本容器链接到命令行容器:

! docker run --rm --volumes-from notebookdockercli_notebook_1 psychemedia/contentmine getpapers -q rhinocerous -o /notebooks/maybe/rhinocerous -x

在 docker-py 中:

cli = docker.Client(base_url='unix://var/run/docker.sock')
container_id = cli.create_container('psychemedia/contentmine',
                                host_config=cli.create_host_config( volumes_from='notebookdockercli_notebook_1'),
                                command='getpapers -q rhinocerous -o /notebooks/testX/rhinocerous -x')
cli.start(container_id)

我不确定如何在运行后删除容器,因为它可能需要任意时间来运行,所以我们如何知道何时删除它? start() 似乎不接受 docker run --rm 开关?我想我们可以用特定的方式命名容器,最后做家务并将它们全部删除?

【讨论】:

  • 另一个步骤 - 通过运行获取 jupyter 容器的详细信息:import os,然后:cli.containers(filters={'id':os.environ['HOSTNAME']})[0]
猜你喜欢
  • 1970-01-01
  • 2018-03-19
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
  • 2013-01-22
相关资源
最近更新 更多