Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testcontainers fails to get container_host_ip when running in docker network #141

Closed
andredasilvapinto opened this issue Apr 29, 2021 · 5 comments · Fixed by #368
Closed

Comments

@andredasilvapinto
Copy link

I believe this is because this code assumes the presence of "bridge"

https://github.com/testcontainers/testcontainers-python/blob/master/testcontainers/core/docker_client.py#L52

https://github.com/testcontainers/testcontainers-python/blob/master/testcontainers/core/docker_client.py#L48

which is not the case when the container runs in a specific docker network (possible to do via DockerContainer.with_kwargs)

@dcc-sapienza
Copy link

dcc-sapienza commented May 7, 2021

Hi, I have the same issue when trying to run an integration test inside a docker container.
As described in the README, when testcontainers-py is running inside a docker container a docker client is required and the sock must be mounted as volume (with -v /var/run/docker.sock:/var/run/docker.sock)
Anyway, when the tests are running they fails because of:

def gateway_ip(self, container_id):
        container = self.client.api.containers(filters={'id': container_id})[0]
>       return container['NetworkSettings']['Networks']['bridge']['Gateway']
E       KeyError: 'bridge'

/root/.cache/pypoetry/virtualenvs/deros-FCD_2FXt-py3.8/lib/python3.8/site-packages/testcontainers/core/docker_client.py:52: KeyError

PS: the testcontainers java implementation work within docker container with the same configuration.

@hungphamvn
Copy link

Hello, I'm trying to run integration test inside .devcontainer (with docker-compose) and got the same error with @dlmiddlecote
Any workaround or solution so far?
Thanks.

dee42 added a commit to dee42/testcontainers-python that referenced this issue Jul 5, 2023
deeninetyone pushed a commit to deeninetyone/testcontainers-python that referenced this issue Jul 6, 2023
@dhutchison
Copy link

Sharing this test as an as the workaround I've taken to getting testcontainers working from within our devcontainer (noting we originally had DOCKER_HOST set too, which needed changed as it causes a code path to be ignored). Maybe it will help someone else, or point to what I'm doing wrong.

from testcontainers.postgres import PostgresContainer
import logging
import sqlalchemy
import os

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setLevel(logging.INFO)
logger.addHandler(handler)

def test_container_runs():

    postgres_container = PostgresContainer("postgres:14.6")

    # If we are running in a container, we need to set an environment variable to allow test
    # containers to work, this might only be required in the devcontainer - might need to 
    # validate that, for now we'll assume it is only in the dev container by looking for
    # our marker file
    # The first check is from how testcontainers determines if we are in a container, 
    # the second is our own check to a file that we know is contained in our devcontainer

    # Reference links:
    # https://github.com/testcontainers/testcontainers-python/blob/main/core/testcontainers/core/utils.py#L47
    # https://github.com/docker/docker/blob/a9fa38b1edf30b23cae3eade0be48b3d4b1de14b/daemon/initlayer/setup_unix.go#L25
    if os.path.exists('/.dockerenv') and os.path.exists('/installation-scripts/versions.properties'):
        logger.info("In DevContainer workaround...")
        gateway_ip = postgres_container.get_docker_client().gateway_ip(os.environ["HOSTNAME"])
        logger.info("Setting TC_HOST to gateway ip: " + gateway_ip)
        os.environ["TC_HOST"] = gateway_ip

    with postgres_container as postgres:
        engine = sqlalchemy.create_engine(postgres.get_connection_url())
        with engine.begin() as connection:
            result = connection.execute(sqlalchemy.text("select version()"))
            version, = result.fetchone()

            logger.info("Version is " + version)

I'm not quite sure if there is a bug or if I'm doing something wrong (our devcontainer should be setup as DIND, but is actually docker-from-docker which causes all manner of fun issues).

The key point in this is we have some code that detects if it is running in our devcontainer, and if so sets the TC_HOST environment variable to the gateway IP for the docker network that the devcontainer is running in. With this set testcontainers will correctly determine that the postgres container has started.

@alexanderankin
Copy link
Member

the original links in the issue were from these two methods respectively

from

def get_container(self, container_id):
containers = self.client.api.containers(filters={'id': container_id})
if not containers:
raise RuntimeError(f'could not get container with id {container_id}')
return containers[0]

and

return port_mappings[0]["HostPort"]

from

def port(self, container_id, port):
port_mappings = self.client.api.port(container_id, port)
if not port_mappings:
raise RuntimeError(f'port mapping for container {container_id} and port {port} is not '
'available')
return port_mappings[0]["HostPort"]

@ivanychev
Copy link

Faced the same issue in the tests. The working workaround for me is to patch the current implementation of this method (pytest example)

def gateway_ip(self, container_id):
    """Default DockerClient.gateway_ip doesn't know how to work with Docker networks, so
    this is the workaround.
    
    Fix as soon as the https://github.com/testcontainers/testcontainers-python/issues/141 is fixed.
    """
    container = self.get_container(container_id)
    networks = container['NetworkSettings']['Networks']
    if 'bridge' in networks:
        return container['NetworkSettings']['Networks']['bridge']['Gateway']
    if len(networks) == 1:
        return list(networks.values())[0]['Gateway']
    raise ValueError(container['NetworkSettings']['Networks'])


