Connecting to MySQL with Ecto in Docker - mysql

I am in the process of Dockerizing my project, and the following is my docker-compose.yml:
version: '3.8'
services:
server:
image: server
environment:
DB_HOST: 0.0.0.0
DB_DATABASE: dev
DB_PORT: 3306
DB_USER: dev
DB_PASSWORD: dev
ports:
- "4000:4000"
restart: on-failure
depends_on:
database:
condition: service_started
database:
image: mysql:latest
command: --default-authentication-plugin=mysql_native_password
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: dev
MYSQL_PASSWORD: dev
MYSQL_DATABASE: dev
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
and the Dockerfile for server:
FROM elixir:latest
EXPOSE 4000
RUN mkdir /server
COPY . /server
WORKDIR /server
RUN mix local.rebar --force
RUN mix local.hex --force
RUN mix deps.get
RUN mix do compile
CMD [ "sh", "/server/entry.sh" ]
where entry.sh is:
# Exit on failure
set -e
mix ecto.create
mix ecto.migrate
mix run priv/repo/seeds.exs
exec mix phx.server
When I run this using docker compose up, I get an error that Phoenix can't connect to the MySQL database. I have tried using hosts 0.0.0.0 and localhost, however both don't work.
This is the corresponding section of my config/dev.exs:
config :app, App.Repo
username: System.get_env("DB_USER"),
password: System.get_env("DB_PASSWORD"),
hostname: System.get_env("DB_HOST"),
database: System.get_env("DB_DATABASE"),
port: 3306,
stacktrace: true,
pool_size: 10
The following is the exact error message I get:
server-1 | 11:23:07.417 [error] GenServer #PID<0.272.0> terminating
server-1 | ** (DBConnection.ConnectionError) (0.0.0.0:3306) connection refused - :econnrefused
server-1 | (db_connection 2.4.3) lib/db_connection/connection.ex:100: DBConnection.Connection.connect/2
server-1 | (connection 1.1.0) lib/connection.ex:622: Connection.enter_connect/5
server-1 | (stdlib 4.2) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
server-1 | Last message: nil
server-1 | State: MyXQL.Connection
server-1 |
server-1 | 11:23:07.430 [error] GenServer #PID<0.278.0> terminating
server-1 | ** (DBConnection.ConnectionError) (0.0.0.0:3306) connection refused - :econnrefused
server-1 | (db_connection 2.4.3) lib/db_connection/connection.ex:100: DBConnection.Connection.connect/2
server-1 | (connection 1.1.0) lib/connection.ex:622: Connection.enter_connect/5
server-1 | (stdlib 4.2) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
server-1 | Last message: nil
server-1 | State: MyXQL.Connection
server-1 | ** (Mix) The database for App.Repo couldn't be created: %RuntimeError{message: "killed"}
server-1 exited with code 1

Related

connect ECONNREFUSED 127.0.0.1:3306 with using jest in docker

