无法使用docker-compose连接到MySQL

huangapple go评论67阅读模式
英文:

Unable to connect to mysql using docker-compose

问题

我正在尝试使用通过Docker引入的Python脚本连接到MySQL数据库。我有以下的Compose文件:

version: '3.9'

services:
  mysql_db:
    image: mysql:latest
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${MY_SQL_DATABASE}
      MYSQL_USER: ${MY_SQL_USER}
      MYSQL_PASSWORD: ${MY_SQL_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${MY_SQL_ROOT_PASSWORD}
    ports:
      - '3306:3306'
    volumes:
      - ./mysql-data:/var/lib/mysql

  adminer:
    image: adminer:latest
    restart: unless-stopped
    ports:
      - 8080:8080

  ingestion-python:
    build:
      context: . 
      dockerfile: ingestion.dockerfile
    depends_on:
      - mysql_db

Adminer成功连接到MySQL。然后,我创建了以下的数据导入脚本来自动化表的创建。我的数据导入脚本如下:

from dotenv import load_dotenv
import os
import pandas as pd
from sqlalchemy import create_engine

def main():
   
    load_dotenv('.env')
    
    user = os.environ.get('MY_SQL_USER')
    password = os.environ.get('MY_SQL_PASSWORD')
    host = os.environ.get('MY_SQL_HOST')
    port = os.environ.get('MY_SQL_PORT')
    db = os.environ.get('MY_SQL_DATABASE')
    table_name = os.environ.get('MY_SQL_TABLE_NAME')

    print(f'mysql+pymysql://{user}:{password}@{host}:{port}/{db}')

    engine = create_engine(f'mysql+pymysql://{user}:{password}@{host}:{port}/{db}')

    df = pd.read_csv('./data/data.parquet', encoding='ISO-8859-1', on_bad_lines='skip', engine='python')
    df.to_sql(name=table_name, con=engine, if_exists='append')

if __name__ == '__main__':
    
    main()

当我运行我的Docker Compose文件(docker-compose up -d)时,我得到以下错误:

2023-02-14 08:58:59 sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "无法连接到MySQL服务器 'mysql_db' ([Errno 111] 连接被拒绝)")
2023-02-14 08:58:59 (有关此错误的更多信息,请访问:https://sqlalche.me/e/20/e3q8)

凭证和连接信息是从我的.env文件中提取的:

# MySQL配置
MY_SQL_DATABASE = test_db
MY_SQL_USER = data
MY_SQL_PASSWORD = random
MY_SQL_ROOT_PASSWORD = root

# Python数据导入
MY_SQL_HOST = mysql_db
MY_SQL_PORT = 3306
MY_SQL_TABLE_NAME = test_table

为什么我无法使用我的Python脚本连接到MySQL数据库?

英文:

I am trying to connect to MySql DB using a python script ingested via docker. I have the following compose file:

version: '3.9'

services:
  mysql_db:
    image: mysql:latest
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: ${MY_SQL_DATABASE}
      MYSQL_USER: ${MY_SQL_USER}
      MYSQL_PASSWORD: ${MY_SQL_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${MY_SQL_ROOT_PASSWORD}
    ports:
      - '3306:3306'
    volumes:
      - ./mysql-data:/var/lib/mysql

  adminer:
    image: adminer:latest
    restart: unless-stopped
    ports:
      - 8080:8080
  
  ingestion-python:
    build:
      context: . 
      dockerfile: ingestion.dockerfile
    depends_on:
      - mysql_db

Adminer connects to MySql with success. Then I created the following ingestion script to automate a criação de uma tabela. My ingestion script is:

from dotenv import load_dotenv
import os
import pandas as pd
from sqlalchemy import create_engine


def main():
   
    load_dotenv('.env')
    
    user = os.environ.get('MY_SQL_USER')
    password = os.environ.get('MY_SQL_PASSWORD')
    host = os.environ.get('MY_SQL_HOST')
    port = os.environ.get('MY_SQL_PORT')
    db = os.environ.get('MY_SQL_DATABASE')
    table_name = os.environ.get('MY_SQL_TABLE_NAME')


    print(f'mysql+pymysql://{user}:{password}@{host}:{port}/{db}')

    engine = create_engine(f'mysql+pymysql://{user}:{password}@{host}:{port}/{db}')

    df = pd.read_csv('./data/data.parquet', encoding='ISO-8859-1', on_bad_lines='skip', engine='python')
    df.to_sql(name=table_name, con=engine, if_exists='append')


if __name__ == '__main__':
    
    main()

When I run my docker compose (docker-compose up -d) file I get:

2023-02-14 08:58:59 sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'mysql_db' ([Errno 111] Connection refused)")
2023-02-14 08:58:59 (Background on this error at: https://sqlalche.me/e/20/e3q8)

The credentials and connections are retrieved from my .env file:

#MYSQL CONFIG
MY_SQL_DATABASE = test_db
MY_SQL_USER = data
MY_SQL_PASSWORD = random
MY_SQL_ROOT_PASSWORD = root

#PYTHON INGESTION
MY_SQL_HOST = mysql_db
MY_SQL_PORT = 3306
MY_SQL_TABLE_NAME = test_table

Why I can't connect to MySql DB using my python script?

答案1

得分: 0

这很可能是一个时间安排的问题 - 您的摄取容器在mysql容器中的数据库准备好之前启动。depends_on 只等待mysql容器的启动,而不是数据库实际准备好接受连接。

您可能需要检查容器的日志输出,以查看数据库实际准备好接受连接的时间,并在摄取容器中添加一些延迟。另一个选项是尝试在一个循环中打开连接,带有足够的重试次数和重试之间的超时,以便在数据库准备好时尽快启动。

英文:

This is most likely a timing problem - your ingestion container is starting before the database in the mysql container is ready. The depends_on only waits for the start of the mysql container, not on the database actually being ready to accept connections.

You might want to check the log outputs from the containers to see when the database is actually ready to accept connections, and include some delay into the ingestion container. Another option would be to try opening the connection in a loop with enough retries and some timeout between retries so that you can start as soon as the database is ready.

答案2

得分: 0

你应该在你的Docker Compose文件中设置主机名:

mysql_db:
  hostname: "mysql_db"
  image: mysql:latest
  restart: unless-stopped
  environment:
    MYSQL_DATABASE: ${MY_SQL_DATABASE}
    MYSQL_USER: ${MY_SQL_USER}
    MYSQL_PASSWORD: ${MY_SQL_PASSWORD}
    MYSQL_ROOT_PASSWORD: ${MY_SQL_ROOT_PASSWORD}
  ports:
    - '3306:3306'
  volumes:
    - ./mysql-data:/var/lib/mysql

但作为备用选项,你也可以尝试使用Docker中公开的默认 主机名:端口 作为连接字符串,因为你没有设置网络:

MY_SQL_HOST = host.docker.internal
MY_SQL_PORT = 3306
MY_SQL_TABLE_NAME = test_table
英文:

You should set the hostname in your docker compose file:

mysql_db:
  hostname: "mysql_db"
  image: mysql:latest
  restart: unless-stopped
  environment:
    MYSQL_DATABASE: ${MY_SQL_DATABASE}
    MYSQL_USER: ${MY_SQL_USER}
  MYSQL_PASSWORD: ${MY_SQL_PASSWORD}
  MYSQL_ROOT_PASSWORD: ${MY_SQL_ROOT_PASSWORD}
  ports:
    - '3306:3306'
  volumes:
    - ./mysql-data:/var/lib/mysql

But as fallback you can also try the default hostname:port exposed in docker as connection string since you don't have a network set up:

MY_SQL_HOST = host.docker.internal
MY_SQL_PORT = 3306
MY_SQL_TABLE_NAME = test_table

huangapple
  • 本文由 发表于 2023年2月14日 20:07:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75447618.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定