ruby-on-rails - Rails容器无法使用gitlab ci连接到mysql容器

标签 ruby-on-rails docker gitlab-ci

我正在为具有构建,测试和发布阶段的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:

No connections until MySQL init completes

If there is no database initialized when the container starts, then a default database will be created. While this is the expected behavior, this means that it will not accept incoming connections until such initialization completes. This may cause issues when using automation tools, such as docker-compose, which start several containers simultaneously.

If the application you're trying to connect to MySQL does not handle MySQL downtime or waiting for MySQL to start gracefully, then a putting a connect-retry loop before the service starts might be necessary. For an example of such an implementation in the official images, see WordPress or Bonita.


从链接的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)。这种方法的缺点是数据库可能在真正准备好接受连接之前就正在侦听端口,因此我仍然建议您在重试循环中对应用程序进行完全登录。

关于ruby-on-rails - Rails容器无法使用gitlab ci连接到mysql容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53248189/

相关文章:

ruby-on-rails - 将图标添加到输入提交按钮

Centos7 上的 Docker : connection refused

amazon-web-services - Aws Batch 未登录到 Cloudwatch

docker - 错误 : In file './docker-compose.yml' , 服务 'volumes' 必须是映射而不是数组

gitlab - .gitlab-ci.yml 中的条件 after_script

gitlab - 即使值发生变化,如何保持Gitlab变量被屏蔽?

ruby-on-rails - 在运行时更改数据库连接

ruby-on-rails - 从 api 保存数据(但只保存一次)

ruby-on-rails - "Couldn' t 找到没有 ID 的 <object>”

linux - gitlab-CI 管道 : lftp error 550 when trying to delete files