Docker-compose 检查 mysql 连接是否准备就绪

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42567475/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 22:14:42  来源:igfitidea点击:

Docker-compose check if mysql connection is ready

mysqldockerdocker-composedockerfile

提问by John Kariuki

I am trying to make sure that my app container does not run migrations / start until the db container is started and READY TO accept connections.

我试图确保我的应用程序容器在 db 容器启动并准备接受连接之前不会运行迁移/启动。

So I decided to use the healthcheck and depends on option in docker compose file v2.

所以我决定使用健康检查并依赖于 docker compose 文件 v2 中的选项。

In the app, I have the following

在应用程序中,我有以下内容

app:
    ...
    depends_on:
      db:
      condition: service_healthy

The db on the other hand has the following healthcheck

另一方面,数据库具有以下健康检查

db:
  ...
  healthcheck:
    test: TEST_GOES_HERE
    timeout: 20s
    retries: 10

I have tried a couple of approaches like :

我尝试了几种方法,例如:

  1. making sure the db DIR is created test: ["CMD", "test -f var/lib/mysql/db"]
  2. Getting the mysql version: test: ["CMD", "echo 'SELECT version();'| mysql"]
  3. Ping the admin (marks the db container as healthy but does not seem to be a valid test) test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
  1. 确保创建了 db DIR test: ["CMD", "test -f var/lib/mysql/db"]
  2. 获取mysql版本: test: ["CMD", "echo 'SELECT version();'| mysql"]
  3. Ping 管理员(将 db 容器标记为健康,但似乎不是有效的测试) test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]

Does anyone have a solution to this?

有没有人有解决方案?

回答by John Kariuki

version: "2.1"
services:
    api:
        build: .
        container_name: api
        ports:
            - "8080:8080"
        depends_on:
            db:
                condition: service_healthy
    db:
        container_name: db
        image: mysql
        ports:
            - "3306"
        environment:
            MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
            MYSQL_USER: "user"
            MYSQL_PASSWORD: "password"
            MYSQL_DATABASE: "database"
        healthcheck:
            test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
            timeout: 20s
            retries: 10

The api container will not start until the db container is healthy (basically until mysqladmin is up and accepting connections.)

api 容器在 db 容器健康之前不会启动(基本上直到 mysqladmin 启动并接受连接。)

回答by Capripot

If you are using docker-compose v3+, conditionas an option of depends_onhas been removed.

如果您使用的是 docker-compose v3+condition作为 的选项depends_on已被删除

The recommended path is to use rather wait-for-it, dockerize, or wait-for. In your docker-compose.ymlfile, change your command to be:

推荐的路径是使用wait-for-itdockerize、 或wait-for。在您的docker-compose.yml文件中,将您的命令更改为:

command: sh -c 'bin/wait-for db:3306 -- bundle exec rails s'

I personally prefer wait-forsince it can run in an Alpine container (shcompatible, no dependance on bash). Drawback is that it depends on netcat, so if you decide to use it, make sure you have netcatinstalled in the container, or install it in your Dockerfile, for example with:

我个人更喜欢wait-for它,因为它可以在 Alpine 容器中运行(sh兼容,不依赖于bash)。缺点是它依赖于netcat,所以如果你决定使用它,请确保你已经netcat安装在容器中,或者将它安装在你的 Dockerfile 中,例如:

RUN apt-get -q update && apt-get -qy install netcat

I also forked the wait-forproject so it can check for healthy HTTP status (it uses wget). Then you can do something like that:

我还分叉了该wait-for项目,以便它可以检查健康的 HTTP 状态(它使用wget)。然后你可以做这样的事情:

command: sh -c 'bin/wait-for http://api/ping -- jest test'

PS: A PR is also readyto be merged to add that capacity to wait-forproject.

PS:PR 也已准备好合并以将该容量添加到wait-for项目中。

回答by Maksim Kostromin

This should be enough

这应该足够了

version: '2.1'
services:
  mysql:
    image: mysql
    ports: ['3306:3306']
    environment:
      MYSQL_USER: myuser
      MYSQL_PASSWORD: mypassword
    healthcheck:
      test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD

回答by nono

If you can change the container to wait for mysql to be ready do it.

如果您可以更改容器以等待 mysql 准备就绪,请执行此操作。

If you don't have the control of the container that you want to connect the database to, you can try to wait for the specific port.

如果您没有要连接数据库的容器的控制权,您可以尝试等待特定端口。

For that purpose, I'm using a small script to wait for a specific port exposed by another container.

为此,我使用了一个小脚本来等待另一个容器公开的特定端口。

In this example, myserverwill wait for port 3306of mydbcontainer to be reachable.

在这个例子中,MYSERVER将等待端口3306mydb的容器可到达。

# Your database
mydb:
  image: mysql
  ports:
    - "3306:3306"
  volumes:
    - yourDataDir:/var/lib/mysql

# Your server
myserver:
  image: myserver
  ports:
    - "....:...."
  entrypoint: ./wait-for-it.sh mydb:3306 -- ./yourEntryPoint.sh

You can find the script wait-for-it documentation here

您可以在此处找到脚本等待文档

回答by Sylhare

Hi for a simple healthcheck using docker-compose v2.1, I used:

嗨,使用docker-compose v2.1进行简单的健康检查,我使用了:

/usr/bin/mysql --user=root --password=rootpasswd --execute \"SHOW DATABASES;\"

Basically it runs a simple mysqlcommand SHOW DATABASES;using as an examplethe user rootwith the password rootpasswdin the database.

基本上,它运行的简单mysql命令SHOW DATABASES;使用,例如,用户root的密码rootpasswd在数据库中。

If the command succeed the db is up and ready so the healthcheck path. You can use intervalso it tests at interval.

如果命令成功,则数据库已启动并准备就绪,因此健康检查路径。您可以使用interval它进行间隔测试。

Removing the other field for visibility, here is what it would look like in your docker-compose.yaml.

删除另一个字段以获得可见性,这就是它在您的docker-compose.yaml.

version: '2.1'

  services:
    db:
      ...
      healthcheck:
        test: "/usr/bin/mysql --user=root --password=rootpasswd --execute \"SHOW DATABASES;\""
        interval: 2s
        timeout: 20s
        retries: 10

     app:
       ...
       depends_on:
         db:
         condition: service_healthy

回答by Mukesh Agarwal

I modified the docker-compose.ymlas per the following example and it worked.

docker-compose.yml按照以下示例修改了它并且它起作用了。

  mysql:
    image: mysql:5.6
    ports:
      - "3306:3306"
    volumes:       
      # Preload files for data
      - ../schemaAndSeedData:/docker-entrypoint-initdb.d
    environment:
      MYSQL_ROOT_PASSWORD: rootPass
      MYSQL_DATABASE: DefaultDB
      MYSQL_USER: usr
      MYSQL_PASSWORD: usr
    healthcheck:
      test:  mysql --user=root --password=rootPass -e 'Design your own check script ' LastSchema

In my case ../schemaAndSeedDatacontains multiple schema and data seeding sql files. Design your own check scriptcan be similar to following select * from LastSchema.LastDBInsert.

在我的例子中../schemaAndSeedData包含多个模式和数据播种 sql 文件。Design your own check script可以类似于以下select * from LastSchema.LastDBInsert

While web dependent container code was

虽然依赖于 Web 的容器代码是

depends_on:
  mysql:
    condition: service_healthy