This is my docker-compose file:
version: '3.9'
services:
mysql:
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_DATABASE: 'admindb'
MYSQL_USER: 'admin'
MYSQL_PASSWORD: 'secretpassword'
MYSQL_ROOT_PASSWORD: 'someverysecretpassword'
ports:
- '3306:3306'
- '33060:33060'
volumes:
- ./db:/var/lib/mysql
networks:
- adminnet
app:
image: "node:latest"
depends_on:
- mysql
user: "node"
restart: unless-stopped
working_dir: /home/app
environment:
NODE_ENV: production
volumes:
- ${PWD}/../:/home/app
ports:
- '8081:8081'
command: "npm start"
networks:
- adminnet
volumes:
db:
data:
networks:
adminnet:
And this is my app.js:
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('admindb', 'admin', 'secretpassword', {
host: 'mysql',
port: 3306,
dialect: 'mysql',
});
sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
When I just run the MySQL container (so, if I remove the "app" instance from the docker-compose file) and replace host:'mysql'
with host:'127.0.0.1'
and run npm start
from my host machine, it is able to successfully connect to the database, which runs from the container.
But if I run app.js from a container, which should connect to the database inside the other container, it doesn't work. I use host:'mysql'
, but I keep getting the following error:
containers-app-1 | Unable to connect to the database: ConnectionError [SequelizeConnectionError]: connect ETIMEDOUT
containers-app-1 | at ConnectionManager.connect (/home/app/node_modules/sequelize/lib/dialects/mysql/connection-manager.js:102:17)
containers-app-1 | at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
containers-app-1 | at async ConnectionManager._connect (/home/app/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:220:24)
containers-app-1 | at async /home/app/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:174:32
containers-app-1 | at async ConnectionManager.getConnection (/home/app/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:197:7)
containers-app-1 | at async /home/app/node_modules/sequelize/lib/sequelize.js:301:26
containers-app-1 | at async Sequelize.authenticate (/home/app/node_modules/sequelize/lib/sequelize.js:453:5) {
containers-app-1 | parent: Error: connect ETIMEDOUT
containers-app-1 | at Connection._handleTimeoutError (/home/app/node_modules/mysql2/lib/connection.js:189:17)
containers-app-1 | at listOnTimeout (node:internal/timers:564:17)
containers-app-1 | at process.processTimers (node:internal/timers:507:7) {
containers-app-1 | errorno: 'ETIMEDOUT',
containers-app-1 | code: 'ETIMEDOUT',
containers-app-1 | syscall: 'connect',
containers-app-1 | fatal: true
containers-app-1 | },
containers-app-1 | original: Error: connect ETIMEDOUT
containers-app-1 | at Connection._handleTimeoutError (/home/app/node_modules/mysql2/lib/connection.js:189:17)
containers-app-1 | at listOnTimeout (node:internal/timers:564:17)
containers-app-1 | at process.processTimers (node:internal/timers:507:7) {
containers-app-1 | errorno: 'ETIMEDOUT',
containers-app-1 | code: 'ETIMEDOUT',
containers-app-1 | syscall: 'connect',
containers-app-1 | fatal: true
containers-app-1 | }
containers-app-1 | }
Something makes it impossible for the node-container to connect to the database inside the mysql-container. I tried to use ping from the node-container, but that package isn't available.
I read a ton of webpages and I'm debugging for the past few hours, without luck. Anyone who might know the issue? I already tried all similar StackOverflow questions and solutions, without any luck.
I tested your stack on my machine and I got it working successfully, after a second run. I ran it twice because of your depends_on
option (see my notes below).
Here's my machine specs:
Machine: MacBook Air (M1, 2020)
OS: macOS Monterey v12.4
Docker Version: 20.10.12 (installed with their .dmg)
Docker Compose Version: not used -- the latest version of docker includes it as a subcommand
I think this problem has multiple causes:
docker-compose.yml
file's depends_on
option. If you read the documentation on depends_on
, you'll see that your app
service DOES NOT wait for mysql
to be healthy before attempting a connection. You have to use the healthcheck
option if you want to make sure mysql
is healthy before connecting.