Connecting NodeJS Docker container to a MySQL Docker container - docker-compose 3 - mysql

When I try to connect two docker containers on the same machine, one running a node.js server and the other running mysql dbms
I get the following error:
(node:32) UnhandledPromiseRejectionWarning: Error: getaddrinfo ENOTFOUND jdbc:mysql://localhost:3306 jdbc:mysql://localhost:3306:3306
mysql driver connection config
const connection= mysql.createConnection({
host: 'jdbc:mysql://topsectiondb:3306',
user: 'root',
password: 'rootpass'
})
docker-compose.yml
version: '3'
services:
topsection:
container_name: topsection-server
restart: always
build: .
ports:
- '7777:7777'
depends_on:
- topsectiondb
environment:
- PORT=7777
topsectiondb:
container_name: topsectiondb
image: mysql:8.0.3
ports:
- '3306:3306'
environment:
- MYSQL_ROOT_PASSWORD=rootpass
Dockerfile
FROM node:10
RUN mkdir serviceFolder
WORKDIR /usr/app/
COPY . .
RUN npm install
EXPOSE 7777
CMD ["npm", "start"]
for a more complete stack trace
https://gist.github.com/armouti/877a8b4405330c44e4009ebae3df822c

First of all there are a couple of problems here.
Firstly you need to look at networking your docker containers in your docker-compose file together. Basically each container doesn't know of the other until you specify which network they are in. Each container can be in multiple but if you want two containers to connect they need to be in the same network. https://docs.docker.com/compose/networking/#configure-the-default-network
Then Secondly you can't use localhost as a url. Basically a docker container is an isolated environment so it has it's own "localhost" so when you use that address it's actually trying to connect to the mysql on the nodejs container. So when networked properly you will be able to connect to the mysql container using their names you gave them in the docker-compose something like topsectiondb:3306 or something like this. This tells docker your using networking to connect one docker container to another and will allow you to make the initial connection. Connect to another container using Docker compose
===================================================
Actual Answer:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});
Basically the mysql library requires a hostname, which in most cases is localhost, but as your linking containers with docker-compose you use the alias of the container. The port number is 3306 by default
So:
host: "topsectiondb" will suffice!

Related

dockerized django application cannot connect to mysql server on localhost

I have a Dockerized django application I am running and I am trying to connect it to a mysql server I have that is port forwarded from another docker container. I have done a sanity test already and confirmed that I can connect to my mysql server using mysql workbench on my localhost.
I have my dockerized django application running on network_mode: host so I thought I would be able to simply connect. Sadly I currently error out on docker-compose build with the error django.db.utils.OperationalError: (2002, "Can't connect to MySQL server on '127.0.0.1' (115)")
An accepted resolution to this issue means that my dockerized django application would be able to connect successfully to my mysql server running localhost:29998
SETTINGS.PY (Django Application)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mytestdb',
'USER': 'userone',
'PASSWORD': 'password',
'HOST': '127.0.0.1',
'PORT': '29998',
}
}
DJANGO App compose file
version: '3.3'
services:
mydjangoapp:
container_name: mydjangoapp
restart: always
env_file: .env
build: .
volumes:
- ./apps:/apps
- ./core:/core
network_mode: host
Django app dockerfile:
FROM python:3.9
COPY . .
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
COPY requirements.txt .
# install python dependencies
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -r requirements.txt
# running migrations
RUN python manage.py migrate
# gunicorn
CMD ["gunicorn", "--config", "gunicorn-cfg.py", "core.wsgi"]
Dockerized mysql server (port forwarded to localhost)
version: '3.3'
services:
mysql:
image: mysql:latest
container_name: mymysqlserver
environment:
- MYSQL_DATABASE=mytestdb
- MYSQL_USER=userone
- MYSQL_ROOT_PASSWORD=password
- MYSQL_PASSWORD=password
ports:
- 29998:3306
Do I need to create some sort of docker network / bridge for this to work? (never tried that before).
I have already attempted the following solutions: sol1 (network_mode=host), sol2,
You django app is not working because:
You are running the containers in separated docker-compose files, this causes django container runs in different network than mysql container.
You are trying to connect to localhost (127.0.0.1) inside the django container. This localhost is different to 'localhost' of your computer and is different to the 'localhost' of mysql container. There are 3 different networks. If you want to connect django container with mysql container use the same network (docker network or your computer IP assigned by a router also will works).
You are trying to connect to the exposed port 29998, but this port is exposed from mysql container to your computer. If you are trying to make an internal connection you should use 3306. (If you are using an internal connection, then you don't need to expose the port)
Why not put the two services in same docker compose file and run it from there, like this:
version: '3.3'
services:
mydjangoapp:
container_name: mydjangoapp
restart: always
env_file: .env
build: .
volumes:
- ./apps:/apps
- ./core:/core
network_mode: host
depends_on: mysql
mysql:
image: mysql:latest
container_name: mymysqlserver
environment:
- MYSQL_DATABASE=mytestdb
- MYSQL_USER=userone
- MYSQL_ROOT_PASSWORD=password
- MYSQL_PASSWORD=password
ports:
- 29998:3306
And then update the settings like this:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mytestdb',
'USER': 'userone',
'PASSWORD': 'password',
'HOST': 'mysql',
'PORT': '3306',
}
}
In that way, the communication between Django and MySQL will be done through docker network, rather than accessing the host machine network.
Apart from that, you need to change the Dockerfile, so that the migration runs after the MySQL server is running. To ensure that, you can add the migration command in the CMD part:
CMD ["sh", "-c", "python manage.py migrate;gunicorn --config gunicorn-cfg.py core.wsgi"]

