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

feat(core): allow custom dockerfile path for image build and bypassing build cache #615

Merged
merged 1 commit into from
Jun 22, 2024
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
12 changes: 10 additions & 2 deletions core/testcontainers/core/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ class DockerImage:
... logs = image.get_logs()

:param tag: Tag for the image to be built (default: None)
:param path: Path to the Dockerfile to build the image
:param path: Path to the build context
:param dockerfile_path: Path to the Dockerfile within the build context path (default: Dockerfile)
:param no_cache: Bypass build cache; CLI's --no-cache
"""

def __init__(
Expand All @@ -33,6 +35,8 @@ def __init__(
docker_client_kw: Optional[dict] = None,
tag: Optional[str] = None,
clean_up: bool = True,
dockerfile_path: Union[str, PathLike] = "Dockerfile",
no_cache: bool = False,
**kwargs,
) -> None:
self.tag = tag
Expand All @@ -42,11 +46,15 @@ def __init__(
self._kwargs = kwargs
self._image = None
self._logs = None
self._dockerfile_path = dockerfile_path
self._no_cache = no_cache

def build(self, **kwargs) -> Self:
logger.info(f"Building image from {self.path}")
docker_client = self.get_docker_client()
self._image, self._logs = docker_client.build(path=str(self.path), tag=self.tag, **kwargs)
self._image, self._logs = docker_client.build(
path=str(self.path), tag=self.tag, dockerfile=self._dockerfile_path, nocache=self._no_cache, **kwargs
)
logger.info(f"Built image {self.short_id} with tag {self.tag}")
return self

Expand Down
28 changes: 28 additions & 0 deletions core/tests/test_core.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import pytest
import tempfile
import random
import os

from pathlib import Path
from typing import Optional

from testcontainers.core.container import DockerContainer
Expand Down Expand Up @@ -64,3 +66,29 @@ def test_docker_image(test_image_tag: Optional[str], test_cleanup: bool, check_f
assert container.get_logs() == ((random_string + "\n").encode(), b""), "Container logs mismatch"

check_for_image(image_short_id, test_cleanup)


@pytest.mark.parametrize("dockerfile_path", [None, Path("subdir/my.Dockerfile")])
def test_docker_image_with_custom_dockerfile_path(dockerfile_path: Optional[Path]):
with tempfile.TemporaryDirectory() as temp_directory:
temp_dir_path = Path(temp_directory)
if dockerfile_path:
os.makedirs(temp_dir_path / dockerfile_path.parent, exist_ok=True)
dockerfile_rel_path = dockerfile_path
dockerfile_kwargs = {"dockerfile_path": dockerfile_path}
else:
dockerfile_rel_path = Path("Dockerfile") # default
dockerfile_kwargs = {}

with open(temp_dir_path / dockerfile_rel_path, "x") as f:
f.write(
f"""
FROM alpine:latest
CMD echo "Hello world!"
"""
)
with DockerImage(path=temp_directory, tag="test", clean_up=True, no_cache=True, **dockerfile_kwargs) as image:
image_short_id = image.short_id
with DockerContainer(str(image)) as container:
assert container._container.image.short_id.endswith(image_short_id), "Image ID mismatch"
assert container.get_logs() == (("Hello world!\n").encode(), b""), "Container logs mismatch"