Docker python 客户端不是从自定义上下文构建映像



简而言之:问题是,我希望docker客户端从用户定义的上下文运行docker build命令。

在长:所以这是我的目录结构;

main_directory
└── package
├──directory_x
└──directory_y
├──docker
|  └──Dockerfile 
+-─dockerclient.py
:

我的 docker 文件有一个步骤,我需要将整个main_directory复制到temp文件夹中。

COPY . /path/temp/main_directory/

main_directory以下命令有效;

docker build -t foo:bar -f package/directory_y/docker/Dockerfile .

但是在使用python docker客户端时我无法做到这一点,因为它要求我提供Dockerfile的path,然后从该给定路径运行docker build命令。我的dockerclient.py有以下代码;

import docker
from ast import literal_eval
class DockerBuildException(BaseException): pass
client = docker.from_env()
dirPath = os.path.dirname(os.path.realpath(__file__))
# dirPath = path/to/main_directory/jagex_airflow/test
try:
responce = client.images.build(path=dirPath + "/docker", tag="foo:bar")
print(responce)
for i in responce:
if b'errorDetail' in i:
d = literal_eval(i.decode('ascii'))
raise DockerBuildException(d['errorDetail']['message'])
except DockerBuildException as e:
print("Error: " + e.args[0])
raise

这种方法的问题是COPY .将所有文件/目录从~/main_directory/jagex_airflow/test/docker复制到容器中。而我希望它从main_directory复制所有内容.

我还尝试分别传入 Dockerfile 路径和上下文路径

with open(dirPath + "/docker/Dockerfile") as file_:
dockerfile = file_.read()
f = BytesIO(dockerfile.encode('utf-8'))
client.images.build(path="path/to/main_directory/", fileobj=f, tag="foo:bar")

但这也没有奏效。

我想知道是否有任何可选参数可以client.images.build指定从何处运行docker build命令,以及一个单独的参数提及Dockerfile路径? 这里也提出了类似的问题,但没有正确的答案。从用户评论中,有人建议将 Dockerfile 保留在根目录中,但这不是我想要做的。我的意思是,如果可以从基本的docker build命令中完成,那么为什么不通过python客户端呢?还是 docker python SDK 真的有这个限制?如果是这种情况,有人可以向我推荐任何用于 docker 的替代 python 客户端(如果有的话(吗?

我认为你应该改用dockerfile参数

...    
responce = client.images.build(dockerfile=dirPath + "/docker/Dockerfile", tag="foo:bar")
...

https://docker-py.readthedocs.io/en/stable/images.html

你在这里似乎有几个问题。

  1. 使用不在 docker 临时目录中的 dockerfile 构建映像。
  2. 复制主项目,以便容器可以访问它

让我们解决您在tempdir之外构建dockerfile的第一个问题:

with open(os.path.join(path_to_dockerfile, 'Dockerfile'), 'rb') as DockerFile:
image, _ = client.images.build(fileobj=DockerFile, 
labels={'name': 'some_name'})
image.tag(repository='some_repository_name')

这使您可以打开几乎位于任何地方的Dockerfile(您甚至可以以这种方式进行花哨的步法来访问远程dockerfiles(,并从该文件创建映像

复制主项目,以便可以从容器访问它

当前,您正在尝试从图像执行此操作。这是有道理的,因为它减少了代码开销,但基于 python SDK 是不切实际的,特别是因为 docker 仅限于 docker-build tmp 目录的上下文。但是,在容器端有一个更高效、更优雅的解决方案:

container = client.containers.run(image='some_image', cmd='some_cmd(/bin/bash)'
name='some_name',
volumes={main_directory: {'bind': container_dir,
'mode': 'rw'}})

通过将文件系统挂载到容器中,您不必在每次从映像构建时浪费时间复制目录,并且您摆脱了超越 docker 构建上下文的痛苦。

注意:Docker 不能很好地处理符号链接。您可能需要创建文件系统的副本(我建议使用 shutil(,该副本已解析符号链接。

最新更新