小能豆

Unable to connect to mysql container Unable to create tables due to 2003 (HY000): Can't connect to MySQL server on 'mysql:3307'

python

I am trying to connect mysql container with my python flask app and I have this error when running docker-compose build --no-cache && docker-compose up:

Creating network "hdbresalepricealert_sql_network" with the default driver
Creating hdbresalepricealert_mysql_1 ... done
Creating hdbresalepricealert_python_app_1 ... done
Attaching to hdbresalepricealert_mysql_1, hdbresalepricealert_python_app_1
mysql_1       | 2023-12-22 04:48:45+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.2.0-1.el8 started.
mysql_1       | 2023-12-22 04:48:46+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
mysql_1       | 2023-12-22 04:48:46+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.2.0-1.el8 started.
mysql_1       | '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'  
mysql_1       | 2023-12-22T04:48:46.269421Z 0 [System] [MY-015015] [Server] MySQL Server - start.
mysql_1       | 2023-12-22T04:48:46.860627Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
mysql_1       | 2023-12-22T04:48:46.866169Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.2.0) starting as process 1
mysql_1       | 2023-12-22T04:48:46.891660Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
mysql_1       | 2023-12-22T04:48:47.157634Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
mysql_1       | 2023-12-22T04:48:47.482067Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
mysql_1       | 2023-12-22T04:48:47.482195Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
mysql_1       | 2023-12-22T04:48:47.485815Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.        
mysql_1       | 2023-12-22T04:48:47.512210Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
mysql_1       | 2023-12-22T04:48:47.512345Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.2.0'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.
python_app_1  | INFO:services.dbService:Entering create tables method from dbservice
python_app_1  | ERROR:services.dbService:Unable to create tables due to 2003 (HY000): Can't connect to MySQL server on 'mysql:3307' (111)
python_app_1  |  * Serving Flask app 'app'
python_app_1  |  * Debug mode: on
python_app_1  | INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.        
python_app_1  |  * Running on all addresses (0.0.0.0)
python_app_1  |  * Running on http://127.0.0.1:5000
python_app_1  |  * Running on http://172.22.0.3:5000
python_app_1  | INFO:werkzeug:Press CTRL+C to quit
python_app_1  | INFO:werkzeug: * Restarting with stat
python_app_1  | INFO:services.dbService:Entering create tables method from dbservice
python_app_1  | ERROR:services.dbService:Unable to create tables due to 2003 (HY000): Can't connect to MySQL server on 'mysql:3307' (111)
python_app_1  | WARNING:werkzeug: * Debugger is active!
python_app_1  | INFO:werkzeug: * Debugger PIN: 111-520-781

My docker-compose file:

version: '3'

services:
  mysql:
    image: mysql:latest
    ports:
      - "3307:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: db
      MYSQL_USER: user
      MYSQL_PASSWORD: password
    networks:
      - sql_network
    volumes:
      - /mysql_data :/var/lib/mysql

  python_app:
    build: .
    ports:
      - "5000:5000"
    networks:
      - sql_network
    depends_on:
      - mysql

networks:
  sql_network:

Relevant portion of the dbService.py:

config = {
    'host': 'mysql',  # This should match the service name in Docker Compose
    'port': '3307',   # This should match the exposed port on the host
    'user': 'user',
    'password': 'password',
    'database': 'db',
}


def create_tables():
    logger.info("Entering create tables method from dbservice")
    try:
        connection = mysql.connector.connect(**config)
        cursor = connection.cursor()
        # Check if 'emails' table already exists
        cursor.execute("SHOW TABLES LIKE 'emails'")
        table_exists = cursor.fetchone()

        if not table_exists:
            cursor.execute(
                '''
                CREATE TABLE emails (
                id INT PRIMARY KEY AUTO_INCREMENT,
                created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                email VARCHAR(255) NOT NULL,
                verified BOOLEAN NOT NULL,
                flatType VARCHAR(255) NOT NULL,
                streetName VARCHAR(255) NOT NULL,
                blkFrom INT NOT NULL,
                blkTo INT NOT NULL,
                lastSent TIMESTAMP,
                token VARCHAR(255))
                ''')
            connection.commit()
            connection.close()
    except Exception as e:
        logger.error(f"Unable to create tables due to {e}")

