この質問に重複のフラグを立てる前に、他の回答を読みましたが、問題は解決しなかったことに注意してください。
2つのサービスで構成されるDocker作成ファイルがあります。
version: "3"
services:
mysql:
image: mysql:5.7
environment:
MYSQL_Host: localhost
MYSQL_DATABASE: mydb
MYSQL_USER: mysql
MYSQL_PASSWORD: 1234
MYSQL_ROOT_PASSWORD: root
ports:
- "3307:3306"
expose:
- 3307
volumes:
- /var/lib/mysql
- ./mysql/migrations:/docker-entrypoint-initdb.d
restart: unless-stopped
web:
build:
context: .
dockerfile: web/Dockerfile
volumes:
- ./:/web
ports:
- "3000:3000"
environment:
NODE_ENV: development
PORT: 3000
links:
- mysql:mysql
depends_on:
- mysql
expose:
- 3000
command: ["./wait-for-it.sh", "mysql:3307"]
/ web/Dockerfile:
FROM node:6.11.1
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install
COPY . /usr/src/app
CMD [ "npm", "start" ]
docker-compose up --build
の後、サービスが起動しますが、 "wait-for-it.sh" スクリプトは、mySQLの起動を待機しているときにタイムアウトします(したがって、DBのテスト時に一時的に使用していません)接続、MySQLが着信接続を受け入れる準備ができていることをコンソールが示すまで待つだけです)
MySQLがホストマシンから実行されている場合、Sequel Proを使用してログインし、DBにクエリを実行して、./mysql/migrations
からサンプルレコードを取得できます。
実行中のMySQLコンテナにSSHで接続して、同じことを行うこともできます。
ただし、Node.jsアプリは、接続時にECONNREFUSED 127.0.0.1:3307
を生成します
MySQL init:
import * as mysql from 'promise-mysql'
const config = {
Host: 'localhost',
database: 'mydb',
port: '3307',
user: 'mysql',
password: '1234',
connectionLimit: 10
}
export let db = mysql.createPool(config);
MySQLクエリ:
import { db } from '../db/client'
export let get = () => {
return db.query('SELECT * FROM users', [])
.then((results) => {
return results
})
.catch((e) => {
return Promise.reject(e)
})
}
URL /を押すと呼び出されるルート
import { Router } from 'express';
import * as repository from '../repository'
export let router = Router();
router.get('/', async (req, res) => {
let users;
try{
users = await repository.users.get();
} catch(e){
// ECONNREFUSED 127.0.0.1:3307
}
res.render('index', {
users: users
});
});
Node.jsが失敗すると同時に、Sequel ProまたはSSHを使用して実行中のDockerコンテナーにクエリを実行し、クエリを実行できるため、競合状態になる可能性はほとんどありません。では、Node.jsがMySQLコンテナにアクセスできない場合でしょうか?
{
error: connect ECONNREFUSED 127.0.0.1:3307
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 3307,
fatal: true
}
この:
mysql:
image: mysql:5.7
environment:
...
ports:
- "3307:3306"
Dockerがホストの3307
ポートをコンテナーの3306
ポートにマップすることを意味します。したがって、Sequelからlocalhost:3307
にアクセスできます。
ただし、コンテナが3307
をリッスンしているという意味ではありません。実際、コンテナはまだ3306
をリッスンしています。他のコンテナがmysql
DNSにアクセスしようとすると、内部コンテナIPに変換されるため、3306
に接続する必要があります。
したがって、ノード構成は次のようになります。
const config = {
Host: 'mysql',
database: 'mydb',
port: '3306',
user: 'mysql',
password: '1234',
connectionLimit: 10
}
そしてこれはあなたのdocker-compose.ymlにあります:
command: ["./wait-for-it.sh", "mysql:3306"]