Spring Boot + MySQL docker containers

I have two containers, one with a Srping app and another with mysql. When I run the Spring app on my local machine, it successfully connects to my MySQL db running in a docker container. Once I spin up the Spring container I get a connection error, the app is unable to communicate with the MySQL container. How do I configure the Spring container to communicate with the db container? I've tried creating a bridge network to no avail. I believe my issue is spring.datasource.url=jdbc:mysql://localhost:3309/library but when I try with the network id the jar fails to build spring.datasource.url=jdbc:mysql://lms-network/library. I've been following this tutorial. docker image.
There are couple of ways we can solve it.
Using docker-compose
Put both the containers in docker-compose file. Example:
version: "3"
services:
spring-boot-service:
build:
context: .
ports:
- 8080:8080
environment:
DB_HOST: mysql-db
DB_NAME: library
DB_USER: <user>
DB_PASSWORD : <pwd>
mysql-db:
image: mysql
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: "root"
MYSQL_DATABASE: <db_name>
#... other properties
then in application.properties, use connection string as :
spring.datasource.url=jdbc:mysql://${DB_HOST}:3306/${DB_NAME}
then use docker-compose up to run both containers together. This way they will share network through docker-compose.
Using host.docker.internal
When you run your spring boot app and mysql in separate containers, you can't refer the mysql database from localhost anymore as localhost means pointing to your container. Since mysql is running on your host machine, you can refer it by using host.docker.internal instead of localhost in connection string.
So you connection string should be
spring.datasource.url=jdbc:mysql://host.docker.internal:3309/library

Cannot connect to MySQL db using docker container