I'm trying to use jest codes before deploy to dev. So i made docker-compose.yml and put "npm test (ENV=test jest --runInBand --forceExit test/**.test.ts -u)" but it has error.
This is my local.yml file (for docker-compose.yml)
version: "3"
services:
my-node:
image: my-api-server:dev
container_name: my_node
# sleep 10 sec for db init
command: bash -c "sleep 10; pwd; cd packages/server; yarn orm schema:sync -f ormconfig.dev.js; yarn db:migrate:run -f ormconfig.dev.js; npm test; cross-env ENV=dev node lib/server.js"
ports:
- "8082:8082"
depends_on:
- my-mysql
- my-redis
my-mysql:
image: mysql:5.7
container_name: my_mysql
command: --character-set-server=utf8mb4 --sql_mode="NO_ENGINE_SUBSTITUTION"
ports:
- "33079:3306"
volumes:
- ./init/:/docker-entrypoint-initdb.d/
environment:
- MYSQL_ROOT_PASSWORD=test
- MYSQL_DATABASE=test
- MYSQL_USER=test
- MYSQL_PASSWORD=test
my-redis:
image: redis:6.2-alpine
container_name: my_redis
ports:
- 6379:6379
command: redis-server --requirepass test
networks:
default:
external:
name: my_nginx_default
and it's my ormconfig.dev.js file
module.exports = {
type: 'mysql',
host: 'my_mysql',
port: 3306,
username: 'test',
password: 'test',
database: 'test',
entities: ['./src/modules/**/entities/*'],
migrations: ['migration/dev/*.ts'],
cli: { "migrationsDir": "migration/dev" }
}
But after i use docker-compose -f res/docker/local.yml up, it throws error after whole build and then jests. and then it opens server which does not have error.
Errors are like these below.
connect ECONNREFUSED 127.0.0.1:3306
and then
my_node | TypeError: Cannot read property 'subscriptionsPath' of undefined
my_node |
my_node | 116 | ): Promise<TestResponse<T>> => {
my_node | 117 | const req = request(server.app)
my_node | > 118 | .post(server.apolloServer!.subscriptionsPath!)
my_node | | ^
my_node | 119 | .set('Accept', 'application/json')
my_node | 120 |
my_node | 121 | if (token) {
I've tried to change entities path.
entities: ['./src/modules/**/entities/*']
entities: ['src/modules/**/entities/*']
entities: [__dirname + '/src/modules/**/entities/*']
My entities are in the right path.
Here is my whole file structure
Can anyone help this problem?
in your module.export host:my-mysql
Looking at the documentation, it could be an environment variable issue. As per the docs, the orm config file used is -
From the environment variables. Typeorm will attempt to load the .env file using dotEnv if it exists. If the environment variables TYPEORM_CONNECTION or TYPEORM_URL are set, Typeorm will use this method.
From the ormconfig.env.
From the other ormconfig.[format] files, in this order: [js, ts, json, yml, yaml, xml].
Since you have not defined the first two, it must be defaulting to use the ormconfig.js file. There is no reason it should pick ormconfig.dev.js.
If you can, change the ormconfig.js file to be this -
module.exports = {
type: 'mysql',
host: 'my_mysql',
port: 3306,
username: 'test',
password: 'test',
database: 'test',
entities: ['./src/modules/**/entities/*'],
migrations: ['migration/dev/*.ts'],
cli: { "migrationsDir": "migration/dev" }
}

Docker Compose getting error ECONNREFUSED 127.0.0.1:3306 with MySQL and NodeJS

I am trying to setup some containers for my NestJS + TypeORM + MySQL environment by using Docker Compose in a Windows 10 host, but I am getting an ECONNREFUSED error:
connect ECONNREFUSED 127.0.0.1:3306 +2ms
backend_1 | Error: connect ECONNREFUSED 127.0.0.1:3306
backend_1 | at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1145:16)
backend_1 | --------------------
backend_1 | at Protocol._enqueue (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:144:48)
backend_1 | at Protocol.handshake (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:51:23)
backend_1 | at PoolConnection.connect (/usr/src/app/node_modules/mysql/lib/Connection.js:116:18)
backend_1 | at Pool.getConnection (/usr/src/app/node_modules/mysql/lib/Pool.js:48:16)
backend_1 | at /usr/src/app/node_modules/typeorm/driver/mysql/MysqlDriver.js:793:18
backend_1 | at new Promise (<anonymous>)
backend_1 | at MysqlDriver.createPool (/usr/src/app/node_modules/typeorm/driver/mysql/MysqlDriver.js:790:16)
backend_1 | at MysqlDriver.<anonymous> (/usr/src/app/node_modules/typeorm/driver/mysql/MysqlDriver.js:278:51)
backend_1 | at step (/usr/src/app/node_modules/typeorm/node_modules/tslib/tslib.js:141:27)
backend_1 | at Object.next (/usr/src/app/node_modules/typeorm/node_modules/tslib/tslib.js:122:57)
I have created the following Dockerfile to configure the NestJS API container:
FROM node:12-alpine
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
EXPOSE 3000
#CMD ["npm", "start"]
CMD /wait-for-it.sh db:3306 -- npm start
COPY . .
And then I reference this from Docker Compose with the following docker-compose.yml:
version: "3.8"
networks:
app-tier:
driver: bridge
services:
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
expose:
- "3306"
ports:
- "3306:3306"
networks:
- app-tier
environment:
MYSQL_DATABASE: school
MYSQL_ALLOW_EMPTY_PASSWORD: ok
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: dbuser
MYSQL_PASSWORD: dbuser
MYSQL_ROOT_HOST: '%'
backend:
depends_on:
- db
build: .
ports:
- "3000:3000"
networks:
- app-tier
Finally, I set the TypeORM configuration to match with the Docker Compose file:
export const DB_CONFIG: TypeOrmModuleOptions = {
type: 'mysql',
host: 'db',
port: 3306,
username: 'dbuser',
password: 'dbuser',
database: 'school',
entities: [], // We specify the entities in the App Module.
synchronize: true,
};
I am kind of new to Docker Compose, but I have tried many things like changing the output port to 3307, setting an explicit network... and the port 3306 is free in my host OS when I run it. Any help?
Edit 1
I have included MYSQL_ROOT_HOST and wait-for-it.sh as suggested, but still no results.
I think your db is taking more time to start and your app is starting before the db, try something like this for your docker-compose.yml file:
version: "3.8"
networks:
app-tier:
driver: bridge
services:
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
expose:
- "3306"
ports:
- "3306:3306"
networks:
- app-tier
environment:
MYSQL_DATABASE: school
MYSQL_ALLOW_EMPTY_PASSWORD: ok
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: dbuser
MYSQL_PASSWORD: dbuser
MYSQL_ROOT_HOST: '%'
backend:
depends_on:
- db
build: .
command: bash -c 'while !</dev/tcp/db/3306; do sleep 1; done; npm start'
ports:
- "3000:3000"
networks:
- app-tier

Windows Docker Can't connect to local MySQL server through socket

I have a project on windows Docker, when I run the docker-compose up, it gives me the bellow error
php_1 | Database tma not reachable at host: localhost for user: drupal
php_1 | ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/run/mysqld/mysqld.sock' (2)
Here is the docker-compose.yml
version: "3"
services:
mariadb:
image: wodby/mariadb:$MARIADB_TAG
container_name: "${PROJECT_NAME}_mariadb"
stop_grace_period: 30s
environment:
MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
MYSQL_DATABASE: $DB_NAME
MYSQL_USER: $DB_USER
MYSQL_PASSWORD: $DB_PASSWORD
volumes:
- ./dev_tools/mariadb-init:/docker-entrypoint-initdb.d # Place init .sql file(s) here.
php:
image: wodby/drupal-php:$PHP_TAG
container_name: "${PROJECT_NAME}_php"
environment:
PHP_SENDMAIL_PATH: /usr/sbin/sendmail -t -i -S mailhog:1025
# PHP_SENDMAIL_PATH: /usr/sbin/sendmail -t -i -S opensmtpd:25
DB_HOST: $DB_HOST
DB_PORT: $DB_PORT
DB_USER: $DB_USER
DB_PASSWORD: $DB_PASSWORD
DB_NAME: $DB_NAME
DB_DRIVER: $DB_DRIVER
PHP_FPM_USER: wodby
PHP_FPM_GROUP: wodby
COLUMNS: 80 # Set 80 columns for docker exec -it.
volumes:
- ./:/var/www/html/
command: sh /var/www/html/dev_tools/php-entrypoint.bash
apache:
image: wodby/apache:$APACHE_TAG
container_name: "${PROJECT_NAME}_apache"
depends_on:
- php
environment:
APACHE_LOG_LEVEL: debug
APACHE_BACKEND_HOST: php
APACHE_VHOST_PRESET: php
APACHE_DOCUMENT_ROOT: /var/www/html/docroot
volumes:
- ./:/var/www/html
labels:
- "traefik.http.routers.${PROJECT_NAME}_apache.rule=Host(`${PROJECT_BASE_URL}`)"

Connect JavaScript running in docker container to MySQL database running on another docker container

I'm currently running a local instance of RocketChat and the RocketBot using docker-compose and a corresponding docker-compose.yaml file:
I use the standard mysql module like this:
var con = mysql.createConnection({
host: '<placeholder>',
user: 'root',
port: '3306',
password: '<placeholder>',
});
The host, user, port and password are gathered from running the inspect command on the container containing the MySQL server. The MySQL does work as I can run it and make changes to it and even connect to it using MySQL workbench. I get this error:
rosbot_1 | [Tue Jun 18 2019 18:42:06 GMT+0000 (UTC)] ERROR Error: connect ETIMEDOUT
rosbot_1 | at Connection._handleConnectTimeout (/home/hubot/node_modules/mysql/lib/Connection.js:412:13)
I have no idea how to proceed now, how can I connect from the bot served by docker-compose to the MySQL container using JavaScript?
EDIT:
docker-compose.yaml:
version: '2.1'
services:
mongo:
image: mongo:3.2
hostname: 'mongo'
volumes:
- ./db/data:/data/db
- ./db/dump:/dump
command: mongod --smallfiles --oplogSize 128 --replSet rs0
mongo-init-replica:
image: mongo:3.2
command: 'mongo mongo/rocketchat --eval "rs.initiate({ _id: ''rs0'', members: [ { _id: 0, host: ''localhost:27017'' } ]})"'
links:
- mongo:mongo
rocketchat:
image: rocketchat/rocket.chat:latest
hostname: 'rocketchat'
volumes:
- ./rocketchat/uploads:/app/uploads
environment:
- PORT=3000
- ROOT_URL=http://localhost:3000
- MONGO_URL=<placeholder>
- MONGO_OPLOG_URL=<placeholder>
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000"]
interval: 30s
timeout: 10s
retries: 5
links:
- mongo:mongo
ports:
- 3000:3000
<placeholder>:
image: <placeholder>
hostname: "<placeholder>"
environment:
- ROCKETCHAT_URL=<placeholder>
- ROCKETCHAT_ROOM=""
- ROCKETCHAT_USER=<placeholder>
- ROCKETCHAT_PASSWORD=<placeholder>
- ROCKETCHAT_AUTH=<placeholder>
- BOT_NAME=<placeholder>
- LISTEN_ON_ALL_PUBLIC=true
- EXTERNAL_SCRIPTS=hubot-help,hubot-seen,hubot-links,hubot-diagnostics,hubot-pugme,hubot-reload
- PENTEXT_PATH=/home/hubot/pentext
- ADDITIONAL_PACKAGES=mysql,lodash
- RESPOND_TO_LIVECHAT=true
- RESPOND_TO_DM=true
depends_on:
rocketchat:
condition: service_healthy
links:
- rocketchat:rocketchat
volumes:
- <placeholder>
ports:
- 3001:3001
Normally, you can connect to another container using the container name as hostname:
If you have a container with mysql, the container name (in this example 'db') is the host name to access the mysql container (also, you can use a hostname: 'mysqlhostname' to specify a different name):
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: mypass
MYSQL_DATABASE: mydb
In your rocketchat container you should add some environment variables for mysq root password and database to make it available to your container
rocketchat:
image: rocketchat/rocket.chat:latest
hostname: 'rocketchat'
volumes:
- ./rocketchat/uploads:/app/uploads
environment:
- PORT=3000
- ROOT_URL=http://localhost:3000
- MONGO_URL=<placeholder>
- MONGO_OPLOG_URL=<placeholder>
- MYSQL_ROOT_PASSWORD: mypass
- MYSQL_DATABASE: mydb
- MYSQL_HOSTNAME: db
...
links:
- rocketchat:rocketchat
- db : db
And then, use the host name and the environment variables to create your connection:
var con = mysql.createConnection({
host: 'db', // or process.env.MYSQL_HOSTNAME
user: 'root',
port: '3306',
password: 'mypass', // or process.env.MYSQL_ROOT_PASSWORD
});

docker-compose: nodejs + mysql can't connect mysql

I try to dockerlized my own node application, but can't connect the mysql container. my codes:
docker-compose.yml
version: '3.2'
services:
node:
build: ./
ports:
- "8787:8787"
depends_on:
- db
networks:
- docker_xxx
environment:
- PORT=8787
- DATABASE_HOST=db
- DATABASE_PASSWORD=xxx
- EGG_SERVER_ENV=local
- NODE_ENV=development
# command: ["./wait-for-it.sh", "db:3306", "--", "npm run docker"]
db:
build: ./db
networks:
- docker_xxx
environment:
- MYSQL_ROOT_PASSWORD=xxx
- MYSQL_DATABASE=database
- MYSQL_USER=user
- MYSQL_PASSWORD=passwd
networks:
docker_xxx:
driver: bridge
./Dockerfile (for nodejs)
FROM node:8.9.4-alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app/
RUN npm install --production
COPY . /usr/src/app
# COPY wait-for-it.sh /usr/src/app
EXPOSE 8787
CMD npm run docker
db/Dockerfile (for mysql)
FROM mysql:5.6
ADD honggang.sql /docker-entrypoint-initdb.d
config/config.default.js
config.mysql = {
// mysql settings
client: {
// host
host: process.env.DATABASE_HOST || '127.0.0.1',
// port
port: '3306',
// username
user: 'root',
// password
password: 'xxx',
database: 'xxx',
charset: 'utf8',
dialectOptions: {
collate: 'utf8_general_ci',
},
},
app: true,
agent: false,
};
I run docker-compose up -d , there's only db running.
I run docker logs hash to find errors, it shows the following info:
2018-04-30 14:43:51,334 ERROR 54 nodejs.ECONNREFUSEDError: connect ECONNREFUSED 172.19.0.2:3306
at Object._errnoException (util.js:1022:11)
at _exceptionWithHostPort (util.js:1044:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1182:14)
--------------------
at Protocol._enqueue (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:145:48)
at Protocol.handshake (/usr/src/app/node_modules/mysql/lib/protocol/Protocol.js:52:23)
at PoolConnection.connect (/usr/src/app/node_modules/mysql/lib/Connection.js:130:18)
at Pool.getConnection (/usr/src/app/node_modules/mysql/lib/Pool.js:48:16)
at /usr/src/app/node_modules/ali-rds/node_modules/pify/index.js:29:7
at new Promise (<anonymous>)
at Pool.<anonymous> (/usr/src/app/node_modules/ali-rds/node_modules/pify/index.js:12:10)
at Pool.ret [as getConnection] (/usr/src/app/node_modules/ali-rds/node_modules/pify/index.js:56:34)
at Pool.query (/usr/src/app/node_modules/mysql/lib/Pool.js:202:8)
at /usr/src/app/node_modules/ali-rds/node_modules/pify/index.js:29:7
sql: select now() as currentTime;
code: 'ECONNREFUSED'
errno: 'ECONNREFUSED'
syscall: 'connect'
address: '172.19.0.2'
port: 3306
fatal: true
name: 'ECONNREFUSEDError'
pid: 54
hostname: d9cd95667a5d
I added CMD ping db, it responded.
I tried to use wait-for-it.sh (the code just commented out), but got the error info:
env: can't execute 'bash': No such file or directory
I solved https://github.com/ycjcl868/eggjs-mysql-docker
there are the points:
1. apk add --no-cache bash to run the wait-for-it.sh waiting the mysql server is ok
2. hostname is 0.0.0.0 not localhost/127.0.0.1