-
Couldn't load subscription status.
- Fork 344
Description
Describe the bug
DockerClient.run() errors out on systems where the auto-detected network returns subnets with the host bit set.
Turns out, in DockerClient.find_host_network() each identified subnet is validated by instantiating ipaddress.IPv4Network. By default, this follows a strict validation and if that fails, raises ValueError. However, in DockerClient.find_host_network() is only checked for ipaddress.AddressValueError and ValueError is not handled.
Workaroud
After hot-patching DockerClient.find_host_network() to also ignore ValueError, everything works find (on my machine).
To Reproduce
- system with a docker environment where at least one subnet contains an address with the host bit set
- instantiate and launch a Docker container with Testcontainers
- error:
@pytest.fixture(scope="session")
def db_container() -> Generator[PostgresContainer]:
> with PostgresContainer("postgres:16-alpine", driver="asyncpg") as postgres:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/[snip]/tests/conftest.py:25:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/[snip]/.venv/lib/python3.13/site-packages/testcontainers/core/container.py:216: in __enter__
return self.start()
^^^^^^^^^^^^
/[snip]/.venv/lib/python3.13/site-packages/testcontainers/core/generic.py:77: in start
super().start()
/[snip]/.venv/lib/python3.13/site-packages/testcontainers/core/container.py:192: in start
self._container = docker_client.run(
/[snip]/.venv/lib/python3.13/site-packages/testcontainers/core/docker_client.py:47: in wrapper
return function(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^
/[snip]/.venv/lib/python3.13/site-packages/testcontainers/core/docker_client.py:100: in run
host_network = self.find_host_network()
^^^^^^^^^^^^^^^^^^^^^^^^
/[snip]/.venv/lib/python3.13/site-packages/testcontainers/core/docker_client.py:155: in find_host_network
subnet = ipaddress.IPv4Network(config["Subnet"])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = IPv4Network('172.18.251.1/25'), address = '172.18.251.1/25'
strict = True
def __init__(self, address, strict=True):
"""Instantiate a new IPv4 network object.
Args:
address: A string or integer representing the IP [& network].
'192.0.2.0/24'
'192.0.2.0/255.255.255.0'
'192.0.2.0/0.0.0.255'
are all functionally the same in IPv4. Similarly,
'192.0.2.1'
'192.0.2.1/255.255.255.255'
'192.0.2.1/32'
are also functionally equivalent. That is to say, failing to
provide a subnetmask will create an object with a mask of /32.
If the mask (portion after the / in the argument) is given in
dotted quad form, it is treated as a netmask if it starts with a
non-zero field (e.g. /255.0.0.0 == /8) and as a hostmask if it
starts with a zero field (e.g. 0.255.255.255 == /8), with the
single exception of an all-zero mask which is treated as a
netmask == /0. If no mask is given, a default of /32 is used.
Additionally, an integer can be passed, so
IPv4Network('192.0.2.1') == IPv4Network(3221225985)
or, more generally
IPv4Interface(int(IPv4Interface('192.0.2.1'))) ==
IPv4Interface('192.0.2.1')
Raises:
AddressValueError: If ipaddress isn't a valid IPv4 address.
NetmaskValueError: If the netmask isn't valid for
an IPv4 address.
ValueError: If strict is True and a network address is not
supplied.
"""
addr, mask = self._split_addr_prefix(address)
self.network_address = IPv4Address(addr)
self.netmask, self._prefixlen = self._make_netmask(mask)
packed = int(self.network_address)
if packed & int(self.netmask) != packed:
if strict:
> raise ValueError('%s has host bits set' % self)
E ValueError: 172.18.251.1/25 has host bits set
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.
# Get the operating system information (on a unix os).
$ uname -a
Linux basestation-kubuntu 6.8.0-85-generic #85-Ubuntu SMP PREEMPT_DYNAMIC Thu Sep 18 15:26:59 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
# Get the python version.
$ python --version
Python 3.13.2
# Get the docker version and other docker information.
$ docker info
Client: Docker Engine - Community
Version: 28.5.0
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.29.1
Path: /usr/local/lib/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.40.0
Path: /usr/local/lib/docker/cli-plugins/docker-compose
Server:
Containers: 4
Running: 1
Paused: 0
Stopped: 3
Images: 40
Server Version: 28.5.0
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: systemd
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
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: b98a3aace656320842a23f4a392a33f46af97866
runc version: v1.3.0-0-g4ca628d1
init version: de40ad0
Security Options:
apparmor
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.8.0-85-generic
Operating System: Ubuntu 24.04.3 LTS
OSType: linux
Architecture: x86_64
CPUs: 16
Total Memory: 62.72GiB
Name: basestation-kubuntu
ID: c9b21f46-3e1f-4b8a-a957-546116146beb
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
::1/128
127.0.0.0/8
Live Restore Enabled: false
# Get all python packages.
$ pip freeze
aiosqlite==0.21.0
alembic==1.17.0
altair==5.5.0
annotated-types==0.7.0
anyio==4.11.0
argcomplete==3.6.2
argon2-cffi==25.1.0
argon2-cffi-bindings==25.1.0
arrow==1.3.0
asttokens==3.0.0
async-lru==2.0.5
asyncpg==0.30.0
attrs==25.4.0
babel==2.17.0
beautifulsoup4==4.14.2
bleach==6.2.0
blinker==1.9.0
certifi==2025.10.5
cffi==2.0.0
cfgv==3.4.0
charset-normalizer==3.4.4
click==8.3.0
colorama==0.4.6
comm==0.2.3
commitizen==4.9.1
contourpy==1.3.3
coverage==7.11.0
cycler==0.12.1
dash==3.2.0
dash-bootstrap-components==2.0.4
debugpy==1.8.17
decli==0.6.3
decorator==5.2.1
defusedxml==0.7.1
deprecated==1.2.18
distlib==0.4.0
docker==7.1.0
executing==2.2.1
fastapi==0.119.0
fastjsonschema==2.21.2
filelock==3.20.0
flask==3.1.2
fonttools==4.60.1
fqdn==1.5.1
greenlet==3.2.4
gunicorn==23.0.0
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
identify==2.6.15
idna==3.11
importlib-metadata==8.7.0
iniconfig==2.1.0
ipykernel==7.0.1
ipython==9.6.0
ipython-pygments-lexers==1.1.1
isoduration==20.11.0
itsdangerous==2.2.0
jedi==0.19.2
jinja2==3.1.6
json5==0.12.1
jsonpointer==3.0.0
jsonschema==4.25.1
jsonschema-specifications==2025.9.1
jupyter-client==8.6.3
jupyter-core==5.8.1
jupyter-events==0.12.0
jupyter-lsp==2.3.0
jupyter-server==2.17.0
jupyter-server-terminals==0.5.3
jupyterlab==4.4.9
jupyterlab-pygments==0.3.0
jupyterlab-server==2.27.3
kiwisolver==1.4.9
lark==1.3.0
mako==1.3.10
markupsafe==3.0.3
matplotlib==3.10.7
matplotlib-inline==0.1.7
mistune==3.1.4
narwhals==2.8.0
nbclient==0.10.2
nbconvert==7.16.6
nbformat==5.10.4
nest-asyncio==1.6.0
nodeenv==1.9.1
notebook==7.4.7
notebook-shim==0.2.4
numpy==2.3.3
packaging==25.0
pandas==2.3.3
pandocfilters==1.5.1
parso==0.8.5
pexpect==4.9.0
pillow==11.3.0
platformdirs==4.5.0
plotly==6.3.1
pluggy==1.6.0
polars==1.34.0
polars-runtime-32==1.34.0
pre-commit==4.3.0
prometheus-client==0.23.1
prompt-toolkit==3.0.51
psutil==7.1.0
psycopg2-binary==2.9.11
ptyprocess==0.7.0
pure-eval==0.2.3
pycparser==2.23
pydantic==2.12.2
pydantic-core==2.41.4
pydantic-settings==2.11.0
pygments==2.19.2
pyparsing==3.2.5
pytest==8.4.2
pytest-asyncio==0.21.2
pytest-cov==7.0.0
python-dateutil==2.9.0.post0
python-dotenv==1.1.1
python-json-logger==4.0.0
python-multipart==0.0.20
pytz==2025.2
pyyaml==6.0.3
pyzmq==27.1.0
questionary==2.1.1
referencing==0.37.0
requests==2.32.5
retrying==1.4.2
rfc3339-validator==0.1.4
rfc3986-validator==0.1.1
rfc3987-syntax==1.1.0
rpds-py==0.27.1
ruff==0.14.0
seaborn==0.13.2
send2trash==1.8.3
setuptools==80.9.0
six==1.17.0
sniffio==1.3.1
soupsieve==2.8
sqlalchemy==2.0.44
sqlmodel==0.0.27
stack-data==0.6.3
starlette==0.48.0
termcolor==3.1.0
terminado==0.18.1
testcontainers==4.13.2
tinycss2==1.4.0
tomlkit==0.13.3
tornado==6.5.2
tqdm==4.67.1
traitlets==5.14.3
types-python-dateutil==2.9.0.20251008
typing-extensions==4.15.0
typing-inspection==0.4.2
tzdata==2025.2
uri-template==1.3.0
urllib3==2.5.0
uvicorn==0.37.0
virtualenv==20.35.3
wcwidth==0.2.14
webcolors==24.11.1
webencodings==0.5.1
websocket-client==1.9.0
werkzeug==3.1.3
wrapt==1.17.3
zipp==3.23.0