我正在为具有构建,测试和发布阶段的Rails应用程序设置一个简单的gitlab ci:

build:
  stage: build
  script:
    - docker build --pull -t $TEST_IMAGE .
    - docker push $TEST_IMAGE

test:
  stage: test
  services:
    - docker:dind
  script:
    - docker pull $TEST_IMAGE
    - docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=mysql_strong_password mysql:5.7
    - docker run -e RAILS_ENV=test --link mysql:db $TEST_IMAGE bundle exec rake db:setup
build成功构建docker镜像并推送到注册表
test启动另一个我用作主机数据库的mysql容器,但是在建立与mysql的连接时失败。
Couldn't create database for {"host"=>"db", "adapter"=>"mysql2", "pool"=>5, "username"=>"root", "encoding"=>"utf8", "timeout"=>5000, "password"=>"mysql_strong_password", "database"=>"my_tests"}, {:charset=>"utf8"}
(If you set the charset manually, make sure you have a matching collation)
rails aborted!
Mysql2::Error: Can't connect to MySQL server on 'db' (111 "Connection refused")

我也尝试使用--network而不是link方法创建单独的docker网络,但没有帮助。

这仅在Gitlab运行程序实例上发生。当我在本地计算机上执行这些步骤时,它可以正常工作。

经过大量阅读后,我认为这是docker executor的错误。我想念什么吗?

最佳答案

拒绝连接表示容器知道如何相互访问,但是目标容器在所选端口上没有任何接受连接的对象。这很可能意味着您在数据库完成初始化之前就启动了应用程序。我的建议是更新/创建您的应用程序或在应用程序容器中创建一个入口点,以轮询数据库以使其启动并运行,如果几分钟后仍无法启动,则失败。我也建议使用网络而不是链接,因为不赞成使用链接,并且不能优雅地处理正在重新创建的容器。
您看到的行为是documented in the mysql image:

从链接的wordpress示例中,您可以看到其重试代码:

$maxTries = 10;
do {
    $mysql = new mysqli($host, $user, $pass, '', $port, $socket);
    if ($mysql->connect_error) {
        fwrite($stderr, "\n" . 'MySQL Connection Error: (' . $mysql->connect_errno . ') ' . $mysql->connect_error . "\n");
        --$maxTries;
        if ($maxTries <= 0) {
            exit(1);
        }
        sleep(3);
    }
} while ($mysql->connect_error);
在不更改应用程序本身的情况下等待mysql的示例入口点脚本如下所示:
#!/bin/sh
wait-for-it.sh mysql:3306 -t 300
exec "$@"
wait-for-it.sh来自vishnubob/wait-for-it,最后的exec "$@"用您传递的命令替换pid 1(例如bundle exec rake db:setup)。这种方法的缺点是数据库可能在真正准备好接受连接之前就正在侦听端口,因此我仍然建议您在重试循环中对应用程序进行完全登录。

08-28 02:50
查看更多