I wrote an application in Typescript which use Typeorm to interact with a MySQL database. When I run the app using npm run dev which is a package.json script, the connection is working fine with these credentials:
"type": "mysql",
"host": "127.0.0.1",
"port": 3306,
"username": "root",
"password": "root",
"database": "mydb",
but when I launch my Docker container I get:
> Error: connect ECONNREFUSED 127.0.0.1:3306
> errno: -111,
> code: 'ECONNREFUSED',
> syscall: 'connect',
> address: '127.0.0.1',
> port: 3306,
> fatal: true
I cannot figure out of this problem, I also tried to change 127.0.0.1 with localhost but same problem. That's weird 'cause I'm using Dbeaver to connect with my LAMP which is a Docker container container too and I can establish the connection.
Seems a problem related only with the containers connection, maybe the container of the app doesn't know the network 127.0.0.1?
This is my image file:
FROM node:stretch-slim
WORKDIR /myapp
COPY package.json ./
COPY ./dist ./dist
RUN npm install
EXPOSE 4000
ENV NODE_ENV development
ENV PORT 4000
ENV URL http://localhost:4000
ENV JWT_SECRET secret
CMD ["npm", "run", "start", "dev"]
and this is my docker-compose.yml:
version: '3'
services:
app:
container_name: myapp
restart: always
build: .
ports:
- '4000:4000'
for compile my containers I did: docker-compose up --build
What is wrong? As you can see from my lamp container each port is correctly exposed:
The problem here is that each container use their own network, even though I exposed the mysql container on port 3306 I cannot access to mysql from the myapp container, because myapp container use another network.
So executing the following command: docker network ls I was able to list all the networks available, and then I did:
docker network inspect bridge
which has returned the following gateway: 172.17.0.1
The solution would be to replace localhost with 172.17.0.1. But I don't like the following solution too much, so I rebuilded the myapp image adding previously network_mode inside the docker-compose.yml, so now I have:
version: '3'
services:
app:
container_name: myapp
restart: always
build: .
ports:
- '4000:4000'
network_mode: 'host'
as documentation says:
If you use the host network mode for a container, that container’s network stack is not isolated from the Docker host (the container shares the host’s networking namespace), and the container does not get its own IP-address allocated. For instance, if you run a container which binds to port 80 and you use host networking, the container’s application is available on port 80 on the host’s IP address.
I don't know if there is a better solution out there, I'm a Docker noob so far, so maybe someone more expert on this could propose a better solution to share a container network such as mysql, and then access to that shared network from others containers.
Another solution would be "host": "host.docker.internal"
docker-compose
docker-compose isn't limited to just one service, you can have the whole system, which, in your case, means the DB server, your app, and all the other things.
You can change your docker-compose.yml file to something like below (MySQL bit copied from https://hub.docker.com/_/mysql )
version: '3'
services:
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
app:
container_name: myapp
restart: always
build: .
ports:
- '4000:4000'
Networking
Because your containers are brought up in the same docker-compose, by default they have access to each other by hostname e.g. app, and db. To try this out, bring them up, docker attach/exec to app, and try a ping db.
See https://stackoverflow.com/a/30173220/1148483
This means that in your app, you can use db as the DB host config.
Instead of using localhost, let's replace it with host.docker.internal. This will allow you to connect with your local db

Docker django mysql.sock in different location

I'm trying to containerize my django file, and I keep running into the issue:(2006, ’Can\‘t connect to local MySQL server through socket \‘/var/run/mysqld/mysqld.sock\’ (2 “No such file or directory”)
I found out later mysql.sock is in this location:/tmp/mysql.sock instead of /var/run/mysqld/mysqld.sock, how do I change the location for docker to see /tmp/mysql.sock
Here is my docker-composr.yml:
version: '3'
services:
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: somepassword
adminer:
image: adminer
restart: always
ports:
- 8080:8080
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
I have followed the instructions on the mysql docker website to link mysql instance to a container
EDIT: I read another stack overflow similar to this, I changed my django code to 'HOST': '127.0.0.1' in DATABASES now I get : (2006, 'Can\'t connect to MySQL server on \'127.0.0.1\' (111 "Connection refused")')
Your host should be db. When using docker-compose, you address different servers by their service name.
So, in settings.py, you should have:
DATABASES = {
'default': {
'HOST': 'db',
...
}
}
If you want to connect to your containerized MySQL server both inside and outside of the container, you'll first need to make sure the port is mapped on the host machine:
services:
db:
image: mysql
ports:
- "3306:3306"
...
That will allow you to access MySQL using localhost or 127.0.0.1 directly on your host machine.
If you want to be able to run Django in both the web container and also on the host, you'll need to override the DATABASES setting depending upon the scenario. The web container will need to use a HOST value of db, whereas your local machine will need a value of localhost.

Can't connect to mysql in docker container from phpbb

My docker container is working nicely, and I can connect to my database using my graphical sql client.
However when I try to connect to my phpbb instance, I get this error:
General Error SQL ERROR [ mysqli ]
No such file or directory [2002]
An sql error occurred while fetching this page. Please contact an
administrator if this problem persists.
The phpbb config looks like this:
$dbms = 'mysqli';
$dbhost = 'localhost';
$dbport = '';
$dbname = 'xxxxx_xxxx';
$dbuser = 'xxxxxxxxx';
$dbpasswd = 'xxxxxx';
Would the file or directory it can't find relate to the mysql.so? If so where would I set this in the docker configs?
It not then does anyone know what's going on?
Edit for clarity:
My docker-compose.yml looks like the below and I am running it with 'docker-compose up'
php:
image: webdevops/php-nginx
links:
- db:database
volumes:
- "/home/xxx/code/mytest:/mytest-now"
ports:
- 80:80
environment:
- WEB_DOCUMENT_ROOT=/mytest/public
db:
image: mariadb:latest
volumes:
- "mytest-db:/var/lib/mysql"
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: admin
MYSQL_DATABASE: dbname
MYSQL_USER: user
MYSQL_PASSWORD: password
The reason your connection is not working is the use of localhost. I assume you ran your mysql container either through docker-compose or docker and mapped port 3306 form host to 3306 on container.
Now using the graphical GUI you use localhost:3306 and it works, this is because your forwarded the docker port to the host port.
But your phpbb container the localhost refers to the container itself and hence the connection cannot be made. So there few ways to get it working
Host IP
Use the host IP which where you have mapped the port 3306
$dbhost = '192.168.0.102';
This is not a recommended approach as your host IP will change when you connect to different networks
Use mysql container name
Run your mysql container with a --name mysqldb and use the this name in the connection
$dbhost = 'mysqldb';
Use mysql service name
If you use docker-compose and added mysql as a service
version: '3'
services:
mysqldb2:
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=root
phpbb:
.....
Then you can use the service name in your connection settings
$dbhost = 'mysqldb2';
After running 'docker inspect containername' I noticed an ip address under:
NetworkSettings.Networks.bridge.gateway.
When I tried that, it worked!