@pytest.fixture()
def container_network(monkeypatch) -> Iterable[Network]:
    monkeypatch.setattr(
        DockerClient,
        'gateway_ip',
        gateway_ip,
    )

    client = docker.from_env()
    network_name = f'test_{uuid.uuid4().hex}'
    network = client.networks.create(network_name)
    yield network
    network.remove()

totallyzen added a commit that referenced this issue Mar 20, 2024
Fix #141 - find IP from custom network if the container is not using the
default network
Close #329 - This seems fixed in the underlying docker libraries.
Improve support for Docker in Docker running on a custom network, by
attempting to find the right custom network and use it for new
containers. This adds support for using testcontainers-python running
the GitHub Actions Runner Controller to run self-hosted actions runners
on prem, when you run your workflows in containers.

---------

Co-authored-by: Dee Moore <dee42moore@gmail.com>
Co-authored-by: David Ankin <daveankin@gmail.com>
Co-authored-by: Balint Bartha <39852431+totallyzen@users.noreply.github.com>
alexanderankin pushed a commit that referenced this issue Mar 24, 2024
🤖 I have created a release *beep* *boop*
---


##
[4.2.0](testcontainers-v4.1.0...testcontainers-v4.2.0)
(2024-03-24)


### Features

* support influxdb
([#413](#413))
([13742a5](13742a5))


### Bug Fixes

* **arangodb:** tests to pass on ARM CPUs - change default image to
3.11.x where ARM image is published
([#479](#479))
([7b58a50](7b58a50))
* **core:** DinD issues
[#141](#141),
[#329](#329)
([#368](#368))
([b10d916](b10d916))
* **core:** raise an exception when docker compose fails to start
[#258](#258)
([#485](#485))
([d61af38](d61af38))
* **core:** use auto_remove=True with reaper instance
([#499](#499))
([274a400](274a400))
* **docs:** update the non-existent main.yml badge
([#493](#493))
([1d10c1c](1d10c1c))
* Fix the return type of `DockerContainer.get_logs`
([#487](#487))
([cd72f68](cd72f68))
* **keycloak:** tests on aarch64, use image from [jboss -&gt; quay],
change supported version [16+ -> 18+]
([#480](#480))
([5758310](5758310))
* **postgres:** doctest
([#473](#473))
([c9c6f92](c9c6f92))
* read the docs build works again
([#496](#496))
([dfd1781](dfd1781))
* readthedocs build - take 1
([#495](#495))
([b3b9901](b3b9901))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
bearrito pushed a commit to bearrito/testcontainers-python that referenced this issue Mar 30, 2024
…ntainers#368)

Fix testcontainers#141 - find IP from custom network if the container is not using the
default network
Close testcontainers#329 - This seems fixed in the underlying docker libraries.
Improve support for Docker in Docker running on a custom network, by
attempting to find the right custom network and use it for new
containers. This adds support for using testcontainers-python running
the GitHub Actions Runner Controller to run self-hosted actions runners
on prem, when you run your workflows in containers.

---------

Co-authored-by: Dee Moore <dee42moore@gmail.com>
Co-authored-by: David Ankin <daveankin@gmail.com>
Co-authored-by: Balint Bartha <39852431+totallyzen@users.noreply.github.com>
bearrito pushed a commit to bearrito/testcontainers-python that referenced this issue Mar 30, 2024
🤖 I have created a release *beep* *boop*
---


##
[4.2.0](testcontainers/testcontainers-python@testcontainers-v4.1.0...testcontainers-v4.2.0)
(2024-03-24)


### Features

* support influxdb
([testcontainers#413](testcontainers#413))
([13742a5](testcontainers@13742a5))


### Bug Fixes

* **arangodb:** tests to pass on ARM CPUs - change default image to
3.11.x where ARM image is published
([testcontainers#479](testcontainers#479))
([7b58a50](testcontainers@7b58a50))
* **core:** DinD issues
[testcontainers#141](testcontainers#141),
[testcontainers#329](testcontainers#329)
([testcontainers#368](testcontainers#368))
([b10d916](testcontainers@b10d916))
* **core:** raise an exception when docker compose fails to start
[testcontainers#258](testcontainers#258)
([testcontainers#485](testcontainers#485))
([d61af38](testcontainers@d61af38))
* **core:** use auto_remove=True with reaper instance
([testcontainers#499](testcontainers#499))
([274a400](testcontainers@274a400))
* **docs:** update the non-existent main.yml badge
([testcontainers#493](testcontainers#493))
([1d10c1c](testcontainers@1d10c1c))
* Fix the return type of `DockerContainer.get_logs`
([testcontainers#487](testcontainers#487))
([cd72f68](testcontainers@cd72f68))
* **keycloak:** tests on aarch64, use image from [jboss -&gt; quay],
change supported version [16+ -> 18+]
([testcontainers#480](testcontainers#480))
([5758310](testcontainers@5758310))
* **postgres:** doctest
([testcontainers#473](testcontainers#473))
([c9c6f92](testcontainers@c9c6f92))
* read the docs build works again
([testcontainers#496](testcontainers#496))
([dfd1781](testcontainers@dfd1781))
* readthedocs build - take 1
([testcontainers#495](testcontainers#495))
([b3b9901](testcontainers@b3b9901))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants