簡體   English   中英

僅在首次運行時從 Node 拒絕 MySQL 連接(docker-compose)

[英]MySQL connection refused from Node on first run only (docker-compose)

我正在嘗試構建 NodeJS/MySQL 堆棧,但遇到了間歇性問題。

這是我的 docker compose 文件:

version: '3'
services:
    db:
        image: mysql:5.7
        command: --default-authentication-plugin=mysql_native_password
        ports:
            - "3306:3306"
        environment:
            MYSQL_ROOT_PASSWORD: root
        container_name: 'db'
        networks:
            - db-network
        volumes:
            - db-data:/var/lib/mysql
            - ./db:/docker-entrypoint-initdb.d
    forum:
        image: "node:12"
        user: "node"
        working_dir: /home/node/app
        depends_on:
            - db
        ports:
            - 7000:3000
        environment:
          - NODE_ENV=development
          - PORT=3000
        volumes:
          - ./server:/home/node/app
        command: "npm start"
        networks:
            - db-network
    adminer:
        image: adminer
        restart: always
        networks:
            - db-network
        depends_on:
            - db
        ports:
          - 7777:8080
        environment:
          ADMINER_DEFAULT_DB_DRIVER: mysql
          ADMINER_DEFAULT_DB_HOST: db
volumes:
    db-data:
networks:
    db-network:

你可以看到我有一個映射到 initdb 入口點的 SQL 腳本。 這是一個非常簡單的 SQL,它只是創建了數據庫: CREATE DATABASE IF NOT EXISTS forum; ,則創建CREATE DATABASE IF NOT EXISTS forum;

在 Node 容器中,我使用 knex 與數據庫對話。 當我實例化 knex 時,我還會運行任何未完成的遷移:

const environment = process.env.ENVIRONMENT || 'development'
const Knex = require('knex');
const knexConfig = require('../knexfile');
const knex = Knex(knexConfig[environment]);

async function init() {
  try {
    return await knex.migrate.latest();
  } catch (error) {
    console.log(error);
  } finally {
    return;
  }
}

init();

module.exports = knex;

我遇到的問題只出現在 docker-compose 的“first up”上(或者更具體地說,當它需要創建 db-data 卷時)。 如果我降低音量docker-compose down -V我會在“up-ing”再次出現錯誤。 問題是你的經典 ECONNREFUSED:

Creating network "forum_db-network" with the default driver
Creating volume "forum_db-data" with default driver
Creating db ... done
Creating forum_adminer_1 ... done
Creating forum_forum_1   ... done
Attaching to db, forum_adminer_1, forum_forum_1
db         | Initializing database
db         | 2020-02-20T09:50:46.701629Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
db         | 2020-02-20T09:50:47.004757Z 0 [Warning] InnoDB: New log files created, LSN=45790
db         | 2020-02-20T09:50:47.062521Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
db         | 2020-02-20T09:50:47.122917Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 7810f3c2-53c6-11ea-ba00-0242c0a81002.
db         | 2020-02-20T09:50:47.126689Z 0 [Warning] Gtid table is not ready to be used. Table 'mysql.gtid_executed' cannot be opened.
adminer_1  | [Thu Feb 20 09:50:47 2020] PHP 7.4.2 Development Server (http://[::]:8080) started
db         | 2020-02-20T09:50:47.127637Z 1 [Warning] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
db         | 2020-02-20T09:50:47.955961Z 1 [Warning] 'user' entry 'root@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:47.956454Z 1 [Warning] 'user' entry 'mysql.session@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:47.957026Z 1 [Warning] 'user' entry 'mysql.sys@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:47.957747Z 1 [Warning] 'db' entry 'performance_schema mysql.session@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:47.958212Z 1 [Warning] 'db' entry 'sys mysql.sys@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:47.958797Z 1 [Warning] 'proxies_priv' entry '@ root@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:47.959520Z 1 [Warning] 'tables_priv' entry 'user mysql.session@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:47.960113Z 1 [Warning] 'tables_priv' entry 'sys_config mysql.sys@localhost' ignored in --skip-name-resolve mode.
forum_1    |
forum_1    | > express-oauth-vuex-starter@1.0.0 start /home/node/app
forum_1    | > nodemon index.js
forum_1    |
forum_1    | [nodemon] 2.0.2
forum_1    | [nodemon] to restart at any time, enter `rs`
forum_1    | [nodemon] watching dir(s): *.*
forum_1    | [nodemon] watching extensions: js,mjs,json
forum_1    | [nodemon] starting `node index.js`
db         | Database initialized
db         | Initializing certificates
db         | Generating a RSA private key
db         | ........................................................................................................................+++++
db         | ..........+++++
db         | unable to write 'random state'
db         | writing new private key to 'ca-key.pem'
db         | -----
db         | Generating a RSA private key
db         | .........................................................................................+++++
db         | .............+++++
db         | unable to write 'random state'
db         | writing new private key to 'server-key.pem'
db         | -----
db         | Generating a RSA private key
db         | .....................................................+++++
db         | .+++++
db         | unable to write 'random state'
db         | writing new private key to 'client-key.pem'
db         | -----
db         | Certificates initialized
db         | MySQL init process in progress...
db         | 2020-02-20T09:50:51.037907Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
db         | 2020-02-20T09:50:51.039423Z 0 [Note] mysqld (mysqld 5.7.24) starting as process 89 ...
db         | 2020-02-20T09:50:51.044545Z 0 [Note] InnoDB: PUNCH HOLE support available
db         | 2020-02-20T09:50:51.044653Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
db         | 2020-02-20T09:50:51.044701Z 0 [Note] InnoDB: Uses event mutexes
db         | 2020-02-20T09:50:51.044745Z 0 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
db         | 2020-02-20T09:50:51.044786Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
db         | 2020-02-20T09:50:51.044825Z 0 [Note] InnoDB: Using Linux native AIO
db         | 2020-02-20T09:50:51.045705Z 0 [Note] InnoDB: Number of pools: 1
db         | 2020-02-20T09:50:51.046113Z 0 [Note] InnoDB: Using CPU crc32 instructions
db         | 2020-02-20T09:50:51.048701Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
db         | 2020-02-20T09:50:51.060691Z 0 [Note] InnoDB: Completed initialization of buffer pool
db         | 2020-02-20T09:50:51.064263Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
db         | 2020-02-20T09:50:51.076676Z 0 [Note] InnoDB: Highest supported file format is Barracuda.
db         | 2020-02-20T09:50:51.097380Z 0 [Note] InnoDB: Creating shared tablespace for temporary tables
db         | 2020-02-20T09:50:51.097533Z 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
db         | 2020-02-20T09:50:51.131620Z 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
db         | 2020-02-20T09:50:51.134052Z 0 [Note] InnoDB: 96 redo rollback segment(s) found. 96 redo rollback segment(s) are active.
db         | 2020-02-20T09:50:51.134142Z 0 [Note] InnoDB: 32 non-redo rollback segment(s) are active.
db         | 2020-02-20T09:50:51.135177Z 0 [Note] InnoDB: Waiting for purge to start
db         | 2020-02-20T09:50:51.185530Z 0 [Note] InnoDB: 5.7.24 started; log sequence number 2591440
db         | 2020-02-20T09:50:51.186329Z 0 [Note] Plugin 'FEDERATED' is disabled.
db         | 2020-02-20T09:50:51.192075Z 0 [Note] Found ca.pem, server-cert.pem and server-key.pem in data directory. Trying to enable SSL support using them.
db         | 2020-02-20T09:50:51.192591Z 0 [Warning] CA certificate ca.pem is self signed.
db         | 2020-02-20T09:50:51.194602Z 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
db         | 2020-02-20T09:50:51.197793Z 0 [Note] InnoDB: Buffer pool(s) load completed at 200220  9:50:51
db         | 2020-02-20T09:50:51.198483Z 0 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
db         | 2020-02-20T09:50:51.200316Z 0 [Warning] 'user' entry 'root@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:51.200460Z 0 [Warning] 'user' entry 'mysql.session@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:51.200532Z 0 [Warning] 'user' entry 'mysql.sys@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:51.200606Z 0 [Warning] 'db' entry 'performance_schema mysql.session@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:51.200656Z 0 [Warning] 'db' entry 'sys mysql.sys@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:51.200717Z 0 [Warning] 'proxies_priv' entry '@ root@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:51.202731Z 0 [Warning] 'tables_priv' entry 'user mysql.session@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:51.202816Z 0 [Warning] 'tables_priv' entry 'sys_config mysql.sys@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:51.219832Z 0 [Note] Event Scheduler: Loaded 0 events
db         | 2020-02-20T09:50:51.221248Z 0 [Note] mysqld: ready for connections.
db         | Version: '5.7.24'  socket: '/var/run/mysqld/mysqld.sock'  port: 0  MySQL Community Server (GPL)
forum_1    | Listening...
forum_1    | Error: connect ECONNREFUSED 192.168.16.2:3306
forum_1    |     at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1137:16)
forum_1    |     at Protocol._enqueue (/home/node/app/node_modules/mysql/lib/protocol/Protocol.js:144:48)
forum_1    |     at Protocol.handshake (/home/node/app/node_modules/mysql/lib/protocol/Protocol.js:51:23)
forum_1    |     at Connection.connect (/home/node/app/node_modules/mysql/lib/Connection.js:116:18)
forum_1    |     at /home/node/app/node_modules/knex/lib/dialects/mysql/index.js:69:18
forum_1    | From previous event:
forum_1    |     at Client_MySQL.acquireRawConnection (/home/node/app/node_modules/knex/lib/dialects/mysql/index.js:64:12)
forum_1    |     at create (/home/node/app/node_modules/knex/lib/client.js:291:39)
forum_1    |     at processTicksAndRejections (internal/process/task_queues.js:97:5) {
forum_1    |   errno: 'ECONNREFUSED',
forum_1    |   code: 'ECONNREFUSED',
forum_1    |   syscall: 'connect',
forum_1    |   address: '192.168.16.2',
forum_1    |   port: 3306,
forum_1    |   fatal: true
forum_1    | }
db         | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
db         | Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it.
db         | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
db         | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
db         | 2020-02-20T09:50:54.889060Z 4 [Warning] 'user' entry 'root@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:54.889116Z 4 [Warning] 'user' entry 'mysql.session@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:54.889137Z 4 [Warning] 'user' entry 'mysql.sys@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:54.889164Z 4 [Warning] 'db' entry 'performance_schema mysql.session@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:54.889172Z 4 [Warning] 'db' entry 'sys mysql.sys@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:54.889188Z 4 [Warning] 'proxies_priv' entry '@ root@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:54.890011Z 4 [Warning] 'tables_priv' entry 'user mysql.session@localhost' ignored in --skip-name-resolve mode.
db         | 2020-02-20T09:50:54.890057Z 4 [Warning] 'tables_priv' entry 'sys_config mysql.sys@localhost' ignored in --skip-name-resolve mode.
db         |
db         | /usr/local/bin/docker-entrypoint.sh: running /docker-entrypoint-initdb.d/init.sql
db         | mysql: [Warning] Using a password on the command line interface can be insecure.
db         |
db         |
db         | 2020-02-20T09:50:54.915362Z 0 [Note] Giving 0 client threads a chance to die gracefully
db         | 2020-02-20T09:50:54.915705Z 0 [Note] Shutting down slave threads
db         | 2020-02-20T09:50:54.916456Z 0 [Note] Forcefully disconnecting 0 remaining clients
db         | 2020-02-20T09:50:54.917013Z 0 [Note] Event Scheduler: Purging the queue. 0 events
db         | 2020-02-20T09:50:54.917696Z 0 [Note] Binlog end
db         | 2020-02-20T09:50:54.918665Z 0 [Note] Shutting down plugin 'ngram'
db         | 2020-02-20T09:50:54.919138Z 0 [Note] Shutting down plugin 'partition'
db         | 2020-02-20T09:50:54.919357Z 0 [Note] Shutting down plugin 'BLACKHOLE'
db         | 2020-02-20T09:50:54.920107Z 0 [Note] Shutting down plugin 'ARCHIVE'
db         | 2020-02-20T09:50:54.920322Z 0 [Note] Shutting down plugin 'PERFORMANCE_SCHEMA'
db         | 2020-02-20T09:50:54.921325Z 0 [Note] Shutting down plugin 'MRG_MYISAM'
db         | 2020-02-20T09:50:54.921840Z 0 [Note] Shutting down plugin 'MyISAM'
db         | 2020-02-20T09:50:54.922751Z 0 [Note] Shutting down plugin 'INNODB_SYS_VIRTUAL'
db         | 2020-02-20T09:50:54.923300Z 0 [Note] Shutting down plugin 'INNODB_SYS_DATAFILES'
db         | 2020-02-20T09:50:54.923360Z 0 [Note] Shutting down plugin 'INNODB_SYS_TABLESPACES'
db         | 2020-02-20T09:50:54.923589Z 0 [Note] Shutting down plugin 'INNODB_SYS_FOREIGN_COLS'
db         | 2020-02-20T09:50:54.923959Z 0 [Note] Shutting down plugin 'INNODB_SYS_FOREIGN'
db         | 2020-02-20T09:50:54.924112Z 0 [Note] Shutting down plugin 'INNODB_SYS_FIELDS'
db         | 2020-02-20T09:50:54.924269Z 0 [Note] Shutting down plugin 'INNODB_SYS_COLUMNS'
db         | 2020-02-20T09:50:54.924754Z 0 [Note] Shutting down plugin 'INNODB_SYS_INDEXES'
db         | 2020-02-20T09:50:54.925454Z 0 [Note] Shutting down plugin 'INNODB_SYS_TABLESTATS'
db         | 2020-02-20T09:50:54.925535Z 0 [Note] Shutting down plugin 'INNODB_SYS_TABLES'
db         | 2020-02-20T09:50:54.925688Z 0 [Note] Shutting down plugin 'INNODB_FT_INDEX_TABLE'
db         | 2020-02-20T09:50:54.925728Z 0 [Note] Shutting down plugin 'INNODB_FT_INDEX_CACHE'
db         | 2020-02-20T09:50:54.926261Z 0 [Note] Shutting down plugin 'INNODB_FT_CONFIG'
db         | 2020-02-20T09:50:54.926443Z 0 [Note] Shutting down plugin 'INNODB_FT_BEING_DELETED'
db         | 2020-02-20T09:50:54.926836Z 0 [Note] Shutting down plugin 'INNODB_FT_DELETED'
db         | 2020-02-20T09:50:54.927513Z 0 [Note] Shutting down plugin 'INNODB_FT_DEFAULT_STOPWORD'
db         | 2020-02-20T09:50:54.927560Z 0 [Note] Shutting down plugin 'INNODB_METRICS'
db         | 2020-02-20T09:50:54.927718Z 0 [Note] Shutting down plugin 'INNODB_TEMP_TABLE_INFO'
db         | 2020-02-20T09:50:54.927806Z 0 [Note] Shutting down plugin 'INNODB_BUFFER_POOL_STATS'
db         | 2020-02-20T09:50:54.927847Z 0 [Note] Shutting down plugin 'INNODB_BUFFER_PAGE_LRU'
db         | 2020-02-20T09:50:54.928201Z 0 [Note] Shutting down plugin 'INNODB_BUFFER_PAGE'
db         | 2020-02-20T09:50:54.928360Z 0 [Note] Shutting down plugin 'INNODB_CMP_PER_INDEX_RESET'
db         | 2020-02-20T09:50:54.928817Z 0 [Note] Shutting down plugin 'INNODB_CMP_PER_INDEX'
db         | 2020-02-20T09:50:54.929031Z 0 [Note] Shutting down plugin 'INNODB_CMPMEM_RESET'
db         | 2020-02-20T09:50:54.929717Z 0 [Note] Shutting down plugin 'INNODB_CMPMEM'
db         | 2020-02-20T09:50:54.929740Z 0 [Note] Shutting down plugin 'INNODB_CMP_RESET'
db         | 2020-02-20T09:50:54.929898Z 0 [Note] Shutting down plugin 'INNODB_CMP'
db         | 2020-02-20T09:50:54.929912Z 0 [Note] Shutting down plugin 'INNODB_LOCK_WAITS'
db         | 2020-02-20T09:50:54.930509Z 0 [Note] Shutting down plugin 'INNODB_LOCKS'
db         | 2020-02-20T09:50:54.930535Z 0 [Note] Shutting down plugin 'INNODB_TRX'
db         | 2020-02-20T09:50:54.930549Z 0 [Note] Shutting down plugin 'InnoDB'
db         | 2020-02-20T09:50:54.931131Z 0 [Note] InnoDB: FTS optimize thread exiting.
db         | 2020-02-20T09:50:54.931746Z 0 [Note] InnoDB: Starting shutdown...
db         | 2020-02-20T09:50:55.032188Z 0 [Note] InnoDB: Dumping buffer pool(s) to /var/lib/mysql/ib_buffer_pool
db         | 2020-02-20T09:50:55.032448Z 0 [Note] InnoDB: Buffer pool(s) dump completed at 200220  9:50:55

如果該卷已存在,則不會出現錯誤,knex 會連接並運行遷移。

在錯誤日志中可以看到Node容器在mysqld: ready for connections.之后直接啟動了mysqld: ready for connections. 但是,您可以看到在 Node 錯誤之后,db 容器會運行init.sql 大概這意味着 knex 試圖在特定數據庫存在之前連接到它,我猜這可能是連接被拒絕的原因。

所以我想我正在尋找一種方法來推遲節點容器的實例化,直到 MySQL 容器運行init.sql 我已經在使用depends_on compose 屬性——還有其他depends_on選項可供我使用嗎?

恐怕沒有我知道的本地解決方案。

為了等待服務一般可用,我使用了wait-for-it ,但在您的情況下,您需要一些東西來驗證 MySQL 還包含您的應用程序所需的數據庫。

也許是一個簡單的 Node 腳本,它循環連接並嘗試在正確運行應用程序之前選擇數據庫。

最后我通過為 MySQL 容器設置 MYSQL_DATABASE 環境變量解決了這個問題。 MySQL 圖像文檔

MYSQL_DATABASE
此變量是可選的,允許您指定要在映像啟動時創建的數據庫的名稱。 如果提供了用戶/密碼(見下文),則該用戶將被授予對該數據庫的超級用戶訪問權限(對應於 GRANT ALL)

db:
    image: mysql:5.7
    command: --default-authentication-plugin=mysql_native_password
    ports:
        - "3306:3306"
    environment:
        MYSQL_DATABASE: forum
        MYSQL_ROOT_PASSWORD: root
    container_name: 'db'
    networks:
        - db-network
    volumes:
        - db-data:/var/lib/mysql

除此之外,我使用is-port-reachable來保持初始遷移,直到 MySQL 容器可用。

const isPortReachable = require('is-port-reachable');
const environment = process.env.ENVIRONMENT || 'development'
const Knex = require('knex');
const knexConfig = require('../knexfile');
const knex = Knex(knexConfig[environment]);

async function init() {
  let dbStatus = false;

  while (!dbStatus) {
    dbStatus = await isPortReachable(knexConfig[environment].connection.port, {host: knexConfig[environment].connection.host});
  }

  try {
    return await knex.migrate.latest();
  } catch (error) {
    console.log(error);
  }
}

init();

module.exports = knex;

更新

雖然上述確實解決了這個特定問題,但還有大量其他問題不斷出現 - 所有這些都與 MySQL 配置有關。 最后,我玩膩了打地鼠游戲,轉而使用 Postgres(感謝 Knex,非常簡單)。 跨度圖像,一切都只是工作...

如果您在使用 docker-compose、knex 和 mysql 時遇到問題,我的建議是只使用 Postgres

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM