Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for dockerfile_inline #1116

Merged
merged 1 commit into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions examples/docker-inline/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
version: '3'
services:
dummy:
build:
context: .
dockerfile_inline: |
FROM alpine
RUN echo "hello world"
54 changes: 39 additions & 15 deletions podman_compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import signal
import subprocess
import sys
import tempfile
from asyncio import Task
from enum import Enum

Expand Down Expand Up @@ -2471,27 +2472,45 @@ async def compose_push(compose, args):
await compose.podman.run([], "push", [cnt["image"]])


def container_to_build_args(compose, cnt, args, path_exists):
def container_to_build_args(compose, cnt, args, path_exists, cleanup_callbacks=None):
build_desc = cnt["build"]
if not hasattr(build_desc, "items"):
build_desc = {"context": build_desc}
ctx = build_desc.get("context", ".")
dockerfile = build_desc.get("dockerfile")
if dockerfile:
dockerfile = os.path.join(ctx, dockerfile)
dockerfile_inline = build_desc.get("dockerfile_inline")
if dockerfile_inline is not None:
dockerfile_inline = str(dockerfile_inline)
# Error if both `dockerfile_inline` and `dockerfile` are set
if dockerfile and dockerfile_inline:
raise OSError("dockerfile_inline and dockerfile can't be used simultaneously")
dockerfile = tempfile.NamedTemporaryFile(delete=False, suffix=".containerfile")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current code does not remove the temporary file, does it? I think this is primary deficiency of the current approach. Not sure how to best solve it right now.

One solution would be to introduce a list of cleanup functions that need to be called before podman-compose exits. Then pass this list to container_to_build_args which would append an appropriate os.remove call to that list. And then after podman build completes, remove the file in e.g. finally.

dockerfile.write(dockerfile_inline.encode())
dockerfile.close()
dockerfile = dockerfile.name

def cleanup_temp_dockfile():
if os.path.exists(dockerfile):
os.remove(dockerfile)

if cleanup_callbacks is not None:
list.append(cleanup_callbacks, cleanup_temp_dockfile)
else:
dockerfile_alts = [
"Containerfile",
"ContainerFile",
"containerfile",
"Dockerfile",
"DockerFile",
"dockerfile",
]
for dockerfile in dockerfile_alts:
if dockerfile:
dockerfile = os.path.join(ctx, dockerfile)
if path_exists(dockerfile):
break
else:
dockerfile_alts = [
"Containerfile",
"ContainerFile",
"containerfile",
"Dockerfile",
"DockerFile",
"dockerfile",
]
for dockerfile in dockerfile_alts:
dockerfile = os.path.join(ctx, dockerfile)
if path_exists(dockerfile):
break
if not path_exists(dockerfile):
raise OSError("Dockerfile not found in " + ctx)
build_args = ["-f", dockerfile, "-t", cnt["image"]]
Expand Down Expand Up @@ -2546,8 +2565,13 @@ async def build_one(compose, args, cnt):
if img_id:
return None

build_args = container_to_build_args(compose, cnt, args, os.path.exists)
cleanup_callbacks = []
build_args = container_to_build_args(
compose, cnt, args, os.path.exists, cleanup_callbacks=cleanup_callbacks
)
status = await compose.podman.run([], "build", build_args)
for c in cleanup_callbacks:
c()
return status


Expand Down
24 changes: 24 additions & 0 deletions tests/unit/test_container_to_build_args.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0

import os
import unittest
from unittest import mock

Expand Down Expand Up @@ -156,3 +157,26 @@ def test_caches(self):
'.',
],
)

def test_dockerfile_inline(self):
c = create_compose_mock()

cnt = get_minimal_container()
cnt['build']['dockerfile_inline'] = "FROM busybox\nRUN echo 'hello world'"
args = get_minimal_args()

cleanup_callbacks = []
args = container_to_build_args(
c, cnt, args, lambda path: True, cleanup_callbacks=cleanup_callbacks
)

temp_dockerfile = args[args.index("-f") + 1]
self.assertTrue(os.path.exists(temp_dockerfile))

with open(temp_dockerfile, "rt") as file:
contents = file.read()
self.assertEqual(contents, "FROM busybox\n" + "RUN echo 'hello world'")

for c in cleanup_callbacks:
c()
self.assertFalse(os.path.exists(temp_dockerfile))
Loading