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

Containers fail to start: mssql/win11, mssql/m1, mssql with different port (not intended to work), postgres/win10, mariadb/win11, oracle #360

Open
snifhex opened this issue May 29, 2023 · 13 comments

Comments

@snifhex
Copy link

snifhex commented May 29, 2023

I'm unable to run the SqlServerContainer. After creating the MSSQL container, it gets stuck at the "waiting to be ready" state and does not proceed further.

image

To Reproduce

from sqlalchemy import create_engine, text
from testcontainers.mssql import SqlServerContainer

with SqlServerContainer() as mssql:
    engine = create_engine(mssql.get_connection_url())
    with engine.begin() as connection:
        version = connection.execute(text("select @@VERSION"))

Runtime environment

Docker Desktop 4.19.0 (106363)
Windows 11
Python 3.9
testcontainers==3.7.1
@paketb0te
Copy link

it gets stuck at the "waiting to be ready" state and does not proceed further.

Does it finish execution at some point? Because your code does not actually print anything so you would see no output even if it works...

from sqlalchemy import create_engine, text
from testcontainers.mssql import SqlServerContainer

with SqlServerContainer() as mssql:
    engine = create_engine(mssql.get_connection_url())
    with engine.begin() as connection:
        version = connection.execute(text("select @@VERSION"))
        print(version.all())

This works fine for me (on linux though):

$ python baz.py
Pulling image mcr.microsoft.com/mssql/server:2019-latest
Container started: 813db1176b94
Waiting to be ready...
Waiting to be ready...
Waiting to be ready...
Waiting to be ready...
Waiting to be ready...
Waiting to be ready...
Waiting to be ready...
Waiting to be ready...
Waiting to be ready...
mssql+pymssql://SA:1Secure*Password1@localhost:49158/tempdb
[('Microsoft SQL Server 2019 (RTM-CU21) (KB5025808) - 15.0.4316.3 (X64) \n\tJun  1 2023 16:32:31 \n\tCopyright (C) 2019 Microsoft Corporation\n\tDeveloper Edition (64-bit) on Linux (Ubuntu 20.04.6 LTS) <X64>',)]

@UsmanAbbasi1
Copy link

Any updates on this? I am facing the same issue on mac m1 machine.

@robinalexandre
Copy link

robinalexandre commented Jul 7, 2023

Hello,

Any news ?

Same for me here !

EDIT :

It works if I do not change the default port for me

@ieCecchetti
Copy link

Same for me but for the PostgreSQL container:

Pulling image postgres:latest
Container started: 502b64b3db55
Waiting to be ready...
Waiting to be ready...
Waiting to be ready...

Code is:

from testcontainers.postgres import PostgresContainer
postgres_container = PostgresContainer("postgres:latest", port=54321, dbname=database_name)
    with postgres_container as postgres:
        # Get the connection details for the container
        connection_details = postgres.get_connection_url()

env:

Docker Desktop 4.21.1 
Windows 10
Python 3.9
testcontainers==3.7.1

@JamesFlanders
Copy link

There is a temporary solution mentioned for this issue:
#108 (comment)

@nsaccente
Copy link

nsaccente commented Nov 5, 2023

I've encountered this same issue with mariadb:11.1.2 on Windows 11, except in my case, I was using testcontainers.mysql.MySqlContainer. I got around this issue by just using the core API instead of relying on the addon package:

import subprocess
from testcontainers.core.container import DockerContainer
from testcontainers.core.waiting_utils import wait_for_logs
from time import sleep
from tqdm import tqdm


IMAGE="mariadb:11.1.2"

# Run the docker pull as a separate process since relying on testcontainers to
# pull through the API on windows gives me some issue.
if subprocess.run(["docker", "pull", IMAGE]).returncode == 1:
    raise Exception(
        f"Unable to pull image '{IMAGE}'. Make sure the Docker daemon is "
        "running. If problems persist, you can pull the image manually."
    )

container = DockerContainer(image=IMAGE)
container.env={
   "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD": "1",
   "MARIADB_ALLOW_EMPTY_PASSWORD": "1",
}
container.start()
waiting = wait_for_logs(container, "ready for connections")
print(container.get_container_host_ip)
for i in tqdm(range(20)):
   # Take this time to check docker that the container is running!
   sleep(1)
container.stop()

I hope this helps someone!

@thuyng-ing
Copy link

thuyng-ing commented Jan 25, 2024

Same for me for Oracle

    from testcontainers.oracle import OracleDbContainer

    with OracleDbContainer() as oracle:
        engine = sqlalchemy.create_engine(oracle.get_connection_url())

        with engine.begin() as connection:
            result = connection.execute(sqlalchemy.text("select * from V$VERSION"))

