[mysql] Docker-compose mysql 연결이 준비되었는지 확인

내 앱 컨테이너가 db 컨테이너가 시작되고 연결을 수락 할 준비가 될 때까지 마이그레이션 / 시작을 실행하지 않는지 확인하려고합니다.

그래서 나는 healthcheck를 사용하기로 결정했고 docker compose file v2의 옵션에 따라 달라집니다.

앱에는 다음이 있습니다.

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

반면에 db에는 다음과 같은 상태 검사가 있습니다.

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

다음과 같은 몇 가지 접근 방식을 시도했습니다.

  1. db DIR이 생성되었는지 확인

    test: ["CMD", "test -f var/lib/mysql/db"]
  2. mysql 버전 얻기 :

    test: ["CMD", "echo 'SELECT version();'| mysql"]
  3. 관리자 핑 (db 컨테이너를 정상으로 표시하지만 유효한 테스트가 아닌 것 같음)

    test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]

누구든지 이것에 대한 해결책이 있습니까?



답변

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

api 컨테이너는 db 컨테이너가 정상이 될 때까지 시작되지 않습니다 (기본적으로 mysqladmin이 실행되고 연결을 수락 할 때까지).


답변

docker-compose v3 +condition사용하는 경우의 옵션 depends_on제거되었습니다 .

권장되는 경로가 아니라 사용하는 것입니다 wait-for-it, dockerize또는 wait-for. 당신에 docker-compose.yml파일로 명령을 변경 :

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

개인적 wait-for으로 Alpine 컨테이너에서 실행할 수 있기 때문에 선호합니다 ( sh호환성, 의존성 없음 bash). 단점은에 따라 다르 netcat므로 사용하기로 결정한 경우 netcat컨테이너에 설치 했는지 확인 하거나 다음과 같이 Dockerfile에 설치하십시오.

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

또한 건강한 HTTP 상태를 확인할 수 있도록 프로젝트를 분기wait-for 했습니다 (사용 wget). 그런 다음 다음과 같이 할 수 있습니다.

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

추신 : PR은 또한 해당 용량을 wait-for프로젝트 에 추가하기 위해 병합 할 준비 가되었습니다 .


답변

이 정도면 충분합니다

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


답변

mysql이 준비 될 때까지 기다리도록 컨테이너를 변경할 수 있다면 그렇게하십시오.

데이터베이스를 연결하려는 컨테이너를 제어 할 수없는 경우 특정 포트를 기다릴 수 있습니다.

이를 위해 다른 컨테이너에 의해 노출 된 특정 포트를 기다리는 작은 스크립트를 사용하고 있습니다.

이 예에서 myservermydb 컨테이너 의 포트 3306 에 도달 할 수 있을 때까지 기다립니다 .

# 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

여기 에서 스크립트 wait-for-it 문서를 찾을 수 있습니다.


답변

docker-compose v2.1 사용하여 간단한 상태 확인을 위해 안녕하세요 .

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

기본적으로 데이터베이스 에서 암호 를 가진 사용자 를 예로 사용하여 간단한 mysql명령 SHOW DATABASES;을 실행 합니다.rootrootpasswd

명령이 성공하면 db가 가동되어 상태 확인 경로가 준비됩니다. interval간격으로 테스트하도록 사용할 수 있습니다 .

가시성을 위해 다른 필드를 제거하면 docker-compose.yaml.

version: '2.1'

  services:
    db:
      ... # Other db configuration (image, port, volumes, ...)
      healthcheck:
        test: "/usr/bin/mysql --user=root --password=rootpasswd --execute \"SHOW DATABASES;\""
        interval: 2s
        timeout: 20s
        retries: 10

     app:
       ... # Other app configuration
       depends_on:
         db:
         condition: service_healthy


답변

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

제 경우 ../schemaAndSeedData에는 여러 스키마 및 데이터 시드 SQL 파일이 포함되어 있습니다. Design your own check script다음과 유사 할 수 있습니다 select * from LastSchema.LastDBInsert.

웹 종속 컨테이너 코드가

depends_on:
  mysql:
    condition: service_healthy


답변

나는 똑같은 문제가 있었고이 목적을 위해 외부 bash 스크립트를 만들었습니다 (Maxim 대답에서 영감을 얻었습니다). 교체 mysql-container-name도 비밀번호 / 사용자가 필요 MySQL의 컨테이너의 이름 :

bin / wait-for-mysql.sh :

#!/bin/sh
until docker container exec -it mysql-container-name mysqladmin ping -P 3306 -proot | grep "mysqld is alive" ; do
  >&2 echo "MySQL is unavailable - waiting for it... ?"
  sleep 1
done

내 MakeFile에서이 스크립트는 docker-compose up call 를 호출합니다.

wait-for-mysql: ## Wait for MySQL to be ready
    bin/wait-for-mysql.sh

run: up wait-for-mysql reload serve ## Start everything...

그런 다음 오류없이 다른 명령을 호출 할 수 있습니다.

드라이버에서 예외가 발생했습니다. SQLSTATE [HY000] [2006] MySQL 서버가 사라졌습니다.

출력 예 :

docker-compose -f docker-compose.yaml up -d
Creating network "strangebuzzcom_default" with the default driver
Creating sb-elasticsearch ... done
Creating sb-redis              ... done
Creating sb-db                 ... done
Creating sb-app                ... done
Creating sb-kibana             ... done
Creating sb-elasticsearch-head ... done
Creating sb-adminer            ... done
bin/wait-for-mysql.sh
MySQL is unavailable - waiting for it... ?
MySQL is unavailable - waiting for it... ?
MySQL is unavailable - waiting for it... ?
MySQL is unavailable - waiting for it... ?
MySQL is unavailable - waiting for it... ?
MySQL is unavailable - waiting for it... ?
MySQL is unavailable - waiting for it... ?
MySQL is unavailable - waiting for it... ?
mysqld is alive
php bin/console doctrine:cache:clear-metadata
// Clearing all Metadata cache entries
[OK] Successfully deleted cache entries.

이 접근 방식에서는 이제 쓸모가 없으므로 상태 확인을 삭제했습니다.