testcontainers-node icon indicating copy to clipboard operation
testcontainers-node copied to clipboard

HostPortWaitStrategy strategy does not work for localhost bound ports

Open jalaziz opened this issue 2 years ago • 4 comments

Expected Behaviour

When launching a container with a port bound to localhost, the wait strategy should work.

Actual Behaviour

The HostPortWaitStrategy fails to recognize the open port and eventually times out. This issue seems to only occur on Linux machines. MacOS works fine.

Testcontainer Logs

Error: Port 4566 not bound after 60000ms

   at globalSetup.ts:38

  36 |   console.log(`Starting docker compose environment...`);
  37 |   const composeFilePath = path.resolve(__dirname, '../');
> 38 |   const environment = await new DockerComposeEnvironment(
     |                       ^
  39 |     composeFilePath,
  [40](https://github.com/bastionplatforms/monorepo/actions/runs/7124569757/job/19400552961?pr=553#step:12:41) |     'docker-compose.yml',
  [41](https://github.com/bastionplatforms/monorepo/actions/runs/7124569757/job/19400552961?pr=553#step:12:42) |   )

    at /home/runner/work/monorepo/monorepo/node_modules/testcontainers/src/wait-strategies/host-port-wait-strategy.ts:52:15
    at IntervalRetry.retryUntil (/home/runner/work/monorepo/monorepo/node_modules/testcontainers/src/common/retry.ts:49:16)
    at HostPortWaitStrategy.waitForPort (/home/runner/work/monorepo/monorepo/node_modules/testcontainers/src/wait-strategies/host-port-wait-strategy.ts:[46](https://github.com/bastionplatforms/monorepo/actions/runs/7124569757/job/19400552961?pr=553#step:12:47):5)
    at HostPortWaitStrategy.waitForHostPorts (/home/runner/work/monorepo/monorepo/node_modules/testcontainers/src/wait-strategies/host-port-wait-strategy.ts:27:7)
    at HostPortWaitStrategy.waitUntilReady (/home/runner/work/monorepo/monorepo/node_modules/testcontainers/src/wait-strategies/host-port-wait-strategy.ts:14:5)
    at waitForContainer (/home/runner/work/monorepo/monorepo/node_modules/testcontainers/src/wait-strategies/wait-for-container.ts:17:5)
    at /home/runner/work/monorepo/monorepo/node_modules/testcontainers/src/docker-compose-environment/docker-compose-environment.ts:1[50](https://github.com/bastionplatforms/monorepo/actions/runs/7124569757/job/19400552961?pr=553#step:12:51):13
    at DockerComposeEnvironment.up (/home/runner/work/monorepo/monorepo/node_modules/testcontainers/src/docker-compose-environment/docker-compose-environment.ts:128:7)
    at globalSetup (/home/runner/work/monorepo/monorepo/e2e-tests/globalSetup.ts:38:23)

Steps to Reproduce

  1. Setup a GitHub Actions workflow to launch a compose project through testcontainers.
  2. The compose file:
    services:
      localstack:
        image: localstack/localstack
        ports:
          - "127.0.0.1:4566:4566"            # LocalStack Gateway
        environment:
          - DEBUG=${DEBUG-}
          - DOCKER_HOST=unix:///var/run/docker.sock
          - DYNAMODB_SHARE_DB=1
          - DYNAMODB_IN_MEMORY=1
        healthcheck:
          test: "curl --silent --fail localstack:4566/_localstack/health"
          interval: 1s
          retries: 5
          start_period: 20s
          timeout: 10s
        volumes:
          - "./.localstack/init-aws.sh:/etc/localstack/init/ready.d/init-aws.sh"  # ready hook
          - "./.localstack-volume:/var/lib/localstack"
          - "/var/run/docker.sock:/var/run/docker.sock"
    
  3. Run 'await new DockerComposeEnvironment(composeFilePath, 'docker-compose.yml').up();`
  4. See error...

Environment Information

  • Operating System: Ubuntu 22.04
  • Docker Version: 24.0.7
  • Node version: 18.18.2
  • Testcontainers version: 10.3.2

jalaziz avatar Dec 07 '23 17:12 jalaziz

@jalaziz @cristianrgreco any solution for this?

I was in a previous project using:

  const environment = await new DockerComposeEnvironment(composeFilePath, composeFile)
    .withEnvironment({
      ...
    })
    .withWaitStrategy(serviceName, Wait.forHealthCheck())
    .up([serviceName]);

But now for a new project with lot of dependencies updated (ESM modules, different Node version...), it times out saying Port 52670 not bound after 60000ms (it seems to come from https://github.com/testcontainers/testcontainers-node/blob/9805f226ed259e451c46f15d3988bdff992c46d8/packages/testcontainers/src/wait-strategies/host-port-wait-strategy.ts#L45-L57).

Note I tried to use testcontainers with the latest version and also v9.6.0 that is on the other project.

Thank you,

EDIT: I'm on a MacOS Intel

EDIT2: I did other attempts to run the test without ESM settings into my Jest setup, but it's the same error. It's so weird...

EDIT3: On my side I'm using the strategy Wait.forHealthCheck() for both the working and failing projects

sneko avatar Feb 20 '24 13:02 sneko

After spending some time on it, it seems my old way of bindings ports to make them random on the list:

    ports:
      - '127.0.0.1::5432'

is not working for any reason on the new project.

Switching to:

    ports:
      - '5432'

Don't tell why... the old way is working in a project with direct dependencies versions aligned (also I don't remember why I had to use the 127.0.0.1 at that time). Hope it helps 👍

sneko avatar Feb 20 '24 15:02 sneko

@jalaziz @cristianrgreco any solution for this?

Unfortunately no solution. I've switched to Wait.forHealthCheck() with custom healtchecks for the time being.

jalaziz avatar Feb 21 '24 05:02 jalaziz

I think I just ran into this -- except I can't actually get the custom health check to pass either, even with test: ["CMD-SHELL", "exit 0"] it just fails for however long.

It would be nice if there wasn't a default healthcheck (or it could be disbaled) that tried to use the ports -- it's helpful but a way to disable that logic would be nice

t3hmrman avatar Aug 29 '24 13:08 t3hmrman