从另一个Docker容器中运行命令行命令并重新共享文件

时间:2016-05-07 11:16:42

标签: docker docker-compose jupyter-notebook

在主机命令行上运行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 

我可以看到文件在某处下载,但我不知道在哪里?它们是否已下载到Docker VM上下文 Jupyter容器中?如何从我正用于运行文件下载命令行容器的临时容器中的 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

据推测,如果快速解决问题的第一部分,同样的修复适用于这部分吗?

2 个答案:

答案 0 :(得分:0)

我认为您正在寻找的答案包括创建一个命名容器并将其指定为SELECT c.id, c.name, i.* FROM countries c, images i WHERE i.country_id = c.id GROUP BY c.id; Fixed for 5.7; SELECT c.id, c.name, ANY_VALUE(i.url) url, ANY_VALUE(i.lat) lat, ANY_VALUE(i.lng) lng FROM countries c, images i WHERE i.country_id = c.id GROUP BY c.id; 的挂载点,然后在创建时将其挂载在以后会话中使用它的任何容器中。

答案 1 :(得分:0)

要回答我自己的问题,我认为在命名链接数据卷容器时会出错。

这似乎有效 - 来自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 magic ,使用docker-py创建数据卷容器以供笔记本在与命令行容器同步文件时使用它可能会更清晰。< / p>

上述路由定义了一个在启动时通过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 switch?我想我们可以用特定的方式命名容器,最后做家务并将它们全部删除?