Gradle docker镜像无法连接到mysql testcontainer

时间:2020-01-03 14:40:26

标签: docker gradle testcontainers

我有一个使用MySQL Test容器的小型集成测试。

当我在本地构建时,运行简单的gradlew build命令,它将运行,测试并构建项目。但是,当我尝试使用正式的gradle docker映像时,该测试将暂停,以等待mysql数据库的可用性。

运行我的构建时,它将创建3个容器:

  • Gradle容器
  • quay.io/testcontainers/ryuk:0.2.3
  • mysql:latest

我的gradle映像不同于官方映像,因为它安装了docker:

FROM gradle
USER root
RUN apt-get update && \
    apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg2 \
    software-properties-common && \
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \
    apt-key fingerprint 0EBFCD88 && \
    add-apt-repository \
        "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
        $(lsb_release -cs) \
        stable" && \
    apt-get update && \
    apt-get install -y docker-ce docker-ce-cli containerd.io 

当连接停止时,我连接到了gradle映像,并安装了mysql客户端。我尝试连接到测试正在连接的同一映像,并且连接没有问题。 没有人知道我在做什么错,因为仅在容器中运行构建会出现此问题?

我用这个来跑

docker container run -v /var/run/docker.sock:/var/run/docker.sock -v <local repo>:/home/gradle/project -w /home/gradle/project --rm mygradle gradle build -i

编辑: 这不是因为gradle docker映像,而是任何映像。如果我使用Jenkins运行,并且它是一个容器,那么这也行不通。尝试连接到172.x.x.1(主机地址)和暴露的端口,并且测试未连接,但是访问容器,并使用mysql客户端尝试相同的完全连接,就可以连接。

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。

我没有使用MysqlContainer类,而是定义了一个扩展该类的新类。它将检测应用程序是否在容器内运行,如果是,它将尝试在内部连接到数据库容器,而不是使用localhost和生成的端口。

 public static class IntegrationTestsDatabase<SELF extends MySQLContainer<SELF>> extends MySQLContainer<SELF> {
    public IntegrationTestsDatabase() {
    }

    public IntegrationTestsDatabase(String dockerImageName) {
        super(dockerImageName);
    }

    public String getJdbcUrl() {
        String containerIp = ((ContainerNetwork)this.getContainerInfo().getNetworkSettings().getNetworks().values().stream().findFirst().get()).getIpAddress();
        return this.isRunningInsideDocker() ? "jdbc:mysql://" + containerIp + ":" + MySQLContainer.MYSQL_PORT + "/" + this.getDatabaseName() : super.getJdbcUrl();
    }

    public Boolean isRunningInsideDocker() {
        try {
            Stream stream = Files.lines(Paths.get("/proc/1/cgroup"));

            Boolean var2;
            try {
                var2 = stream.anyMatch((line) -> {
                    return line.contains("/docker");
                });
            } catch (Throwable var5) {
                if (stream != null) {
                    try {
                        stream.close();
                    } catch (Throwable var4) {
                        var5.addSuppressed(var4);
                    }
                }

                throw var5;
            }

            if (stream != null) {
                stream.close();
            }

            return var2;
        } catch (IOException var6) {
            return false;
        }
    }
}

这将与其他容器类型一起使用。