env

Docker Desktop v4.26.1
Windows 10
Python 3.11
testcontainers==3.7.1

@thuyng-ing
Copy link

thuyng-ing commented Jan 26, 2024

<Quoted Reply>

I've encountered this same issue with mariadb:11.1.2 on Windows 11, except in my case, I was using testcontainers.mysql.MySqlContainer. I got around this issue by just using the core API instead of relying on the addon package:

import subprocess
from testcontainers.core.container import DockerContainer
from testcontainers.core.waiting_utils import wait_for_logs
from time import sleep
from tqdm import tqdm


IMAGE="mariadb:11.1.2"

# Run the docker pull as a separate process since relying on testcontainers to
# pull through the API on windows gives me some issue.
if subprocess.run(["docker", "pull", IMAGE]).returncode == 1:
    raise Exception(
        f"Unable to pull image '{IMAGE}'. Make sure the Docker daemon is "
        "running. If problems persist, you can pull the image manually."
    )

container = DockerContainer(image=IMAGE)
container.env={
   "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD": "1",
   "MARIADB_ALLOW_EMPTY_PASSWORD": "1",
}
container.start()
waiting = wait_for_logs(container, "ready for connections")
print(container.get_container_host_ip)
for i in tqdm(range(20)):
   # Take this time to check docker that the container is running!
   sleep(1)
container.stop()

I hope this helps someone!

Thanks to @nsaccente reply. I managed to make something that works for Oracle on Windows 10. I hope this helps someone.

oracle container sample code
import subprocess

import sqlalchemy
from sqlalchemy import create_engine
from testcontainers.core.container import DockerContainer
from testcontainers.core.waiting_utils import wait_for_logs

IMAGE="gvenzl/oracle-xe:21-slim-faststart"

# Run the docker pull as a separate process since relying on testcontainers to
# pull through the API on windows gives me some issue.
if subprocess.run(["docker", "pull", IMAGE]).returncode == 1:
    raise Exception(
        f"Unable to pull image '{IMAGE}'. Make sure the Docker daemon is "
        "running. If problems persist, you can pull the image manually."
    )

db_port = 1521
db_username = "system"
db_password = "oracle"
db_name = "xe"
os.environ['TC_HOST'] = 'localhost'

container = DockerContainer(image=IMAGE)

container.with_exposed_ports(db_port)
container.env={
    "ORACLE_USERNAME": "system",
    "ORACLE_PASSWORD": "oracle",
    "DB_NAME": "xe",
    "DB_HOST": "oracle",
}

container.start()

waiting = wait_for_logs(container, "DATABASE IS READY TO USE!")

engine = create_engine(f'oracle+oracledb://system:oracle@(DESCRIPTION=(CONNECT_TIMEOUT=30)(RETRY_COUNT=20)(RETRY_DELAY=3)(ADDRESS_LIST=(LOAD_BALANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST={container.get_container_host_ip()})(PORT={container.get_exposed_port(db_port)})))(CONNECT_DATA=(SERVICE_NAME={db_name})))')
with engine.begin() as connection:
    result = connection.execute(sqlalchemy.text("select * from V$VERSION"))
    print(result)

container.stop()

@alexanderankin
Copy link
Member

@thuyng-ing i think this is the module we are looking to merge for oracle but i guess we will be looking at these suggestions as well when we are able to publish again - #363

@Wormfriend
Copy link

Wormfriend commented Feb 1, 2024

<Quoted Reply>

I've encountered this same issue with mariadb:11.1.2 on Windows 11, except in my case, I was using testcontainers.mysql.MySqlContainer. I got around this issue by just using the core API instead of relying on the addon package:

import subprocess
from testcontainers.core.container import DockerContainer
from testcontainers.core.waiting_utils import wait_for_logs
from time import sleep
from tqdm import tqdm


IMAGE="mariadb:11.1.2"

# Run the docker pull as a separate process since relying on testcontainers to
# pull through the API on windows gives me some issue.
if subprocess.run(["docker", "pull", IMAGE]).returncode == 1:
    raise Exception(
        f"Unable to pull image '{IMAGE}'. Make sure the Docker daemon is "
        "running. If problems persist, you can pull the image manually."
    )

container = DockerContainer(image=IMAGE)
container.env={
   "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD": "1",
   "MARIADB_ALLOW_EMPTY_PASSWORD": "1",
}
container.start()
waiting = wait_for_logs(container, "ready for connections")
print(container.get_container_host_ip)
for i in tqdm(range(20)):
   # Take this time to check docker that the container is running!
   sleep(1)
container.stop()

I hope this helps someone!

