testcontainers / testcontainers-rs

A library for integration-testing against docker containers from within Rust.
https://rust.testcontainers.org
Apache License 2.0
753 stars 142 forks source link

Can't connect to container #753

Closed jaads closed 1 day ago

jaads commented 5 days ago

For my tests I currently have to start the docker container manually. I want to change that by using testcontainers-rs. I created the container like it's stated in the docs, with the same configuration as it is in my docker compose file. But I cannot connect to it. Due to my PG client (sqlx) is

Io(Os { code: 61, kind: ConnectionRefused, message: "Connection refused" })

and this although when starting the container from the docker compose file, it worked fine. I tried other clients, but no one is working.

Here is my initial container configuration from docker compose:

version: '3.8'

services:
  postgres:
    image: postgis/postgis:13-3.4-alpine
    environment:
      POSTGRES_PASSWORD: passwd
    ports:
      - 5100:5432

I can connect to it without any problems. But when I start the same thing with testcontainer-rs, I cannot connect anymore. This is how I converted it:

const CONTAINER_PORT: u16 = 5432;

pub async fn start_database() -> u16 {
    let container = GenericImage::new("postgis/postgis", "13-3.4-alpine")
        .with_exposed_port(CONTAINER_PORT.tcp())
        .with_wait_for(WaitFor::message_on_stdout("ready to accept connections"))
        .with_env_var("POSTGRES_USER", "postgres")
        .with_env_var("POSTGRES_PASSWORD", "passwd")
        .start()
        .await
        .expect("Unable to start container");

    println!("Started container: {:?}", container);

    // return the ephemeral host ports
    container
        .get_host_port_ipv4(CONTAINER_PORT)
        .await
        .expect("Unable to get container port")
}

The container starts successfully and the functions returns the port. Here how I'm trying to connect to it:

#[tokio::test]
async fn test_schema_and_data_operations() {
    let port = start_database().await;
    let s = format!("postgres://postgres:passwd@localhost:{}/postgres", port);
    PgConnection::connect(s.as_str()).await.unwrap();
}

But it does not connect. It panics with the above error message (connection refused). What I am missing?

DDtKey commented 4 days ago

Hi @jaads šŸ‘‹
Please, check a little bit different issue, but it should help you since there is common ground between them: https://github.com/testcontainers/testcontainers-rs/issues/752

Specifically my responses there

jaads commented 4 days ago

Hi @DDtKey. I have tried using the ready-to-use postgres module, but I encountered the same issue unfortunately :/

DDtKey commented 4 days ago

Looks like the container is dropped before even attempt to connect:

start_database returns u16 => Container is dropped almost immediately after start

Take a look at the documentation about usage

jaads commented 4 days ago

ohh that was indeed the problem. my bad!! thanks so much @DDtKey!

I now get { code: 54, kind: ConnectionReset, message: "Connection reset by peer" } though. I don't think I can use the ready-to-use postgres container because I also need to have postgis installed. Is there a workaround for this issue? I guess it's the same as https://github.com/testcontainers/testcontainers-rs/issues/752

DDtKey commented 4 days ago

Generally speaking - yes, you can apply the same patch for your implementation as we did for postgres prepared module.

But actually, you still should be able to use ready one, but customize the image with ImageExt - see examples in the documentation

jaads commented 2 days ago

I wasn't able to fix it myself, so I used the ready so use module for now. But at some point I'd need to use this image. since there is no ready to use module for this image, will the fix be applied for GenericImage as well?

DDtKey commented 2 days ago

As I mentioned above, you can use ImageExt for existing postgres module to override the image reference. See with_name method documentation

It's only postgres specific, and there is nothing to do with generic one. It's just additional WaitFor required (actual fix was only this PR)

jaads commented 1 day ago

alright, I have it now using with_name āœ… thanks so much!! šŸŽ‰