Skip to content

Commit 932ee30

Browse files
authored
feat(core): Support working with env files (#737)
Fix: #687 Users should not be required to load each env var manually if they have an env file. Added support for loading a dot-env file. Usage: ```python with DockerContainer("nginx:latest").with_env_file("my_env_file"): # We now have a container with the relevant env vars from the file ``` This is an implementation of ```docker run --env-file <file> ...```
1 parent f1d8d35 commit 932ee30

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed

core/testcontainers/core/container.py

+8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import contextlib
2+
from os import PathLike
23
from socket import socket
34
from typing import TYPE_CHECKING, Optional, Union
45

56
import docker.errors
67
from docker import version
78
from docker.types import EndpointConfig
9+
from dotenv import dotenv_values
810
from typing_extensions import Self, assert_never
911

1012
from testcontainers.core.config import ConnectionMode
@@ -57,6 +59,12 @@ def with_env(self, key: str, value: str) -> Self:
5759
self.env[key] = value
5860
return self
5961

62+
def with_env_file(self, env_file: Union[str, PathLike]) -> Self:
63+
env_values = dotenv_values(env_file)
64+
for key, value in env_values.items():
65+
self.with_env(key, value)
66+
return self
67+
6068
def with_bind_ports(self, container: int, host: Optional[int] = None) -> Self:
6169
self.ports[container] = host
6270
return self

core/tests/test_core.py

+29
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import tempfile
2+
from pathlib import Path
3+
14
from testcontainers.core.container import DockerContainer
25

36

@@ -17,3 +20,29 @@ def test_get_logs():
1720
assert isinstance(stdout, bytes)
1821
assert isinstance(stderr, bytes)
1922
assert "Hello from Docker".encode() in stdout, "There should be something on stdout"
23+
24+
25+
def test_docker_container_with_env_file():
26+
"""Test that environment variables can be loaded from a file"""
27+
with tempfile.TemporaryDirectory() as temp_directory:
28+
env_file_path = Path(temp_directory) / "env_file"
29+
with open(env_file_path, "w") as f:
30+
f.write(
31+
"""
32+
TEST_ENV_VAR=hello
33+
NUMBER=123
34+
DOMAIN=example.org
35+
ADMIN_EMAIL=admin@${DOMAIN}
36+
ROOT_URL=${DOMAIN}/app
37+
"""
38+
)
39+
container = DockerContainer("alpine").with_command("tail -f /dev/null") # Keep the container running
40+
container.with_env_file(env_file_path) # Load the environment variables from the file
41+
with container:
42+
output = container.exec("env").output.decode("utf-8").strip()
43+
assert "TEST_ENV_VAR=hello" in output
44+
assert "NUMBER=123" in output
45+
assert "DOMAIN=example.org" in output
46+
assert "[email protected]" in output
47+
assert "ROOT_URL=example.org/app" in output
48+
print(output)

poetry.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ docker = "*" # ">=4.0"
8383
urllib3 = "*" # "<2.0"
8484
wrapt = "*" # "^1.16.0"
8585
typing-extensions = "*"
86+
python-dotenv = "*"
8687

8788
# community modules
8889
python-arango = { version = "^7.8", optional = true }

0 commit comments

Comments
 (0)