Skip to content

Commit 43d5de2

Browse files
committed
fix: Improve context path handling for custom Dockerfiles
Signed-off-by: verils <[email protected]>
1 parent f7eeda1 commit 43d5de2

File tree

2 files changed

+120
-39
lines changed

2 files changed

+120
-39
lines changed

podman_compose.py

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2851,18 +2851,23 @@ def container_to_build_args(
28512851
build_desc = cnt["build"]
28522852
if not hasattr(build_desc, "items"):
28532853
build_desc = {"context": build_desc}
2854+
28542855
ctx = build_desc.get("context", ".")
2855-
dockerfile = build_desc.get("dockerfile", "")
2856-
dockerfile_inline = build_desc.get("dockerfile_inline")
2857-
if dockerfile_inline is not None:
2858-
dockerfile_inline = str(dockerfile_inline)
2856+
custom_dockerfile = build_desc.get("dockerfile", "")
2857+
custom_dockerfile_inline = build_desc.get("dockerfile_inline")
2858+
2859+
build_args = []
2860+
2861+
dockerfile = None
2862+
if custom_dockerfile_inline is not None:
2863+
dockerfile_inline = str(custom_dockerfile_inline)
28592864
# Error if both `dockerfile_inline` and `dockerfile` are set
2860-
if dockerfile and dockerfile_inline:
2865+
if custom_dockerfile and dockerfile_inline:
28612866
raise OSError("dockerfile_inline and dockerfile can't be used simultaneously")
2862-
dockerfile = tempfile.NamedTemporaryFile(delete=False, suffix=".containerfile")
2863-
dockerfile.write(dockerfile_inline.encode())
2864-
dockerfile.close()
2865-
dockerfile = dockerfile.name
2867+
dockerfile_tmp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".containerfile")
2868+
dockerfile_tmp_file.write(dockerfile_inline.encode())
2869+
dockerfile_tmp_file.close()
2870+
dockerfile = dockerfile_tmp_file.name
28662871

28672872
def cleanup_temp_dockfile() -> None:
28682873
if os.path.exists(dockerfile):
@@ -2871,36 +2876,39 @@ def cleanup_temp_dockfile() -> None:
28712876
if cleanup_callbacks is not None:
28722877
cleanup_callbacks.append(cleanup_temp_dockfile)
28732878

2874-
build_args = []
2875-
# if givent context was not recognized as git url, try joining paths to get a file locally
2876-
if not is_context_git_url(ctx):
2877-
custom_dockerfile_given = False
2878-
if dockerfile:
2879-
dockerfile = os.path.join(ctx, dockerfile)
2880-
custom_dockerfile_given = True
2881-
else:
2882-
dockerfile_alts = [
2883-
"Containerfile",
2884-
"ContainerFile",
2885-
"containerfile",
2886-
"Dockerfile",
2887-
"DockerFile",
2888-
"dockerfile",
2889-
]
2890-
for dockerfile in dockerfile_alts:
2891-
dockerfile = os.path.join(ctx, dockerfile)
2892-
if path_exists(dockerfile):
2893-
break
2894-
2895-
if path_exists(dockerfile):
2896-
# normalize dockerfile path, as the user could have provided unpredictable file formats
2897-
dockerfile = os.path.normpath(os.path.join(ctx, dockerfile))
2898-
build_args.extend(["-f", dockerfile])
2899-
else:
2900-
if custom_dockerfile_given:
2901-
# custom dockerfile name was also not found in the file system
2902-
raise OSError(f"Dockerfile not found in {dockerfile}")
2903-
raise OSError(f"Dockerfile not found in {ctx}")
2879+
build_args.extend(["-f", dockerfile])
2880+
else:
2881+
# if givent context was not recognized as git url, try joining paths to get a file locally
2882+
if not is_context_git_url(ctx):
2883+
dockerfile = None
2884+
dockerfile_from_cwd = None
2885+
custom_dockerfile_given = False
2886+
if custom_dockerfile:
2887+
dockerfile = custom_dockerfile
2888+
dockerfile_from_cwd = os.path.join(ctx, custom_dockerfile)
2889+
custom_dockerfile_given = True
2890+
else:
2891+
dockerfile_alts = [
2892+
"Containerfile",
2893+
"ContainerFile",
2894+
"containerfile",
2895+
"Dockerfile",
2896+
"DockerFile",
2897+
"dockerfile",
2898+
]
2899+
for dockerfile in dockerfile_alts:
2900+
dockerfile_from_cwd = os.path.join(ctx, dockerfile)
2901+
if path_exists(dockerfile_from_cwd):
2902+
break
2903+
2904+
if path_exists(dockerfile_from_cwd):
2905+
# normalize dockerfile path, as the user could have provided unpredictable file formats
2906+
build_args.extend(["-f", dockerfile])
2907+
else:
2908+
if custom_dockerfile_given:
2909+
# custom dockerfile name was also not found in the file system
2910+
raise OSError(f"Dockerfile not found at {custom_dockerfile}")
2911+
raise OSError(f"Dockerfile not found in {ctx}")
29042912

