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

wait strategy conflict when two mysql databases are up (Port 33060 not bound after 60000ms) #107

Closed
rhyek opened this issue Jul 22, 2020 · 9 comments · Fixed by #108
Closed

Comments

@rhyek
Copy link
Contributor

rhyek commented Jul 22, 2020

I'm working on a monorepo using nx. I have two docker-compose.yamls: one for my local dev environment which I have permanently up using docker-compose up -d and then one dedicated to e2e tests using testcontainers.

dev:

version: "3"
services:
  db:
    container_name: leadgogo_dev_db
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - "MYSQL_USER=${DB_USER}"
      - "MYSQL_PASSWORD=${DB_PASS}"
      - "MYSQL_DATABASE=${DB_DBNAME}"
    volumes:
      - ./leadgogo_20200624_1428AST.sql.gz:/docker-entrypoint-initdb.d/dump.sql.gz
    ports:
      - "${DB_PORT}:3306"

e2e

version: '3'
services:
  db:
    container_name: leadgogo_e2e_webapi_db
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - 'MYSQL_USER=${DB_USER}'
      - 'MYSQL_PASSWORD=${DB_PASS}'
      - 'MYSQL_DATABASE=${DB_DBNAME}'
    volumes:
      - ./leadgogo_20200624_1428AST.sql.gz:/docker-entrypoint-initdb.d/dump.sql.gz
    ports:
      - '${DB_PORT}:3306'
  migrations:
    container_name: leadgogo_e2e_webapi_migrations
    build: ./e2e-dist/sql-migrations
    environment:
      - 'DB_USER=${DB_USER}'
      - 'DB_PASS=${DB_PASS}'
      - DB_HOST=db
      - DB_PORT=3306
      - 'DB_DBNAME=${DB_DBNAME}'
    depends_on:
      - db

The e2e environment is activated in my jest test file like this:

const environment = await new DockerComposeEnvironment(
  composeFilePath,
  composeFile
)
  .withBuild()
  .withWaitStrategy(
    'leadgogo_e2e_webapi_db',
    Wait.forLogMessage(`socket: '/var/run/mysqld/mysqld.sock'  port: 3306`)
  )
  .up();

When I have my dev docker compose up I can't run my e2e tests successfully. They always fail with the internal testcontainers error message Port 33060 not bound after 60000ms.

As soon as I deactivate the dev docker compose my e2e tests will consistently pass.

I have debug logs for both situations:
with dev up
with dev down

One obvious difference is in first one you see the debug message testcontainers DEBUG Waiting for internal port 33060 +32ms while in the second you do not.

@rhyek rhyek mentioned this issue Jul 22, 2020
@rhyek
Copy link
Contributor Author

rhyek commented Jul 22, 2020

So that PR fixes my issue, but as an aside, @cristianrgreco is the wait strategy I've supplied there necessary? Not sure how the implicit wait strategy works for a mysql-based container.

@cristianrgreco
Copy link
Collaborator

@rhyek the wait strategy is only necessary if the service - mysql in this case - is not ready to accept connections once its port is bound. By default testcontainers will wait for any port the service exposes to be bound. Does it not work if you remove the wait strategy from your example?

@rhyek
Copy link
Contributor Author

rhyek commented Jul 22, 2020

@rhyek the wait strategy is only necessary if the service - mysql in this case - is not ready to accept connections once its port is bound. By default testcontainers will wait for any port the service exposes to be bound. Does it not work if you remove the wait strategy from your example?

@cristianrgreco thanks. it does work without it, but wasn't sure if it could cause any issues.

Edit: This is inaccurate. Read below.

@cristianrgreco
Copy link
Collaborator

GH auto-closes issues now when the PR is merged 🙂 Will release this shortly..

@cristianrgreco
Copy link
Collaborator

Available in 3.2.0, pls close the issue if all is working 🙂

@rhyek
Copy link
Contributor Author

rhyek commented Jul 22, 2020

@cristianrgreco everything works perfect now. Thanks! :-)

@rhyek rhyek closed this as completed Jul 22, 2020
@rhyek
Copy link
Contributor Author

rhyek commented Jul 22, 2020

@cristianrgreco, fyi and unrelated to this issue, I just tested without the log message wait strategy and I now get the same error Port 33060 not bound after 60000ms, only this time it's pointing to the correct container. I assume it's not an issue with testcontainers, but just a detail with the mysql image. What do you think?

@cristianrgreco
Copy link
Collaborator

cristianrgreco commented Jul 23, 2020

@rhyek I just tested this locally. If no wait strategy is provided, testcontainers defaults to waiting for the container's host ports. MySQL exposes two, 3306 and 33060. It seems port 33060 never gets bound, so the default wait strategy will timeout. I tried specifying the log message wait strategy and it works as expected:

const { DockerComposeEnvironment, Wait } = require("testcontainers");

(async () => {
    const environment = await new DockerComposeEnvironment(__dirname, "docker-compose.yml")
      .withBuild()
      .withWaitStrategy('leadgogo_e2e_webapi_db', Wait.forLogMessage(`socket: '/var/run/mysqld/mysqld.sock'  port: 3306`))
      .up();
})();

Does this snippet not work for you?

@rhyek
Copy link
Contributor Author

rhyek commented Jul 23, 2020

@cristianrgreco yes, that code works fine for my purposes.

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

Successfully merging a pull request may close this issue.

2 participants