-
Notifications
You must be signed in to change notification settings - Fork 332
Closed
Description
Describe the bug
Resource (container, network, volume) remains when timeout occurs. This only happens using the "with" keyword. When exception is raised insideDockerCompose.__enter__
, it doesn't call DockerCompose.stop
.
To Reproduce
app
is a container that doesn't write any log, so timeout occurs.
def test_app():
compose = DockerCompose(".",
compose_file_name=["docker-compose.yml"],
pull=False,
build=True,)
compose.waiting_for({
"app": LogMessageWaitStrategy("App started").with_startup_timeout(5),
})
with compose:
assert 1 == 1
After running the test, we can see the container remains.
Here is the example.
((.venv) ) ➜ test-testcontainers-compose docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
((.venv) ) ➜ test-testcontainers-compose pytest
======================================================== test session starts =========================================================
platform darwin -- Python 3.12.11, pytest-8.4.2, pluggy-1.6.0
rootdir: /Users/franz/src/test_projects/test-testcontainers-compose
collected 1 item
test/test__app.py F [100%]
============================================================== FAILURES ==============================================================
______________________________________________________________ test_app ______________________________________________________________
def test_app():
compose = DockerCompose(".",
compose_file_name=["docker-compose.yml"],
pull=False,
build=True,)
compose.waiting_for({
"app": LogMessageWaitStrategy("App started").with_startup_timeout(5),
})
> with compose:
^^^^^^^
test/test__app.py:14:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.venv/lib/python3.12/site-packages/testcontainers/compose/compose.py:226: in __enter__
self.start()
.venv/lib/python3.12/site-packages/testcontainers/compose/compose.py:296: in start
strategy.wait_until_ready(container)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <testcontainers.core.wait_strategies.LogMessageWaitStrategy object at 0x10626e780>
container = ComposeContainer(ID='86c195d03369', Name='test-testcontainers-compose-app-1', Command='"tail -f /dev/null"', Project='test-testcontainers-compose', Service='app', State='running', Health='', ExitCode=0, Publishers=[])
def wait_until_ready(self, container: "WaitStrategyTarget") -> None:
"""
Wait until the specified message appears in the container logs.
Args:
container: The container to monitor
Raises:
TimeoutError: If the message doesn't appear within the timeout period
RuntimeError: If the container exits before the message appears
"""
from .waiting_utils import _NOT_EXITED_STATUSES, _get_container_logs_for_debugging, _get_container_status_info
# Implement our own wait logic to avoid recursive calls to wait_for_logs
wrapped = container.get_wrapped_container()
start_time = time.time()
while True:
duration = time.time() - start_time
if duration > self._startup_timeout:
# Get current logs and status for debugging
stdout_str, stderr_str = _get_container_logs_for_debugging(container)
status_info = _get_container_status_info(container)
message_pattern = self._message.pattern if hasattr(self._message, "pattern") else str(self._message)
> raise TimeoutError(
f"Container did not emit logs containing '{message_pattern}' within {self._startup_timeout:.3f} seconds. "
f"Container status: {status_info['status']}, health: {status_info['health_status']}. "
f"Recent stdout: {stdout_str}. "
f"Recent stderr: {stderr_str}. "
f"Hint: Check if the container is starting correctly, the expected message is being logged, "
f"and the log pattern matches what the application actually outputs."
)
E TimeoutError: Container did not emit logs containing 'App started' within 5.000 seconds. Container status: unknown, health: unknown. Recent stdout: . Recent stderr: . Hint: Check if the container is starting correctly, the expected message is being logged, and the log pattern matches what the application actually outputs.
.venv/lib/python3.12/site-packages/testcontainers/core/wait_strategies.py:122: TimeoutError
========================================================== warnings summary ==========================================================
.venv/lib/python3.12/site-packages/testcontainers/core/waiting_utils.py:178
/Users/franz/src/test_projects/test-testcontainers-compose/.venv/lib/python3.12/site-packages/testcontainers/core/waiting_utils.py:178: DeprecationWarning: The @wait_container_is_ready decorator is deprecated and will be removed in a future version. Use structured wait strategies instead: container.waiting_for(HttpWaitStrategy(8080).for_status_code(200)) or container.waiting_for(LogMessageWaitStrategy('ready'))
@wait_container_is_ready()
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
====================================================== short test summary info =======================================================
FAILED test/test__app.py::test_app - TimeoutError: Container did not emit logs containing 'App started' within 5.000 seconds. Container status: unknown, health: unkno...
==================================================== 1 failed, 1 warning in 7.56s ====================================================
((.venv) ) ➜ test-testcontainers-compose docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
86c195d03369 test-testcontainers-compose-app "tail -f /dev/null" 9 seconds ago Up 8 seconds test-testcontainers-compose-app-1
Runtime environment
Provide a summary of your runtime environment. Which operating system, python version, and docker version are you using? What is the version of testcontainers-python
you are using? You can run the following commands to get the relevant information.
((.venv) ) ➜ test-testcontainers-compose uname -a
Darwin MacBookAir 24.5.0 Darwin Kernel Version 24.5.0: Tue Apr 22 19:48:46 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T8103 arm64 arm Darwin
((.venv) ) ➜ test-testcontainers-compose python --version
Python 3.12.11
((.venv) ) ➜ test-testcontainers-compose docker info
Client:
Version: 28.3.3
Context: desktop-linux
Debug Mode: false
Plugins:
ai: Docker AI Agent - Ask Gordon (Docker Inc.)
Version: v1.9.11
Path: /Users/franz/.docker/cli-plugins/docker-ai
buildx: Docker Buildx (Docker Inc.)
Version: v0.27.0-desktop.1
Path: /Users/franz/.docker/cli-plugins/docker-buildx
cloud: Docker Cloud (Docker Inc.)
Version: v0.4.21
Path: /Users/franz/.docker/cli-plugins/docker-cloud
compose: Docker Compose (Docker Inc.)
Version: v2.39.2-desktop.1
Path: /Users/franz/.docker/cli-plugins/docker-compose
debug: Get a shell into any image or container (Docker Inc.)
Version: 0.0.42
Path: /Users/franz/.docker/cli-plugins/docker-debug
desktop: Docker Desktop commands (Docker Inc.)
Version: v0.2.0
Path: /Users/franz/.docker/cli-plugins/docker-desktop
extension: Manages Docker extensions (Docker Inc.)
Version: v0.2.31
Path: /Users/franz/.docker/cli-plugins/docker-extension
init: Creates Docker-related starter files for your project (Docker Inc.)
Version: v1.4.0
Path: /Users/franz/.docker/cli-plugins/docker-init
mcp: Docker MCP Plugin (Docker Inc.)
Version: v0.15.0
Path: /Users/franz/.docker/cli-plugins/docker-mcp
model: Docker Model Runner (EXPERIMENTAL) (Docker Inc.)
Version: v0.1.39
Path: /Users/franz/.docker/cli-plugins/docker-model
sbom: View the packaged-based Software Bill Of Materials (SBOM) for an image (Anchore Inc.)
Version: 0.6.0
Path: /Users/franz/.docker/cli-plugins/docker-sbom
scout: Docker Scout (Docker Inc.)
Version: v1.18.3
Path: /Users/franz/.docker/cli-plugins/docker-scout
WARNING: Plugin "/Users/franz/.docker/cli-plugins/docker-dev" is not valid: failed to fetch metadata: fork/exec /Users/franz/.docker/cli-plugins/docker-dev: no such file or directory
WARNING: Plugin "/Users/franz/.docker/cli-plugins/docker-feedback" is not valid: failed to fetch metadata: fork/exec /Users/franz/.docker/cli-plugins/docker-feedback: no such file or directory
Server:
Containers: 1
Running: 1
Paused: 0
Stopped: 0
Images: 66
Server Version: 28.3.3
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
CDI spec directories:
/etc/cdi
/var/run/cdi
Discovered Devices:
cdi: docker.com/gpu=webgpu
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 05044ec0a9a75232cad458027ca83437aae3f4da
runc version: v1.2.5-0-g59923ef
init version: de40ad0
Security Options:
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.10.14-linuxkit
Operating System: Docker Desktop
OSType: linux
Architecture: aarch64
CPUs: 8
Total Memory: 7.751GiB
Name: docker-desktop
ID: 2c1b74ff-4b37-4cfe-acce-e58d8c8dc84f
Docker Root Dir: /var/lib/docker
Debug Mode: false
HTTP Proxy: http.docker.internal:3128
HTTPS Proxy: http.docker.internal:3128
No Proxy: hubproxy.docker.internal
Labels:
com.docker.desktop.address=unix:///Users/franz/Library/Containers/com.docker.docker/Data/docker-cli.sock
Experimental: false
Insecure Registries:
hubproxy.docker.internal:5555
::1/128
127.0.0.0/8
Live Restore Enabled: false
((.venv) ) ➜ test-testcontainers-compose pip freeze
certifi==2025.8.3
charset-normalizer==3.4.3
docker==7.1.0
idna==3.10
iniconfig==2.1.0
packaging==25.0
pluggy==1.6.0
Pygments==2.19.2
pytest==8.4.2
python-dotenv==1.1.1
requests==2.32.5
testcontainers==4.13.0
typing_extensions==4.15.0
urllib3==2.5.0
wrapt==1.17.3
Metadata
Metadata
Assignees
Labels
No labels