Docker (docker -compose) узел + MySQL: ECONNREFUSED - PullRequest
0 голосов
/ 31 января 2020

У меня есть файл docker -compose.yml, в котором запущены три контейнера. Моя проблема в том, что когда я запускаю свои контейнеры, мне кажется, что мой контейнер узла (api) запускается раньше, чем мой MySQL контейнер, даже если я объявляю зависящий_он от моего docker -compose.yml, выдавая следующую ошибку:

error connecting: Error: connect ECONNREFUSED xxx.xx.x.x:3306
at TCPConnectWrap.afterConnect [as oncomplete]

После того, как я получил эту ошибку, я вижу в своей консоли, что контейнер MySQL только запускается. Моя база данных в порядке, я могу получить к ней доступ без проблем. Если я внесу некоторые изменения в мой код nodejs, то это заставит мой сервер узлов переосмыслить sh, и когда сервер снова включится, у меня не возникнет проблем с подключением, поскольку контейнер MySQL уже запущен.

Я даже пытался использовать решения в качестве ожидающего решения. sh (https://github.com/vishnubob/wait-for-it/blob/master/wait-for-it.sh), но результат был таким же, серверная часть моего узла пытается сделать mysql соединение, но контейнер mysql не готов.

Это мой docker -compose.yml

version: "3"
services:
    mysql:
        image: my_mysql
        build: ./db
        restart: always
        container_name: my_mysql
        volumes:
            - /var/lib/mysql
            - ./db:/db
        ports:
            - "3307:3306"
        environment:
            - MYSQL_ROOT_PASSWORD=x 
            - MYSQL_USER=x
            - MYSQL_PASSWORD=x
            - MYSQL_DATABASE=x
        networks: 
            - my_network
        command: --default-authentication-plugin=mysql_native_password
    api:
        container_name: my_api
        build: ./api
        restart: always
        ports:
            - "9000:9000"
        environment:
            DB_HOSTNAME: mysql    
        working_dir: /api
        volumes:
            - ./api:/api
        depends_on: 
            - mysql
        networks:
            - my_network
    client:
        container_name: my_client
        image: mhart/alpine-node:12
        build: ./client
        restart: always
        ports:
            - "3000:3000"
        working_dir: /client
        volumes:
            - ./client:/client
        entrypoint: ["npm", "start"]
        depends_on: 
            - api
        networks: 
            - my_network
networks:
    my_network:
        driver: bridge

Dockerfile для моего nodejs бэкэнда:

FROM mhart/alpine-node:12
WORKDIR /api
COPY package*.json /api/
RUN npm i -G nodemon
RUN npm install
COPY . /api/
EXPOSE 9000
CMD ["npm", "run", "dev"]

Dockerfile для моего фронта реакции:

FROM mhart/alpine-node:12
WORKDIR /client
COPY package*.json /client/
RUN npm install
COPY . /client/
EXPOSE 3000
CMD ["npm", "start"]

и Dockerfile для mysql:

FROM mysql:8.0.19

Вызов mysql соединения в nodejs:

const config = require('config');
const express = require('express');
const router = express.Router();
const mysql = require('mysql');

const connection = mysql.createConnection({
  host     : config.get('mysql.config.host'),
  user     : config.get('mysql.config.user'),
  password : config.get('mysql.config.password'),
  database : config.get('mysql.config.database'),
  port     : config.get('mysql.config.port')
});

connection.connect(function(err) {
  if (err) {
    console.error('error connecting: ' + err.stack);
    return;
  }
  console.log('connected  as id ' + connection.threadId);
});

router.get("/", function(req, res, next) {

  connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
    if (error) {
      throw error;
    }
    res.send(`MySQL OK: ${results[0].solution}`);
  });

});

module.exports = router;

Спасибо за любую помощь.

1 Ответ

0 голосов
/ 31 января 2020

Я не смог протестировать его, но рекомендация docker состоит в том, чтобы создать сценарий для ожидания подключения другого контейнера.

В качестве альтернативы, вы можете написать собственный скрипт-обертку для выполнения большего количества приложений. -specifi c проверка здоровья. Например, вы можете подождать, пока Postgres определенно не будет готов к приему команд:

#!/bin/sh
# wait-for-postgres.sh

set -e

host="$1"
shift
cmd="$@"

until PGPASSWORD=$POSTGRES_PASSWORD psql -h "$host" -U "postgres" -c '\q'; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

>&2 echo "Postgres is up - executing command"
exec $cmd

Вы можете проверить документацию здесь: Управление порядком запуска и выключения в Compose

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...