My dockerfile:

FROM python:3.12.1-bullseye

ARG REPO_DIR="."
ARG PROJECT_USER="randy"
ARG HOME_DIR="/home/$PROJECT_USER"
ARG DESTINATION_FOLDER="hdb"

WORKDIR $HOME_DIR

# The copy is from local (where the docker command is executed) to this 
COPY $REPO_DIR $DESTINATION_FOLDER

RUN pip install -r $DESTINATION_FOLDER/app/run-requirements.txt

RUN groupadd -g 2222 $PROJECT_USER && useradd -u 2222 -g 2222 -m $PROJECT_USER
RUN chown -R 2222:2222 $HOME_DIR && \
    rm /bin/sh && ln -s /bin/bash /bin/sh
USER 2222

WORKDIR $HOME_DIR/${DESTINATION_FOLDER}

CMD [ "python3", "app/app.py" ]

Relevant portion of my app.py:

time.sleep(10)
create_tables()

Essentially I’m trying to create the tables first using the create tables function in the dbservice.py, I included the wait as I read that if I connected before the mysql container is up there might be some issues.

I’m able to connect to the sql container using docker exec -it <container image> bash and login, no problem, I see that the container is up and running in docker-compose ps. I just cannot connect to the mysql container when running docker-compose build --no-cache && docker-compose up. Its been bugging me for days and I have scoured the web for all possible solutions including chatgpt but to no avail. I think it may be some small gotcha that I’ve missed. Can anyone help?


阅读 75

收藏
2023-12-22

共1个答案

小能豆

The error you’re encountering (2003 (HY000): Can't connect to MySQL server on 'mysql:3307' (111)) suggests that the Python application (python_app) is unable to connect to the MySQL server. Here are a few things you can check and try to resolve the issue:

  1. Check MySQL Container Name: Ensure that the hostname or IP address used in the config dictionary in dbService.py matches the service name defined in your docker-compose.yml for the MySQL container. In your case, it’s set to 'mysql'.

config = { 'host': 'mysql', # Check if this matches the service name in Docker Compose 'port': '3307', # Check if this matches the exposed port on the host 'user': 'user', 'password': 'password', 'database': 'db', }

  1. Check MySQL Port: Ensure that the port used in the config dictionary is the same as the one defined in your docker-compose.yml file. In your case, it’s set to 3307.

services: mysql: ports: - "3307:3306"

  1. Check MySQL Server Availability: Ensure that the MySQL server is up and running inside the container. You can use the following command to check the logs of the MySQL container:

docker-compose logs mysql

Look for any errors or issues reported in the MySQL container logs.

  1. Wait for MySQL to be Ready: Although you have added a time.sleep(10) in your app.py to wait for MySQL, it might be beneficial to use a more robust solution. You can use tools like wait-for-it or dockerize to wait for the MySQL service to be ready before starting your Python application. Add one of these tools to your python_app Dockerfile and use it in your entry script.

  2. wait-for-it: https://github.com/vishnubob/wait-for-it

  3. dockerize: https://github.com/jwilder/dockerize

Example:

CMD ["./wait-for-it.sh", "mysql:3307", "--", "python3", "app/app.py"]

  1. Check Firewall Settings: Ensure that there are no firewall issues preventing the Python application from connecting to the MySQL server. Check if any firewall rules are blocking the connection.

  2. Network Connectivity: Ensure that the Python application container is in the same Docker network as the MySQL container. In your case, both containers are in the sql_network network, which seems correct.

Try these steps and see if it resolves the connectivity issue. If the problem persists, checking the MySQL container logs (docker-compose logs mysql) might provide additional clues about what’s going wrong.

2023-12-22