diff --git a/core/testcontainers/core/image.py b/core/testcontainers/core/image.py index 4004e9e4..6d793f83 100644 --- a/core/testcontainers/core/image.py +++ b/core/testcontainers/core/image.py @@ -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__( @@ -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 @@ -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 diff --git a/core/tests/test_core.py b/core/tests/test_core.py index efac8262..8d0c7794 100644 --- a/core/tests/test_core.py +++ b/core/tests/test_core.py @@ -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 @@ -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"