Skip to content

Commit 852c3a3

Browse files
committed
add support for docker compose v2
Signed-off-by: Paul S. Schweigert <[email protected]>
1 parent 94a63d6 commit 852c3a3

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

compose/testcontainers/compose/__init__.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Iterable, List, Optional, Tuple, Union
33

44
import requests
5+
from functools import cached_property
56

67
from testcontainers.core.exceptions import NoSuchPortExposed
78
from testcontainers.core.waiting_utils import wait_container_is_ready
@@ -14,6 +15,9 @@ class DockerCompose:
1415
Args:
1516
filepath: Relative directory containing the docker compose configuration file.
1617
compose_file_name: File name of the docker compose configuration file.
18+
compose_command: The command to use for docker compose. If not specified, a call to
19+
docker compose --help will be made to determine the correct command to use.
20+
If docker compose is not installed, docker-compose will be used.
1721
pull: Pull images before launching environment.
1822
build: Build images referenced in the configuration file.
1923
env_file: Path to an env file containing environment variables to pass to docker compose.
@@ -45,6 +49,7 @@ def __init__(
4549
self,
4650
filepath: str,
4751
compose_file_name: Union[str, Iterable] = "docker-compose.yml",
52+
compose_command: str = None,
4853
pull: bool = False,
4954
build: bool = False,
5055
env_file: Optional[str] = None,
@@ -57,6 +62,7 @@ def __init__(
5762
self.build = build
5863
self.env_file = env_file
5964
self.services = services
65+
self._user_defined_compose_command = compose_command.split(" ") if compose_command else None
6066

6167
def __enter__(self) -> "DockerCompose":
6268
self.start()
@@ -65,14 +71,30 @@ def __enter__(self) -> "DockerCompose":
6571
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
6672
self.stop()
6773

74+
@cached_property
75+
def base_docker_compose(self):
76+
"""
77+
Returns the basecommand parts used for the docker compose commands depending on the docker compose api
78+
79+
Returns
80+
-------
81+
list[str]
82+
The docker compose command parts
83+
"""
84+
if self._user_defined_compose_command:
85+
return self._user_defined_compose_command
86+
87+
return ["docker","compose"] if subprocess.run(["docker", "compose", "--help"], stdout=subprocess.DEVNULL,
88+
stderr=subprocess.STDOUT).returncode == 0 else ["docker-compose"]
89+
6890
def docker_compose_command(self) -> List[str]:
6991
"""
7092
Returns command parts used for the docker compose commands
7193
7294
Returns:
7395
cmd: Docker compose command parts.
7496
"""
75-
docker_compose_cmd = ['docker-compose']
97+
docker_compose_cmd = self.base_docker_compose[:]
7698
for file in self.compose_file_names:
7799
docker_compose_cmd += ['-f', file]
78100
if self.env_file:
@@ -92,7 +114,6 @@ def start(self) -> None:
92114
up_cmd.append('--build')
93115
if self.services:
94116
up_cmd.extend(self.services)
95-
96117
self._call_command(cmd=up_cmd)
97118

98119
def stop(self) -> None:
@@ -168,7 +189,10 @@ def get_service_host(self, service_name: str, port: int) -> str:
168189

169190
def _get_service_info(self, service: str, port: int) -> List[str]:
170191
port_cmd = self.docker_compose_command() + ["port", service, str(port)]
171-
output = subprocess.check_output(port_cmd, cwd=self.filepath).decode("utf-8")
192+
try:
193+
output = subprocess.check_output(port_cmd, cwd=self.filepath).decode("utf-8")
194+
except subprocess.CalledProcessError as e:
195+
raise NoSuchPortExposed(str(e.stderr))
172196
result = str(output).rstrip().split(":")
173197
if len(result) != 2 or not all(result):
174198
raise NoSuchPortExposed(f"port {port} is not exposed for service {service}")

compose/tests/test_docker_compose.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def test_can_build_images_before_spawning_service_via_compose():
3434

3535
assert compose.build
3636
docker_compose_cmd = call_mock.call_args_list[0][1]["cmd"]
37-
assert "docker-compose" in docker_compose_cmd
37+
assert "docker-compose" in docker_compose_cmd or ("docker" in docker_compose_cmd and "compose" in docker_compose_cmd)
3838
assert "up" in docker_compose_cmd
3939
assert "--build" in docker_compose_cmd
4040

0 commit comments

Comments
 (0)