29052913
build_args.extend(["-t", cnt["image"]])
29062914

@@ -2939,6 +2947,7 @@ def cleanup_temp_dockfile() -> None:
29392947
build_args.extend(["--cache-from", cache_img])
29402948
for cache_img in build_desc.get("cache_to", []):
29412949
build_args.extend(["--cache-to", cache_img])
2950+
29422951
build_args.append(ctx)
29432952
return build_args
29442953

tests/unit/test_container_to_build_args.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,78 @@ def test_caches(self):
158158
],
159159
)
160160

161+
def test_dockerfile_with_relative_context_and_dockerfile(self):
162+
c = create_compose_mock()
163+
164+
cnt = get_minimal_container()
165+
cnt['build']['context'] = "../"
166+
cnt['build']['dockerfile'] = "compose/backend/Containerfile"
167+
168+
args = get_minimal_args()
169+
170+
args = container_to_build_args(c, cnt, args, lambda path: True)
171+
172+
self.assertEqual(
173+
[
174+
'-f',
175+
'compose/backend/Containerfile',
176+
'-t',
177+
'new-image',
178+
'--no-cache',
179+
'--pull-always',
180+
'../',
181+
],
182+
args
183+
)
184+
185+
def test_dockerfile_with_relative_context_and_dockerfile_1(self):
186+
c = create_compose_mock()
187+
188+
cnt = get_minimal_container()
189+
cnt['build']['context'] = "subdir/"
190+
cnt['build']['dockerfile'] = "compose/backend/Containerfile"
191+
192+
args = get_minimal_args()
193+
194+
args = container_to_build_args(c, cnt, args, lambda path: True)
195+
196+
self.assertEqual(
197+
[
198+
'-f',
199+
'compose/backend/Containerfile',
200+
'-t',
201+
'new-image',
202+
'--no-cache',
203+
'--pull-always',
204+
'subdir/',
205+
],
206+
args
207+
)
208+
209+
def test_dockerfile_with_absolute_context_and_dockerfile(self):
210+
c = create_compose_mock()
211+
212+
cnt = get_minimal_container()
213+
cnt['build']['context'] = "/context/path"
214+
cnt['build']['dockerfile'] = "compose/backend/Containerfile"
215+
216+
args = get_minimal_args()
217+
218+
args = container_to_build_args(c, cnt, args, lambda path: True)
219+
220+
self.assertEqual(
221+
[
222+
'-f',
223+
'compose/backend/Containerfile',
224+
'-t',
225+
'new-image',
226+
'--no-cache',
227+
'--pull-always',
228+
'/context/path',
229+
],
230+
args
231+
)
232+
161233
def test_dockerfile_inline(self):
162234
c = create_compose_mock()
163235

0 commit comments

Comments
 (0)