Skip to content

Commit dfdc36c

Browse files
add volumes parameter to images_build
Signed-off-by: Federico Rizzo <[email protected]>
1 parent 8864814 commit dfdc36c

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

podman/domain/images_build.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,28 @@ def build(self, **kwargs) -> tuple[Image, Iterator[bytes]]:
6666
layers (bool) - Cache intermediate layers during build.
6767
output (str) - specifies if any custom build output is selected for following build.
6868
outputformat (str) - The format of the output image's manifest and configuration data.
69+
volumes (dict[str, dict[str, Union[str, list]]])
70+
Mount a host directory into containers when executing RUN instructions during the build.
71+
The key is the host path and the value is a dictionary with the keys:
72+
73+
- bind: The path to mount the volume inside the container
74+
- mode: One or multiple of [ro|rw],[z|Z|O],[U],[[r]shared|[r]slave|[r]private]
75+
By default, the volumes are mounted read-write
76+
77+
For example:
78+
79+
{
80+
81+
'/etc/host':
82+
83+
{'bind': '/etc/host', 'mode': 'ro'},
84+
85+
'/tmp/cache':
86+
87+
{'bind': '/var/cache/libdnf5', 'mode': ['rw', 'z']},
88+
89+
}
90+
6991
7092
Returns:
7193
first item is the podman.domain.images.Image built
@@ -184,6 +206,7 @@ def _render_params(kwargs) -> dict[str, list[Any]]:
184206
"layers": kwargs.get("layers"),
185207
"output": kwargs.get("output"),
186208
"outputformat": kwargs.get("outputformat"),
209+
"volume": [],
187210
}
188211

189212
if "buildargs" in kwargs:
@@ -215,5 +238,17 @@ def default(value, def_value):
215238
params["dockerfile"], f".containerfile.{random.getrandbits(160):x}"
216239
)
217240

241+
volumes = kwargs.get("volumes")
242+
if volumes is not None:
243+
for hostdir, target in volumes.items():
244+
mode = target.get('mode', [])
245+
binddir = target.get('bind')
246+
if binddir is None:
247+
raise ValueError("'bind' value not defined")
248+
if not isinstance(mode, list):
249+
raise ValueError("'mode' value should be a list")
250+
mode_str = ",".join(mode)
251+
params["volume"].append(f"{hostdir}:{target['bind']}:{mode_str}")
252+
218253
# Remove any unset parameters
219254
return dict(filter(lambda i: i[1] is not None, params.items()))

podman/tests/integration/test_images.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import platform
2020
import tarfile
2121
import types
22+
import random
2223
import unittest
24+
from tempfile import NamedTemporaryFile
2325

2426
import podman.tests.integration.base as base
2527
from podman import PodmanClient
@@ -158,6 +160,25 @@ def test_build_cache(self):
158160
break
159161
self.assertEqual(parsed.split()[3], image.id)
160162

163+
def test_build_volume(self):
164+
file = self.enterContext(NamedTemporaryFile(mode="w+"))
165+
content = "test"
166+
file.write(content)
167+
file.seek(0)
168+
containerfile_str = "\n".join(
169+
[
170+
"FROM quay.io/libpod/alpine_labels:latest",
171+
f"RUN cp /host{file.name} /copy",
172+
"""CMD ["cat", "/copy"]""",
173+
]
174+
)
175+
buffer = io.StringIO(containerfile_str)
176+
177+
vol_dict = {f"{file.name}": {"bind": f"/host{file.name}", "mode": ["ro", "Z"]}}
178+
image, stream = self.client.images.build(fileobj=buffer, volumes=vol_dict)
179+
cntr = self.client.containers.run(image, remove=True, stdout=True)
180+
self.assertEqual(cntr.decode(), content)
181+
161182
def test_build_with_context(self):
162183
context = io.BytesIO()
163184
with tarfile.open(fileobj=context, mode="w") as tar:

0 commit comments

Comments
 (0)