Testcontainers-java: MySQLContainer unable to run MySQL 8

Created on 6 Jun 2018  ·  8Comments  ·  Source: testcontainers/testcontainers-java

I'm having trouble getting MySQL 8 (namely mysql:8.0.11 image) to run with Testcontainers. Container startup fails due to timeout, with the following output:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
log4j:WARN No appenders could be found for logger (org.testcontainers.shaded.io.netty.util.internal.logging.InternalLoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
        ℹ︎ Checking the system...
        ✔ Docker version should be at least 1.6.0
        ✔ Docker environment should have more than 2GB free disk space
        ✔ File should be mountable
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

org.testcontainers.containers.ContainerLaunchException: Container startup failed

    at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:214)
    at org.testcontainers.containers.GenericContainer.starting(GenericContainer.java:638)
    at org.testcontainers.containers.FailureDetectingExternalResource$1.evaluate(FailureDetectingExternalResource.java:29)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
    at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:83)
    at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:207)
    ... 9 more
Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
    at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:279)
    at org.testcontainers.containers.GenericContainer.lambda$start$0(GenericContainer.java:209)
    at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:76)
    ... 10 more
Caused by: org.rnorth.ducttape.TimeoutException: org.rnorth.ducttape.TimeoutException: java.util.concurrent.TimeoutException
    at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:53)
    at org.testcontainers.containers.JdbcDatabaseContainer.waitUntilContainerStarted(JdbcDatabaseContainer.java:94)
    at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:258)
    ... 12 more
Caused by: org.rnorth.ducttape.TimeoutException: java.util.concurrent.TimeoutException
    at org.rnorth.ducttape.timeouts.Timeouts.callFuture(Timeouts.java:70)
    at org.rnorth.ducttape.timeouts.Timeouts.getWithTimeout(Timeouts.java:43)
    at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:38)
    ... 14 more
Caused by: java.util.concurrent.TimeoutException
    at java.util.concurrent.FutureTask.get(FutureTask.java:205)
    at org.rnorth.ducttape.timeouts.Timeouts.callFuture(Timeouts.java:65)
    ... 16 more


Test ignored.

Process finished with exit code 255

Note:
I've tried overriding MySQLContainer#getDriverClassName to address the JDBC driver warning, but that didn't affect anything.

This can be reproduced with a very simple project using:

plugins {
    id 'java'
}

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.12'
    testCompile 'mysql:mysql-connector-java:8.0.11'
    testCompile 'org.testcontainers:mysql:1.7.3'
}
public class DemoTests {

    @ClassRule
    public static MySQLContainer container = new MySQLContainer("mysql:8.0.11");

    private DataSource dataSource;

    @Before
    public void setUp() {
        MysqlDataSource dataSource = new MysqlDataSource();
        dataSource.setUrl(container.getJdbcUrl());
        dataSource.setUser(container.getUsername());
        dataSource.setPassword(container.getPassword());
        this.dataSource = dataSource;
    }

    @Test
    public void someTest() throws Exception {
        try (Connection con = this.dataSource.getConnection();
                PreparedStatement ps = con.prepareStatement("select 1");
                ResultSet rs = ps.executeQuery()) {
            while (rs.next()) {
                System.out.println(rs.getInt(0));
            }
        }
    }

}

Environment details:

$ cat /etc/os-release 
NAME="Ubuntu"
VERSION="18.04 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
$ uname -srvmpio
Linux 4.15.0-22-generic #24-Ubuntu SMP Wed May 16 12:15:17 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ java -version
openjdk version "1.8.0_172"
OpenJDK Runtime Environment (Zulu 8.30.0.1-linux64) (build 1.8.0_172-b01)
OpenJDK 64-Bit Server VM (Zulu 8.30.0.1-linux64) (build 25.172-b01, mixed mode)
$ docker version 
Client:
 Version:      18.05.0-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   f150324
 Built:        Wed May  9 22:16:13 2018
 OS/Arch:      linux/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.05.0-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   f150324
  Built:        Wed May  9 22:14:23 2018
  OS/Arch:      linux/amd64
  Experimental: false
good first issue hacktoberfest modulejdbc resolutioacknowledged typfeature

Most helpful comment

When you simply run it with
docker run -it --rm -e MYSQL_ROOT_PASSWORD=blablubb -p 3306:3306 mysql:latest
you can't connect to the database plain with normal connection. Even with not the latest MySQL Workbench this is an issue, see screenshot.
screenshot_2018-06-08_15-49-52

We could use a workaround for this:
docker run -it --rm -e MYSQL_ROOT_PASSWORD=blablubb -p 3306:3306 mysql:latest --default-authentication-plugin=mysql_native_password

