CircleCI 作业创建 docker MySQL 8 但无法连接

CircleCI job creates docker MySQL 8 but nothing can connect

(请参阅 post 末尾的更新以获得可能有用的调试信息。)

我有一个通过 - setup_remote_docker+docker-compose 部署 MySQL 8 的 CircleCI 作业,然后尝试启动 Java 应用程序与 MySQL 通信8. 不幸的是,即使 docker ps 显示容器已启动并且 运行ning,任何与 MySQL 通信的尝试——无论是通过 Java 应用程序还是 docker exec--失败,表示容器不是 运行ning(并且 Java 抛出“通信 Link 失败”异常)。这有点令人困惑,因为容器似乎已启动,并且完全相同的命令在我的本地计算机上运行。

这是我的 CircleCI config.yml:

  Build and Test:
    <<: *configure_machine
    steps:
      - *load_repo
      - ... other unrelated stuff ...
      - *load_gradle_wrapper
      - run:
          name: Install Docker Compose
          environment:
            COMPOSE_VERSION: '1.29.2'
          command: |
            curl -L "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o ~/docker-compose
            chmod +x ~/docker-compose
            sudo mv ~/docker-compose /usr/local/bin/docker-compose
      - setup_remote_docker
      - run:
          name: Start MySQL docker
          command: docker-compose up -d
      - run:
          name: Check Docker MySQL
          command: docker ps
      - run:
          name: Query MySQL #test that fails
          command: docker exec -it mysql8_test_mysql mysql mysql -h 127.0.0.1 --port 3306 -u root -prootpass -e "show databases;"

这是我的 docker-compose.yml,其中一个步骤是 运行:

version: "3.1"

services:
  # MySQL Dev Image
  mysql-migrate:
    container_name: mysql8_test_mysql
    image: mysql:8.0
    command:
      mysqld --default-authentication-plugin=mysql_native_password
      --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
      --log-bin-trust-function-creators=true
    environment:
      MYSQL_DATABASE: test_db
      MYSQL_ROOT_PASSWORD: rootpass
    ports:
      - "3306:3306"
    volumes:
      - "./docker/mysql/data:/var/lib/mysql"
      - "./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf"
      - "./mysql_schema_v1.sql:/docker-entrypoint-initdb.d/mysql_schema_v1.sql"

这是一个相当简单的设置,CircleCI 的输出是正的 ,直到 它到达 docker exec,我添加它来测试连接。这是 CircleCI 每一步的输出:

Start MySQL Docker:

#!/bin/bash -eo pipefail
docker-compose up -d

Creating network "project_default" with the default driver
Pulling mysql-migrate (mysql:8.0)...
8.0: Pulling from library/mysql

5158dd02: Pulling fs layer
f6778b18: Pulling fs layer
a6c74a04: Pulling fs layer
4028a805: Pulling fs layer
7163f0f6: Pulling fs layer
cb7f57e0: Pulling fs layer
7a431703: Pulling fs layer
5fe86aaf: Pulling fs layer
add93486: Pulling fs layer
960383f3: Pulling fs layer
80965951: Pulling fs layer
Digest: sha256:b17a66b49277a68066559416cf44a185cfee538d0e16b5624781019bc716c122    121B/121BkBBB
Status: Downloaded newer image for mysql:8.0
Creating mysql8_******_mysql ... 
Creating mysql8_******_mysql ... done

所以我们知道 MySQL 8 被拉得很好(因此上一步有效)。下一步是询问 Docker 什么是 运行ning.

Check Docker MySQL:

#!/bin/bash -eo pipefail
docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                  PORTS                               NAMES
cb6b7941ad65        mysql:8.0           "docker-entrypoint.s…"   1 second ago        Up Less than a second   0.0.0.0:3306->3306/tcp, 33060/tcp   mysql8_test_mysql

CircleCI received exit code 0

到目前为止看起来还不错。但是现在让我们实际尝试通过 docker exec.

运行 一个针对它的命令

Query MySQL:

#!/bin/bash -eo pipefail
docker exec -it mysql8_test_mysql mysql mysql -h 127.0.0.1 --port 3306 -u root -prootpass -e "show databases;"

ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1:3306' (111)

Exited with code exit status 1

CircleCI received exit code 1

所以现在我们无法连接到 MySQL,即使 docker ps 显示它并 运行ning。我什至尝试添加一个荒谬的步骤来等待,以防 MySQL 需要更多时间:

      - run:
          name: Start MySQL docker
          command: docker-compose up -d
      - run:
          name: Check Docker MySQL
          command: docker ps
      - run:
          name: Wait Until Ready
          command: sleep 120
      - run:
          name: Query MySQL
          command: docker exec -it mysql8_test_mysql mysql mysql -h 127.0.0.1 --port 3306 -u root -prootpass -e "show databases;"

当然,增加 2 分钟等待 MySQL 启动并没有帮助。关于为什么这在 CircleCI 中如此困难有什么想法吗?

提前致谢。

更新 1:我可以成功启动 MySQL 如果我 SSH 进入作业的服务器并且 运行 我自己执行相同的命令:

docker-compose up

然后在另一个终端运行这个:

docker exec -it mysql8_test_mysql mysql mysql -h localhost --port 3306 -u root -prootpass -e "show databases;"

+--------------------+
| Database           |
+--------------------+
| information_schema |
| test_db            |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

所以可以开始MySQL。只是在完成工作步骤时无法正常工作。

更新 2:我在 docker-compose up -ddocker psnow 之间移动了两分钟的等待没有什么是 运行ning。因此容器必须启动然后崩溃,这就是为什么稍后它不可用的原因。

问题的原因是我的 docker-compose.yml 中的 volumes 条目包含以下行:

 - "./mysql_schema_v1.sql:/docker-entrypoint-initdb.d/mysql_schema_v1.sql"

当我在 docker-compose up -d 之后立即检查时,容器似乎启动了,但实际上它会在几秒钟后崩溃,因为 CircleCI 似乎有 Docker 卷的问题,可能与此有关:https://discuss.circleci.com/t/docker-compose-doesnt-mount-volumes-with-host-files-with-circle-ci/19099.

为了使其正常工作,我删除了 volume 条目并添加了 运行 命令来复制和导入架构,如下所示:

      - run:
          name: Start MySQL docker
          command: docker-compose up -d
      # Manually copy schema file instead of using docker-compose volumes (has issues with CircleCI)
      - run:
          name: Copy Schema
          command: docker cp mysql_schema_v1.sql mysql8_mobile_mysql:docker-entrypoint-initdb.d/mysql_schema_v1.sql
      - run:
          name: Import Schema
          command: docker exec mysql8_mobile_mysql /bin/sh -c 'mysql -u root -prootpass < docker-entrypoint-initdb.d/mysql_schema_v1.sql'

通过这个新设置,我已经能够创建表并连接到 MySQL。但是,运行ning 测试 MySQL 似乎有一个问题导致挂断,但这可能无关紧要。我会跟进更多信息,但至少我希望这可以帮助其他人。