Thanks to @nsaccente reply. I managed to make something that works for Oracle on Windows 10. I hope this helps someone.

import subprocess

import sqlalchemy
from sqlalchemy import create_engine
from testcontainers.core.container import DockerContainer
from testcontainers.core.waiting_utils import wait_for_logs

IMAGE="gvenzl/oracle-xe:21-slim-faststart"

# Run the docker pull as a separate process since relying on testcontainers to
# pull through the API on windows gives me some issue.
if subprocess.run(["docker", "pull", IMAGE]).returncode == 1:
    raise Exception(
        f"Unable to pull image '{IMAGE}'. Make sure the Docker daemon is "
        "running. If problems persist, you can pull the image manually."
    )

db_port = 1521
db_username = "system"
db_password = "oracle"
db_name = "xe"
os.environ['TC_HOST'] = 'localhost'

container = DockerContainer(image=IMAGE)

container.with_exposed_ports(db_port)
container.env={
    "ORACLE_USERNAME": "system",
    "ORACLE_PASSWORD": "oracle",
    "DB_NAME": "xe",
    "DB_HOST": "oracle",
}

container.start()

waiting = wait_for_logs(container, "DATABASE IS READY TO USE!")

engine = create_engine(f'oracle+oracledb://system:oracle@(DESCRIPTION=(CONNECT_TIMEOUT=30)(RETRY_COUNT=20)(RETRY_DELAY=3)(ADDRESS_LIST=(LOAD_BALANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST={container.get_container_host_ip()})(PORT={container.get_exposed_port(db_port)})))(CONNECT_DATA=(SERVICE_NAME={db_name})))')
with engine.begin() as connection:
    result = connection.execute(sqlalchemy.text("select * from V$VERSION"))
    print(result)

container.stop()
@pytest.fixture(scope="session", autouse=True)
def setup_testdb(): 
    image = "mcr.microsoft.com/mssql/server:2022-latest"
    container = DockerContainer(image=image)
    container.env = {
        "ACCEPT_EULA": "Y",
        "MSSQL_SA_PASSWORD":"1TestTest!"
    }
    container.with_bind_ports(1433, host=1433)
    with container as mssql:
        wait_for_logs(container, "SQL Server is now ready for client connections")
        print(mssql.get_container_host_ip())
        yield mssql

The above listing adapted for usage within a pytest.fixture and mssql. Thank you very much for your help!

@alexanderankin alexanderankin changed the title Container Stuck at "Waiting to be Ready" State Containers fail to start: mssql/win11, mssql/m1, mssql with different port (not intended to work), postgres/win10, mariadb/win11, oracle Mar 31, 2024
@mlt-dk
Copy link

mlt-dk commented Apr 3, 2024

I have the same problem

Just wanted to add a clue to the problem solving (I know below isn't really practical as a solution)...

If I debug into the SqlServerContainer and further into the _connect method of the underlying DbContainer base class and simply step through the lines the container class successfully instantiates and connects to the docker container. This led me to believe that the time delay introduced by manually stepping through the code in debug made the testcontainer successfully capture the log message it was listening for.

In fact, adding a sleep to the start method of the DbContainer makes it run successfully on my end (I know this is hacky and is likely hiding another problem - but wanted to mention it as a clue)

image

@santi
Copy link
Collaborator

santi commented Apr 4, 2024

The SQL Server images take a looong time to start in most cases. To try pinpointing the errors here further, you could try the following:

  • Try using a specific SQL Server container image tag, like mcr.microsoft.com/mssql/server:2022-CU12-ubuntu-22.04
  • Try using a lighter SQL Server compatible image like mcr.microsoft.com/azure-sql-edge:1.0.7

Also note that the default SqlServerContainer expects sqlalchemy to use the pymssql driver, where the package pymssql needs to be installed. If you want to use another driver (which also needs to be installed), try using pyodbc:

with SqlServerContainer("mcr.microsoft.com/mssql/server:2022-CU12-ubuntu-22.04", dialect="mssql+pyodbc",) as mssql:
    engine = sqlalchemy.create_engine(mssql.get_connection_url())
    with engine.begin() as connection:
        result = connection.execute(sqlalchemy.text("select @@VERSION"))

Lastly, to check that you are able to start the image at all, try starting it manually with docker and observe the log output:

docker run -e ACCEPT_EULA=y -e SQLSERVER_USER=SA -e SA_PASSWORD="1Secure*Password1" mcr.microsoft.com/mssql/server:2022-CU12-ubuntu-22.04

@santi
Copy link
Collaborator

santi commented Apr 4, 2024

On another note: If #525 lands, the wait strategy will change and testing will be more robust for more image versions which might fix your problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests