testcontainers / testcontainers-python

Testcontainers is a Python library that providing a friendly API to run Docker container. It is designed to create runtime environment to use during your automatic tests.
https://testcontainers-python.readthedocs.io/en/latest/
Apache License 2.0
1.58k stars 288 forks source link

Bug: Impossible to run postgres on custom port #696

Closed romanzdk closed 1 month ago

romanzdk commented 1 month ago

Describe the bug

I need to run 2 postgres databases each on different port. Both containers start and from logs I can see that both are ready but testcontainers are just stuck on "Waiting for container...".

To Reproduce

from testcontainers.postgres import PostgresContainer
import pytest

@pytest.fixture(scope = 'session')
def get_pg():
    with PostgresContainer('postgres:13.0', port = 5432) as postgres:
        yield postgres

@pytest.fixture(scope = 'session')
def get_pg2():
    with PostgresContainer('postgres:13.0', port = 5433) as postgres:
        yield postgres

def test_main(get_pg, get_pg2):
    pass

and run pytest file.py -sv to get:

tst.py::test_main Pulling image testcontainers/ryuk:0.8.1
Container started: 6625a5a0b4b6
Waiting for container <Container: 6625a5a0b4b6> with image testcontainers/ryuk:0.8.1 to be ready ...
Pulling image postgres:13.0
Container started: efc03dfa6156
Waiting for container <Container: efc03dfa6156> with image postgres:13.0 to be ready ...
Pulling image postgres:13.0
Container started: 5d210f1c2925
Waiting for container <Container: 5d210f1c2925> with image postgres:13.0 to be ready ...

docker ps gives:

CONTAINER ID   IMAGE                       COMMAND                  CREATED          STATUS          PORTS                                                   NAMES
d798e5b25672   postgres:13.0               "docker-entrypoint.s…"   11 seconds ago   Up 11 seconds   5432/tcp, 0.0.0.0:32809->5433/tcp, :::32809->5433/tcp   practical_golick
22577bb1ae29   postgres:13.0               "docker-entrypoint.s…"   14 seconds ago   Up 13 seconds   0.0.0.0:32808->5432/tcp, :::32808->5432/tcp             gallant_wescoff
2bf51013a3b1   testcontainers/ryuk:0.8.1   "/bin/ryuk"              14 seconds ago   Up 13 seconds   0.0.0.0:32807->8080/tcp, :::32807->8080/tcp             testcontainers-ryuk-da6ca2ce-355d-43d2-b40c-09c

Runtime environment

# Get the operating system information (on a unix os).
Darwin Roman--MacBook-Pro.local 23.3.0 Darwin Kernel Version 23.3.0: Wed Dec 20 21:30:59 PST 2023; root:xnu-10002.81.5~7/RELEASE_ARM64_T6030 arm64
# Get the python version.
python 3.12.2
testcontainers==4.8.1
alexanderankin commented 1 month ago

the postgres image does not support being run on a custom port. if you are trying to expose it on a specific port, please consider just letting the container runtime pick a random port and querying it at runtime to determine which external port to use.

it is not being considered right now to implement a custom internal port.

https://github.com/docker-library/docs/blob/master/postgres/README.md

alexanderankin commented 1 month ago

for this use case:

mkdir  testcontainers-python_696
cd  testcontainers-python_696
python -m venv .venv
test -f .venv/bin/activate && . .venv/bin/activate || . .venv/Scripts/activate
pip install testcontainers pytest
from testcontainers.postgres import PostgresContainer
import pytest

@pytest.fixture(scope = 'session')
def get_pg():
    with PostgresContainer('postgres:16-alpine') as postgres:
        yield postgres

@pytest.fixture(scope = 'session')
def get_pg2():
    with PostgresContainer('postgres:16-alpine') as postgres:
        yield postgres

def test_main(get_pg, get_pg2):
    print(f"get_pg has port {get_pg.get_exposed_port(5432)}")
    print(f"get_pg2 has port {get_pg2.get_exposed_port(5432)}")

produces:

$ pytest script.py  -s
=============================================================================================== test session starts ===============================================================================================
platform linux -- Python 3.11.9, pytest-8.3.2, pluggy-1.5.0
rootdir: ~/testcontainers-python_696
collected 1 item                                                                                                                                                                                                  

script.py Pulling image testcontainers/ryuk:0.8.1
Container started: a08116c1c65a
Waiting for container <Container: a08116c1c65a> with image testcontainers/ryuk:0.8.1 to be ready ...
Pulling image postgres:16-alpine
Container started: 377144de6df4
Waiting for container <Container: 377144de6df4> with image postgres:16-alpine to be ready ...
Pulling image postgres:16-alpine
Container started: 447592a8ac89
Waiting for container <Container: 447592a8ac89> with image postgres:16-alpine to be ready ...
Waiting for container <Container: 377144de6df4> with image postgres:16-alpine to be ready ...
get_pg has port 32778
Waiting for container <Container: 447592a8ac89> with image postgres:16-alpine to be ready ...
get_pg2 has port 32779