如何使用docker-py(docker SDK)将文件从主机复制到容器中

16

我知道用 docker cp 可以在主机和 Docker 容器之间进行双向文件复制,并且可以使用 docker-py 从运行中的容器获取文件。但是,我无法想象如何(或者是否可能)使用 docker-py 将文件从主机复制到正在运行的容器中。

你们有没有遇到这样的问题?能否实现或者必须使用 Python 的 os.system 命令来执行?我希望避免使用后一种解决方案。


1
你可以使用 put_archive 做一些有趣的事情。https://docker-py.readthedocs.io/en/stable/containers.html#docker.models.containers.Container.put_archive - Oluwafemi Sule
谢谢,我在SDK中错过了这个选项,我一直在尝试复制。我打算尝试一下。 - s.t.e.a.l.t.h
有更新吗?我正在尝试将本地机器上的文件复制到Docker容器中。 - Michael Ababio
在这里查看答案...https://dev59.com/yGEh5IYBdhLWcg3ww1xp#59743346 - John Drinane
3个回答

27

这样做应该可以:

import os
import tarfile
import docker

client = docker.from_env()

def copy_to(src, dst):
    name, dst = dst.split(':')
    container = client.containers.get(name)

    os.chdir(os.path.dirname(src))
    srcname = os.path.basename(src)
    tar = tarfile.open(src + '.tar', mode='w')
    try:
        tar.add(srcname)
    finally:
        tar.close()

    data = open(src + '.tar', 'rb').read()
    container.put_archive(os.path.dirname(dst), data)

然后像这样使用:

copy_to('/local/foo.txt', 'my-container:/tmp/foo.txt')

1
如何在 put_archive 后从容器中提取存档? - Malar Kandasamy
在容器中使用 put_archive 后的文件名是什么? - Malar Kandasamy
@MalarKandasamy 看起来 put_archive 正在将其提取到 dst 中。 - Kobi

5

使用内存BytesIO的代码片段:

def copy_to_container(container: 'Container', src: str, dst_dir: str):
    """ src shall be an absolute path """
    stream = io.BytesIO()
    with tarfile.open(fileobj=stream, mode='w|') as tar, open(src, 'rb') as f:
        info = tar.gettarinfo(fileobj=f)
        info.name = os.path.basename(src)
        tar.addfile(info, f)

    container.put_archive(dst_dir, stream.getvalue())

不错!可以通过在with块中执行tar.add(src,arcname = os.path.basename(src))来简化这个过程,而不是打开文件,创建tarinfo并添加文件对象。 - Manuel Jacob

0
#!/usr/bin/python

import os
import tarfile
import docker

client = docker.from_env()

def copy_to(src, dst):
    name, dst = dst.split(':')
    container = client.containers.get(name)

    os.chdir(os.path.dirname(src))
    srcname = os.path.basename(src)
    tar = tarfile.open(srcname + '.tar', mode='w')
    obj=os.walk(srcname)
    for items in obj:
        for files in items[2]:
            if files[-4::] == ".csv" :
                abs_path = items[0] + "/" + files
                tar.add(abs_path)

    tar.close()
    data = open(srcname + '.tar', 'rb')
    container.put_archive(dst, data)
    data.close()

copy_to('source_directory', 'container_name:destination_directory')

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

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