This does even work for the 5.7, 5.6 mysql docker image but it does not work for the 5.5 one.

So the workaround should only applied to mysql docker images with version >= 5.6. But we can't decide by using docker tags since the docker tags are free to change for everyone.

We need a check for the version of given docker image before starting it. We could simply launch one container before and parse the version but this might be a big performance issue then.

If you want to use mysql:8 as docker image or mysql:latest I would suggest to add the command --default-authentication-plugin=mysql_native_password to your MySqlContainer instance.

All 8 comments

When you simply run it with
docker run -it --rm -e MYSQL_ROOT_PASSWORD=blablubb -p 3306:3306 mysql:latest
you can't connect to the database plain with normal connection. Even with not the latest MySQL Workbench this is an issue, see screenshot.
screenshot_2018-06-08_15-49-52

We could use a workaround for this:
docker run -it --rm -e MYSQL_ROOT_PASSWORD=blablubb -p 3306:3306 mysql:latest --default-authentication-plugin=mysql_native_password

This does even work for the 5.7, 5.6 mysql docker image but it does not work for the 5.5 one.

So the workaround should only applied to mysql docker images with version >= 5.6. But we can't decide by using docker tags since the docker tags are free to change for everyone.

We need a check for the version of given docker image before starting it. We could simply launch one container before and parse the version but this might be a big performance issue then.

If you want to use mysql:8 as docker image or mysql:latest I would suggest to add the command --default-authentication-plugin=mysql_native_password to your MySqlContainer instance.

Thanks @StefanHufschmidt - I originally tried to start the container manually and connect to it using mysql CLI client and was under impression that it worked, but I must've messed something up (like starting the wrong container :roll_eyes:) as now I do get the same ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded like you.

Hopefully this ticket can still be used to provide the solution within Testcontainers that would make it work out-of-the-box.

I read in https://dev.mysql.com/doc/connectors/en/connector-j-reference-configuration-properties.html that you could set the defaultAuthenticationPlugin property on the jdbc url. I tried to set it to com.mysql.cj.protocol.a.authentication.MysqlNativePasswordPlugin (even though the doc (erroneously?) says it's the default) but it does not work. Has anyone explored this option already?

I'm also trying to run TC with MySQL 8.x. I tried adding the"--default-authentication-plugin=mysql_native_password" config but it just hangs till a timeout occurs. In the logs there's a mbind: Operation not permitted message printed but apparently it's not the problem and it's just a warning according to https://github.com/docker-library/mysql/issues/303

Has anyone succeeded in running MySQL 8.x with MySQLContainer?

FWIW this my log:

15:43:17.351 [tc-okhttp-stream-1806378373] INFO  o.x.t.d.j.d.DatabaseContainerExecutor - STDERR: 2019-01-14T14:43:17.350505Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.13'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.
15:43:17.378 [tc-okhttp-stream-1806378373] INFO  o.x.t.d.j.d.DatabaseContainerExecutor - STDERR: 2019-01-14T14:43:17.377980Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: '/var/run/mysqld/mysqlx.sock' bind-address: '::' port: 33060
15:43:17.440 [tc-okhttp-stream-1806378373] INFO  o.x.t.d.j.d.DatabaseContainerExecutor - STDERR: mbind: Operation not permitted
15:44:59.807 [main] ERROR 🐳 [mysql:8] - Could not start container
org.rnorth.ducttape.TimeoutException: org.rnorth.ducttape.TimeoutException: java.util.concurrent.TimeoutException
...

I did some more debugging last weekend, I am using Spring Boot and apparently if you add any property to your jdbc url (spring.datasource.url), it will not help as testcontainers doesn't seem to be using that url to test if the container is up and running.

apparently if you add any property to your jdbc url (spring.datasource.url), it will not help as testcontainers doesn't seem to be using that url to test if the container is up and running.

Note: I do use some property to the JDBC URL (jdbc:mysql://%s:%s/xwiki?useSSL=false) but this has always worked with MySQL 5.5, 5.7. Only problem I have is with MySQL 8, and I've added --default-authentication-plugin=mysql_native_password as suggested, using https://github.com/xwiki/xwiki-platform/blob/91edf322863811160bb9e78e1439641dfc9237bd/xwiki-platform-core/xwiki-platform-test/xwiki-platform-test-docker/src/main/java/org/xwiki/test/docker/junit5/database/DatabaseContainerExecutor.java#L123

Cool thanks @rnorth ! Will tests as soon as the next TC version is released!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lovepoem picture lovepoem  ·  3Comments

denis-zhdanov picture denis-zhdanov  ·  3Comments

oneiros-de picture oneiros-de  ·  3Comments

dabraham02124 picture dabraham02124  ·  3Comments

McKratt picture McKratt  ·  4Comments