skip to Main Content

My integration tests using the TestContainers package run just fine locally on macOS. However, they don’t succeed in GitHub Actions, because host.docker.internal isn’t available there.

What’s an alternative? I’ve tried the Docker Host IP address, which is 172.17.0.1. However, this isn’t working either.

Example of setting up a container with my own image:

public async Task<IContainer> StartPostServiceContainerAsync(IContainer postgresContainer,
    IContainer rabbitmqContainer)
{
    var postgresPort = postgresContainer.GetMappedPublicPort(5432);
    var rabbitmqPort = rabbitmqContainer.GetMappedPublicPort(5672);

    var container = new ContainerBuilder()
        .WithImage("mydockerhubname/postservice:latest")
        .WithPortBinding(8080, true)
        .WithEnvironment("ConnectionStrings__PostsConn",
            $"Server=host.docker.internal;Port={postgresPort};Database=postgres;User Id=postgres;Password=postgres;")
        .WithEnvironment("RabbitMQHost", "host.docker.internal")
        .WithEnvironment("RabbitMQPort", rabbitmqPort.ToString())
        .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(8080))
        .WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged("Now listening on"))
        .DependsOn(postgresContainer)
        .DependsOn(rabbitmqContainer)
        .Build();

    await container.StartAsync();
    _containers["postservice"] = container;
    return container;
}

Example test:

[Fact]
public async Task Can_Call_Get_Posts_Endpoint()
{
    // Arrange
    var postgresContainer = await _fixture.StartPostgresContainerAsync();
    var rabbitmqContainer = await _fixture.StartRabbitMQContainerAsync();
    var postServiceContainer = await _fixture.StartPostServiceContainerAsync(postgresContainer, rabbitmqContainer);

    var postsServicePort = postServiceContainer.GetMappedPublicPort(8080);

    var httpClient = new HttpClient();
    var requestUri = new UriBuilder(
        Uri.UriSchemeHttp,
        postServiceContainer.Hostname,
        postsServicePort,
        "api/posts"
    ).Uri;

    // Act
    var response = await httpClient.GetAsync(requestUri);
    response.EnsureSuccessStatusCode();

    // Assert
    var content = await response.Content.ReadAsStringAsync();
    Assert.Equal("[]", content);
}

How can I fix this?

2

Answers


  1. Chosen as BEST ANSWER

    The issue has been resolved by using .withNetwork and . withNetworkAliases

    https://java.testcontainers.org/features/networking/

        public async Task<IContainer> StartPostgresContainerAsync()
        {
            var container = new ContainerBuilder()
                .WithImage("postgres:latest")
                .WithEnvironment("POSTGRES_USER", "postgres")
                .WithEnvironment("POSTGRES_PASSWORD", "postgres")
                .WithEnvironment("POSTGRES_DB", "postgres")
                .WithNetwork(_network)
                .WithNetworkAliases("postgres")
                .WithPortBinding(5432, true)
                .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(5432))
                .WithWaitStrategy(Wait.ForUnixContainer()
                    .UntilMessageIsLogged("database system is ready to accept connections"))
                .Build();
    
            await container.StartAsync();
            _containers["postgres"] = container;
    
            return container;
        }
    
            var container = new ContainerBuilder()
                .WithImage("mydockerhubname/postservice:latest")
                .WithNetwork(_network)
                .WithPortBinding(8080, true)
                .WithEnvironment("ConnectionStrings__PostsConn",
                    $"Server=postgres;Port=5432;Database=postgres;User Id=postgres;Password=postgres;")
                .WithEnvironment("RabbitMQHost", "rabbitmq")
                .WithEnvironment("RabbitMQPort", "5672")
                .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(8080))
                .WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged("Now listening on"))
                .DependsOn(postgresContainer)
                .DependsOn(rabbitmqContainer)
                .Build();
    

  2. host.docker.internal represents your machine ip address. So I think when you run it in local machine, the test container got the connection string with host.docker.internal which redirected to the local-ip, so it will query in localhost:5432 postgresql database.

    And when you run it in the github workflow, it got a complete new setup which we are not aware of. So when it got host.docker.internal it resolves it to the server’s machine ip in which the workflow is being run.And there it can’t find any postgresql server running.

    I think the solution is try to create the postgresql container from the workflow as shown here. And then try to connect and query there.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search