Docker-compose check if mysql connection is ready

后端 未结 9 2146
一个人的身影
一个人的身影 2020-11-27 13:40

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.

So I decided to use

9条回答
  •  半阙折子戏
    2020-11-27 13:57

    Adding an updated solution for the healthcheck approach. Simple snippet:

    healthcheck:
      test: out=$$(mysqladmin ping -h localhost -P 3306 -u foo --password=bar 2>&1); echo $$out | grep 'mysqld is alive' || { echo $$out; exit 1; }
    

    Explanation: Since mysqladmin ping returns false positives (especially for wrong password), I'm saving the output to a temporary variable, then using grep to find the expected output (mysqld is alive). If found it will return the 0 error code. In case it's not found, I'm printing the whole message, and returning the 1 error code.

    Extended snippet:

    version: "3.8"
    services:
      db:
        image: linuxserver/mariadb
        environment:
          - FILE__MYSQL_ROOT_PASSWORD=/run/secrets/mysql_root_password
          - FILE__MYSQL_PASSWORD=/run/secrets/mysql_password
        secrets:
          - mysql_root_password
          - mysql_password
        healthcheck:
          test: out=$$(mysqladmin ping -h localhost -P 3306 -u root --password=$$(cat $${FILE__MYSQL_ROOT_PASSWORD}) 2>&1); echo $$out | grep 'mysqld is alive' || { echo $$out; exit 1; }
    
    secrets:
      mysql_root_password:
        file: ${SECRETSDIR}/mysql_root_password
      mysql_password:
        file: ${SECRETSDIR}/mysql_password
    

    Explanation: I'm using docker secrets instead of env variables (but this can be achieved with regular env vars as well). The use of $$ is for literal $ sign which is stripped when passed to the container.

    Output from docker inspect --format "{{json .State.Health }}" db | jq on various occasions:

    Everything alright:

    {
      "Status": "healthy",
      "FailingStreak": 0,
      "Log": [
        {
        {
          "Start": "2020-07-20T01:03:02.326287492+03:00",
          "End": "2020-07-20T01:03:02.915911035+03:00",
          "ExitCode": 0,
          "Output": "mysqld is alive\n"
        }
      ]
    }
    

    DB is not up (yet):

    {
      "Status": "starting",
      "FailingStreak": 1,
      "Log": [
        {
          "Start": "2020-07-20T01:02:58.816483336+03:00",
          "End": "2020-07-20T01:02:59.401765146+03:00",
          "ExitCode": 1,
          "Output": "\u0007mysqladmin: connect to server at 'localhost' failed error: 'Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2 \"No such file or directory\")' Check that mysqld is running and that the socket: '/var/run/mysqld/mysqld.sock' exists!\n"
        }
      ]
    }
    

    Wrong password:

    {
      "Status": "unhealthy",
      "FailingStreak": 13,
      "Log": [
        {
          "Start": "2020-07-20T00:56:34.303714097+03:00",
          "End": "2020-07-20T00:56:34.845972979+03:00",
          "ExitCode": 1,
          "Output": "\u0007mysqladmin: connect to server at 'localhost' failed error: 'Access denied for user 'root'@'localhost' (using password: YES)'\n"
        }
      ]
    }
    

提交回复
热议问题