Container is not running with host network
nandamller opened this issue · 2 comments
Hi, I am trying to use your library. However, I can't get it to work with containers on network = 'host'
Here is my minimalist test.py:
import pytest
import os
from http.client import HTTPConnection
from pytest_docker_tools import build, container
app_image = build(path=os.path.join(os.path.dirname(__file__), 'app'),)
app = container(image='{app_image.id}', network='host')
def test_app(app):
assert app.status == 'running'
@pytest.fixture
def app_connection(app):
return HTTPConnection('127.0.0.1:8080')
def test_app_connection(app_connection):
app_connection.request('GET', '/')
response = app_connection.getresponse()
assert response.status == 200
My minimalist app.py:
import logging
from flask import Flask
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
app = Flask(__name__)
@app.route("/", methods=['GET'])
def main():
logger.info(f"\nIt's here!\n")
return 'ok'
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080, debug=True)
My Dockerfile:
FROM python:3.8.12-bullseye
COPY . ./python
WORKDIR python
RUN pip install -r requirements.txt
CMD ["python3", "app.py" ]
The requirements.txt
Flask==2.0.2
Versions:
Python 3.9.7, pytest-7.1.2, pluggy-1.0.0
plugins: docker-tools-3.1.3, docker-0.12.0
And this is the error I'm getting:
___________________________________________________ ERROR at setup of test_app ____________________________________________________
request = <SubRequest 'app' for <Function test_app>>, docker_client = <docker.client.DockerClient object at 0x7ff643dbd2b0>
wrapper_class = <class 'pytest_docker_tools.wrappers.container.Container'>
kwargs = {'detach': True, 'image': 'sha256:dc01bb5db190457b853253c7e117799f4190a133e4f30ba3136398ca377e2540', 'labels': {'creat...pytest-docker-tools.signature': 'f2725c8390dd6369525756e85c5595fd6eec803dc9867a90aaf8174c435bac96'}, 'network': 'host'}
signature = 'f2725c8390dd6369525756e85c5595fd6eec803dc9867a90aaf8174c435bac96', timeout = 30
container = <pytest_docker_tools.wrappers.container.Container object at 0x7ff643dbd850>
@fixture_factory()
def container(request, docker_client, wrapper_class, **kwargs):
""" Docker container: image={image} """
wrapper_class = wrapper_class or Container
kwargs.update({"detach": True})
set_reusable_labels(kwargs, request)
signature = hash_params(kwargs)
set_signature(kwargs, signature)
if request.config.option.reuse_containers:
if "name" not in kwargs.keys():
pytest.fail(
"Tried to use '--reuse-containers' command line argument without "
"setting 'name' attribute on container"
)
name = kwargs["name"]
try:
current = docker_client.containers.get(name)
except NotFound:
pass
else:
# Found a container with the right name, but it doesn't have pytest-docker-tools labels
# We shouldn't just clobber it, its not ours. Bail out.
if not is_reusable_container(current):
pytest.fail(
f"Tried to reuse {name} but it does not appear to be a reusable container"
)
# It's ours, and its not stale. Reuse it!
if check_signature(current.labels, signature):
return wrapper_class(current)
# It's ours and it is stale. Clobber it.
print(f"Removing stale reusable container: {name}")
current.remove(force=True)
timeout = kwargs.pop("timeout", 30)
raw_container = docker_client.containers.run(**kwargs)
if not request.config.option.reuse_containers:
request.addfinalizer(
lambda: raw_container.remove(force=True) and raw_container.wait(timeout=10)
)
container = wrapper_class(raw_container)
try:
> wait_for_callable("Waiting for container to be ready", container.ready, timeout)
../.local/lib/python3.9/site-packages/pytest_docker_tools/factories/container.py:69:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
message = 'Waiting for container to be ready'
func = <bound method Container.ready of <pytest_docker_tools.wrappers.container.Container object at 0x7ff643dbd850>>, timeout = 30
def wait_for_callable(message: str, func: Callable, timeout: int = 30) -> None:
"""
Runs a callable once a second until it returns True or we hit the timeout.
"""
sys.stdout.write(message)
try:
for i in range(timeout):
sys.stdout.write(".")
sys.stdout.flush()
if func():
return
time.sleep(1)
finally:
sys.stdout.write("\n")
> raise TimeoutError(f"Timeout of {timeout}s exceeded")
E pytest_docker_tools.exceptions.TimeoutError: Timeout of 30s exceeded
../.local/lib/python3.9/site-packages/pytest_docker_tools/utils.py:37: TimeoutError
During handling of the above exception, another exception occurred:
request = <SubRequest 'app' for <Function test_app>>, docker_client = <docker.client.DockerClient object at 0x7ff643dbd2b0>
wrapper_class = <class 'pytest_docker_tools.wrappers.container.Container'>
kwargs = {'detach': True, 'image': 'sha256:dc01bb5db190457b853253c7e117799f4190a133e4f30ba3136398ca377e2540', 'labels': {'creat...pytest-docker-tools.signature': 'f2725c8390dd6369525756e85c5595fd6eec803dc9867a90aaf8174c435bac96'}, 'network': 'host'}
signature = 'f2725c8390dd6369525756e85c5595fd6eec803dc9867a90aaf8174c435bac96', timeout = 30
container = <pytest_docker_tools.wrappers.container.Container object at 0x7ff643dbd850>
@fixture_factory()
def container(request, docker_client, wrapper_class, **kwargs):
""" Docker container: image={image} """
wrapper_class = wrapper_class or Container
kwargs.update({"detach": True})
set_reusable_labels(kwargs, request)
signature = hash_params(kwargs)
set_signature(kwargs, signature)
if request.config.option.reuse_containers:
if "name" not in kwargs.keys():
pytest.fail(
"Tried to use '--reuse-containers' command line argument without "
"setting 'name' attribute on container"
)
name = kwargs["name"]
try:
current = docker_client.containers.get(name)
except NotFound:
pass
else:
# Found a container with the right name, but it doesn't have pytest-docker-tools labels
# We shouldn't just clobber it, its not ours. Bail out.
if not is_reusable_container(current):
pytest.fail(
f"Tried to reuse {name} but it does not appear to be a reusable container"
)
# It's ours, and its not stale. Reuse it!
if check_signature(current.labels, signature):
return wrapper_class(current)
# It's ours and it is stale. Clobber it.
print(f"Removing stale reusable container: {name}")
current.remove(force=True)
timeout = kwargs.pop("timeout", 30)
raw_container = docker_client.containers.run(**kwargs)
if not request.config.option.reuse_containers:
request.addfinalizer(
lambda: raw_container.remove(force=True) and raw_container.wait(timeout=10)
)
container = wrapper_class(raw_container)
try:
wait_for_callable("Waiting for container to be ready", container.ready, timeout)
except TimeoutError:
> raise ContainerNotReady(
container, "Timeout while waiting for container to be ready"
)
E pytest_docker_tools.exceptions.ContainerNotReady: Timeout while waiting for container to be ready
../.local/lib/python3.9/site-packages/pytest_docker_tools/factories/container.py:71: ContainerNotReady
------------------------------------------------------ Captured stdout setup ------------------------------------------------------
Building /home/fernanda/conectionTest/app.....................
Waiting for container to be ready..............................
------------------------------------------------------- nostalgic_goldberg --------------------------------------------------------
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
INFO:werkzeug: * Running on all addresses (0.0.0.0)
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://127.0.0.1:8080
* Running on http://192.168.2.109:8080 (Press CTRL+C to quit)
INFO:werkzeug: * Restarting with stat
WARNING:werkzeug: * Debugger is active!
INFO:werkzeug: * Debugger PIN: 982-840-186
______________________________________________ ERROR at setup of test_app_connection ______________________________________________
request = <SubRequest 'app' for <Function test_app_connection>>
docker_client = <docker.client.DockerClient object at 0x7ff643dbd2b0>
wrapper_class = <class 'pytest_docker_tools.wrappers.container.Container'>
kwargs = {'detach': True, 'image': 'sha256:dc01bb5db190457b853253c7e117799f4190a133e4f30ba3136398ca377e2540', 'labels': {'creat...pytest-docker-tools.signature': 'f2725c8390dd6369525756e85c5595fd6eec803dc9867a90aaf8174c435bac96'}, 'network': 'host'}
signature = 'f2725c8390dd6369525756e85c5595fd6eec803dc9867a90aaf8174c435bac96', timeout = 30
container = <pytest_docker_tools.wrappers.container.Container object at 0x7ff643d71970>
@fixture_factory()
def container(request, docker_client, wrapper_class, **kwargs):
""" Docker container: image={image} """
wrapper_class = wrapper_class or Container
kwargs.update({"detach": True})
set_reusable_labels(kwargs, request)
signature = hash_params(kwargs)
set_signature(kwargs, signature)
if request.config.option.reuse_containers:
if "name" not in kwargs.keys():
pytest.fail(
"Tried to use '--reuse-containers' command line argument without "
"setting 'name' attribute on container"
)
name = kwargs["name"]
try:
current = docker_client.containers.get(name)
except NotFound:
pass
else:
# Found a container with the right name, but it doesn't have pytest-docker-tools labels
# We shouldn't just clobber it, its not ours. Bail out.
if not is_reusable_container(current):
pytest.fail(
f"Tried to reuse {name} but it does not appear to be a reusable container"
)
# It's ours, and its not stale. Reuse it!
if check_signature(current.labels, signature):
return wrapper_class(current)
# It's ours and it is stale. Clobber it.
print(f"Removing stale reusable container: {name}")
current.remove(force=True)
timeout = kwargs.pop("timeout", 30)
raw_container = docker_client.containers.run(**kwargs)
if not request.config.option.reuse_containers:
request.addfinalizer(
lambda: raw_container.remove(force=True) and raw_container.wait(timeout=10)
)
container = wrapper_class(raw_container)
try:
> wait_for_callable("Waiting for container to be ready", container.ready, timeout)
../.local/lib/python3.9/site-packages/pytest_docker_tools/factories/container.py:69:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
message = 'Waiting for container to be ready'
func = <bound method Container.ready of <pytest_docker_tools.wrappers.container.Container object at 0x7ff643d71970>>, timeout = 30
def wait_for_callable(message: str, func: Callable, timeout: int = 30) -> None:
"""
Runs a callable once a second until it returns True or we hit the timeout.
"""
sys.stdout.write(message)
try:
for i in range(timeout):
sys.stdout.write(".")
sys.stdout.flush()
if func():
return
time.sleep(1)
finally:
sys.stdout.write("\n")
> raise TimeoutError(f"Timeout of {timeout}s exceeded")
E pytest_docker_tools.exceptions.TimeoutError: Timeout of 30s exceeded
../.local/lib/python3.9/site-packages/pytest_docker_tools/utils.py:37: TimeoutError
During handling of the above exception, another exception occurred:
request = <SubRequest 'app' for <Function test_app_connection>>
docker_client = <docker.client.DockerClient object at 0x7ff643dbd2b0>
wrapper_class = <class 'pytest_docker_tools.wrappers.container.Container'>
kwargs = {'detach': True, 'image': 'sha256:dc01bb5db190457b853253c7e117799f4190a133e4f30ba3136398ca377e2540', 'labels': {'creat...pytest-docker-tools.signature': 'f2725c8390dd6369525756e85c5595fd6eec803dc9867a90aaf8174c435bac96'}, 'network': 'host'}
signature = 'f2725c8390dd6369525756e85c5595fd6eec803dc9867a90aaf8174c435bac96', timeout = 30
container = <pytest_docker_tools.wrappers.container.Container object at 0x7ff643d71970>
@fixture_factory()
def container(request, docker_client, wrapper_class, **kwargs):
""" Docker container: image={image} """
wrapper_class = wrapper_class or Container
kwargs.update({"detach": True})
set_reusable_labels(kwargs, request)
signature = hash_params(kwargs)
set_signature(kwargs, signature)
if request.config.option.reuse_containers:
if "name" not in kwargs.keys():
pytest.fail(
"Tried to use '--reuse-containers' command line argument without "
"setting 'name' attribute on container"
)
name = kwargs["name"]
try:
current = docker_client.containers.get(name)
except NotFound:
pass
else:
# Found a container with the right name, but it doesn't have pytest-docker-tools labels
# We shouldn't just clobber it, its not ours. Bail out.
if not is_reusable_container(current):
pytest.fail(
f"Tried to reuse {name} but it does not appear to be a reusable container"
)
# It's ours, and its not stale. Reuse it!
if check_signature(current.labels, signature):
return wrapper_class(current)
# It's ours and it is stale. Clobber it.
print(f"Removing stale reusable container: {name}")
current.remove(force=True)
timeout = kwargs.pop("timeout", 30)
raw_container = docker_client.containers.run(**kwargs)
if not request.config.option.reuse_containers:
request.addfinalizer(
lambda: raw_container.remove(force=True) and raw_container.wait(timeout=10)
)
container = wrapper_class(raw_container)
try:
wait_for_callable("Waiting for container to be ready", container.ready, timeout)
except TimeoutError:
> raise ContainerNotReady(
container, "Timeout while waiting for container to be ready"
)
E pytest_docker_tools.exceptions.ContainerNotReady: Timeout while waiting for container to be ready
../.local/lib/python3.9/site-packages/pytest_docker_tools/factories/container.py:71: ContainerNotReady
------------------------------------------------------ Captured stdout setup ------------------------------------------------------
Waiting for container to be ready..............................
---------------------------------------------------------- angry_volhard ----------------------------------------------------------
* Serving Flask app 'app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
INFO:werkzeug: * Running on all addresses (0.0.0.0)
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://127.0.0.1:8080
* Running on http://192.168.2.109:8080 (Press CTRL+C to quit)
INFO:werkzeug: * Restarting with stat
WARNING:werkzeug: * Debugger is active!
INFO:werkzeug: * Debugger PIN: 982-840-186
===================================================== short test summary info =====================================================
ERROR test.py::test_app - pytest_docker_tools.exceptions.ContainerNotReady: Timeout while waiting for container to be ready
ERROR test.py::test_app_connection - pytest_docker_tools.exceptions.ContainerNotReady: Timeout while waiting for container to be...
What am I doing wrong?
AFAIK running containers in host network mode currently is not supported. I was trying to do the same a couple of months ago. I ened up starting to hack the plugin to integrate proper support. However this wasn`t strait forward, because other issues showed up on the way that needed to be addressed as well. In the end I was able to continue without using host networking
Have you tried using network_mode="host"
instead of network="host"
?
Note that I only use this with docker networks myself (so i can use pytest-xdist safely), so you are kinda on your own here.