unable to access mysql db using python (both running on different containers) - python

I am trying to connect to mysql db using a python program. When run locally it works.
But while dockerizing the application I created, one container is for the python code and the other for the mysql db, when ran i this manner it fails to connect.
Python_code:
db.bind(provider='mysql', user='docker_root', password='password', host='db', database=database, port = 3306)
docker-compose:
version: "3"
services:
app:
image: app:latest
links:
- db
ports:
- "8001:8081"
environment:
- DB_HOST= db
db:
image: mysql:5.7.26
restart: always
environment:
MYSQL_DATABASE: 'my_db'
MYSQL_USER: 'docker_root'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- "3306:3306"
volumes:
- ./DB_config/:/etc/mysql/mysql.conf.d
And the docker-compose up fails with the eroor:
pony.orm.dbapiprovider.OperationalError: (2003, "Can't connect to
MySQL server on 'db' ([Errno 111] Connection refused)")
Where am I going wrong? Please advise!

I would recommend you to exit your application in case it cannot connect to MySQL and set the restart policy to always, because depends_on does not guarantee that MySQL will be totally up when app starts but it is good to have it there.
version: "3"
services:
app:
image: app:latest
restart: always
links:
- db
ports:
- "8001:8081"
environment:
- DB_HOST= db
depends_on:
- db
db:
image: mysql:5.7.26
restart: always
environment:
MYSQL_DATABASE: 'my_db'
MYSQL_USER: 'docker_root'
MYSQL_PASSWORD: 'password'
MYSQL_ROOT_PASSWORD: 'password'
ports:
- "3306:3306"
volumes:
- ./DB_config/:/etc/mysql/mysql.conf.d
And your application code should be something like:
try:
db.bind(provider='mysql', user='docker_root', password='password', host='db', database=database, port = 3306)
except:
# write some logs
exit(1)

Try using container port 3306 -
db.bind(provider='mysql', user='docker_root', password='password', host='db', database=database, port = 3306)
Also, add depends_on attribute, you can remove the links attribute -
depends_on:
- db

YOu can use depends_on flag as mentioned in accepted answer. If it does not solve your problem them use this approach.
After starting the container, your server will try to connect to the database server. sometimes database server may take some time to boot up and in this window, if the server tries to connect to database server it will face problems.
Try adding logic to reconnect database server after few seconds if the connection fails.
try{
connectToDatabase();
}catch(error){
waitForHalfMinute();
connectToDatabase();
}

Related

Mysql connector python error violation of protocol (_ssl.c:2483)

Im running an application running React, python and MySQL with a docker compose, When I run the application everything works fine, but when a pettition to the database (from the frontend with axios) is made multiple times, the connection breaks and the following error appears. Everything is running locally
"2055: Lost connection to MySQL server at 'database:3306', system error: 8 EOF occurred in violation of protocol (_ssl.c:2483)"
Here is the configuration of my connection and my dockerfile
import mysql.connector
return mysql.connector.connect(
host=os.environ.get("database"),
user="root",
password="root",
database="locatec",
port=3306,
auth_plugin='mysql_native_password'
)
database:
image: mysql
container_name: database
restart: always
ports:
- '3306:3306'
#command: --init-file /init.sql
volumes:
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
- ~/apps/mysql:/var/lib/locatec5
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: test
MYSQL_PASSWORD: test
MYSQL_ROOT_HOST: '%'
TIMEZONE: UTC
networks:
- locatec
server:
build:
context: ../../../
dockerfile: infra/deploy/backend/dev/Dockerfile
restart: always
ports:
- "5000:5000"
container_name: server
networks:
- locatec
depends_on:
- database
I tried using
mysql-connector-python==8.0.30
, also I configured the param of ssl to false
This looks like an error I faced some time ago. In my case, it was due to a client initiating a secured connection to a non-secured server.
The error message indicates that the client has initiated a SSL/TLS connection and is expecting to receive more data than the server has sent during the handshake procedure.
There are two ways to fix this, either by:
enabling SSL/TLS on server side so that the client can initiate a SSL/TLS handshake and get a consistent response. [Docker side]
disabling the SSL/TLS from the database connector. [Python side]

(pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'mysql' ([Errno -3] Temporary failure in name resolution

I am trying to Dockerize a FastAPI app that uses MYSQL and Seleniun.
I am having issues with connecting MYSQL with the FASTAPI app in the Docker.
I have tried to establish connection with MYSQL container using MYSQL Workbench which worked well using 'localhost' as the host. However, when I try to run the fastapi container which should connect with MySqL database, I am having this error:
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'mysql' ([Errno -3] Temporary failure in name resolution
Here is docker-compose.yml:
version: '3'
services:
chrome:
build: .
image: selenium/node-chrome:3.141.59-20210929
ports:
- "4444:4444"
- "5900:5900"
volumes:
- "/dev/shm:/dev/shm"
networks:
- selenium
mysql:
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
- MYSQL_ROOT_PASSWORD=admin
- MYSQL_DATABASE=autojob
- MYSQL_USER=user
- MYSQL_PASSWORD=4444
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost"]
timeout: 20s
retries: 10
volumes:
- ./init:/docker-entrypoint-initdb.d
- autojob:/var/lib/mysql
ports:
- "3307:3306"
expose:
- "3307"
app:
build: .
restart: on-failure
container_name: "autojobserve_container"
command:
uvicorn autojobserve.app:app --host 0.0.0.0 --port 8000 --reload
ports:
- 8000:8000
volumes:
- "./:/app"
networks:
- selenium
depends_on:
mysql:
condition: service_healthy
volumes:
autojob: {}
networks:
selenium:
Here is the line that connects with MYSQL in FastAPI:
engine = create_engine("mysql+pymysql://user:4444#mysql:3307/autojob")
In DockerDesktop, it shows that Mysql container is ready for connection too:
2022-11-08T11:49:26.334069Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
2022-11-08T11:49:26.334869Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.31' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
2022-11-08 11:49:14+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
2022-11-08 11:49:14+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2022-11-08 11:49:14+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
'/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
What possibly could be wrong?
Note: Everything works well before dockerizing.
Your app container declares networks: [selenium]. The mysql container doesn't have a networks: block at all, so Compose automatically inserts networks: [default]. Since the two containers aren't on the same Docker network they can't communicate with each other, and one of the ways you see that is with the DNS-resolution issue you're seeing.
The setup I'd recommend here is to delete all of the networks: blocks in the whole file. Compose will automatically create the default network and attach containers to it, and for most applications this is a correct setup.
(You also do not need the obsolete expose: option, or to manually specify container_name:. You should not need to use volumes: to inject code into your container or command: either, the code and its default command should generally be specified in the Dockerfile.)

Unable to connect to Docker Postgres from outside

I am using this docker-compose to spin up a postgres instance on my laptop. It works fine when I connect it as localhost. However, I would like to connect to it from a different laptop but i'm not able to. In the postgresql.conf file, the listening address is set to * already and I also added the this line host all all 0.0.0.0/0 md5 to pg_hba.conf. When I connect to it locally with DBeaver, it only works with localhost or 0.0.0.0 as host but doesn't work when I change it to the container IP. What am I missing here?
docker-compose.yml
services:
database:
image: postgres
ports:
- "5432:5432"
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: mydb
user: postgres
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:

Connect to mysql when running Python unit tests using remote interpreter

I am starting a Flask project and I want to run unit tests in PyCharm using Docker remote interpreter, but I am not being able to connect to the mysql database container when running the tests. The application runs normally, so the database is reachable outside the container. In the past I managed to do that in PhpStorm, but the configurations in PyCharm are not the same and I am having some trouble setting everything up. I already managed to use the remote interpreter to run tests, but the only trouble is when I need to connect to the database.
I am getting the following error when trying to connect:
mysql.connector.errors.InterfaceError: 2003: Can't connect to MySQL server on 'localhost:3306' (111 Connection refused)
So, the server is reachable, but for whatever reason it is not allowing to connect.
Here is the docker-compose.yml
version: "2"
networks:
learning_flask:
name: learning_flask
driver: bridge
services:
mysql:
image: mysql:5.7
container_name: mysql
restart: unless-stopped
tty: true
ports:
- "127.0.0.1:3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- ./db:/docker-entrypoint-initdb.d/:ro
networks:
- learning_flask
app:
build: ./app
container_name: learning_flask_app
ports:
- "5000:5000"
volumes:
[ './app:/app' ]
depends_on:
- mysql
networks:
- learning_flask
and then the code I am trying to execute:
import unittest
import mysql.connector
class TestCase(unittest.TestCase):
def test_something(self):
config = {
'user': 'root',
'password': 'root',
'host': 'localhost',
'port': '3306'
}
connection = mysql.connector.connect(**config)
if __name__ == '__main__':
unittest.main()
If I try to change the host on the connection config to mysql, I get the following error:
mysql.connector.errors.InterfaceError: 2003: Can't connect to MySQL server on 'mysql:3306' (-2 Name or service not known)

Docker compose mysql connection failing

I am trying to run 2 docker containers using docker-compose and connect mysql container to app container.Mysql container is running but app container is failing to start with the error Error:2003: Can't connect to MySQL server on '127.0.0.1:3306' (111 Connection refused)
It seems like my app container is trying to connect my host mysql instead of mysql container.
docker-compose.yml
version: '2'
services:
mysql:
image: mysql:5.7
container_name: database
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: malicious
MYSQL_USER: root
MYSQL_PASSWORD: root
app:
build: .
restart: unless-stopped
volumes:
- .:/Docker_compose_app #app directory
depends_on:
- "mysql"
command: [ "python", "database_update.py"]
restart: unless-restart
environment:
# Environment variables to configure the app on startup.
MYSQL_DATABASE: malicious
MYSQL_HOST: database
Dockerfile
FROM python:2.7
ADD . /Docker_compose_app
WORKDIR /Docker_compose_app
RUN apt-get update
RUN pip install --requirement requirement.txt
This is my database_update.py file.
def create_TB(cursor,connection):
query = '''CREATE TABLE {}(malicious VARCHAR(100) NOT NULL)'''.format("url_lookup")
cursor.execute(query)
connection.commit()
def connection():
try:
cnx = mysql.connector.connect(user="root",password = 'root',database=malicious)
cursor = cnx.cursor()
create_TB(cursor,cnx)
except mysql.connector.errors.Error as err:
data = {"There is an issue in connection to DB":"Error: {}".format(err)}
There are two issues I can see:
Try to add
links:
- mysql:mysql
to the app service in your Docker Compose file. This will make sure that you can reach the mysql container from app. It will set up a hostname mapping (DNS) in your app container, so when you ping mysql from app, it will resolve it to the mysql container's IP address.
In your .py file, where are you defining which host to connect to? Add host="mysql" to the connect call. By default, it will connect to 127.0.0.1, which is what you're seeing.
cnx = mysql.connector.connect(host="mysql", user="root", password = 'root', database=malicious)
Fixing both of these should solve your problem.
You might want to consider using Docker Networks.
I was having a similar problem while having two seperate Python container connecting to one mysql-Container, while those 2 were connected to a Vue-Frontend.
First I tried using links (which was not optimal, because the communication-flow is not entirely linear), just like you but the I ran across this great post:
https://www.cbtnuggets.com/blog/devops/how-to-share-a-mysql-db-with-multiple-docker-containers
Using Networks shift the port mapping off and lets you enhance your overall App-Architecture.
Therefore I think you should try something like:
services:
python-app:
networks:
- network_name
...
mysql:
networks:
- network_name
...
networks:
network_name:

Categories