Docker Compose部署Flask应用时出现MySQLdb OperationalError(2002)连接问题求助
Hey there, let's fix this MySQL connection issue you're running into!
The Root Cause
When you set MYSQL_HOST = 'localhost' in your Flask config, your Flask container is trying to connect to a MySQL server inside its own container—not the separate MySQL container you created with Docker Compose. That's why you get the socket error: there's no MySQL running in the Flask container.
Your docker exec command works because you're directly accessing the MySQL container itself, where the socket file exists.
Step-by-Step Fixes
1. Update Flask's MySQL Host Configuration
Change the MYSQL_HOST value to match the service name of your MySQL container in docker-compose.yml (which is db). Docker Compose automatically creates DNS entries for service names, so your Flask container can resolve db to the MySQL container's IP.
Modified Flask config:
from flask_mysqldb import MySQL,MySQLdb app = Flask(__name__) app.config['MYSQL_HOST'] = 'db' # Replace 'localhost' with 'db' app.config['MYSQL_USER'] = '*****' app.config['MYSQL_PASSWORD'] = '****' app.config['MYSQL_DB'] = 'emp' app.config['MYSQL_CURSORCLASS'] = 'DictCursor' mysql = MySQL(app)
2. Add Dependencies & Health Checks to Docker Compose
Make sure your Flask service waits for MySQL to be fully ready before starting. A basic depends_on ensures the MySQL container is up, but adding a health check guarantees the MySQL service is actually accepting connections.
Modified docker-compose.yml:
version: '3.1' services: db: image: mysql command: --default-authentication-plugin=mysql_native_password volumes: - ./db:/docker-entrypoint-initdb.d/:ro restart: always environment: MYSQL_ROOT_PASSWORD: **** MYSQL_DATABASE: emp MYSQL_PASSWORD: **** ports: - "33061:3306" # Add health check to verify MySQL is ready healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"] interval: 5s timeout: 5s retries: 5 emp: build: . restart: always ports: - 5005:5000 # Wait for MySQL to be healthy before starting depends_on: db: condition: service_healthy volumes: - my-db:/path/to/your/app/data # Fix volume syntax (add target path) volumes: my-db: # Define the volume at the top level
3. Fix the Dockerfile's CMD Conflict
Your current Dockerfile has two CMD commands—only the last one (python3 app.py) will run, so your cron job won't start. To run both cron and Flask, use a startup script:
- Create a
start.shfile in your project root:
#!/bin/bash # Start cron in the background cron -f & # Start Flask in the foreground python3 app.py
- Update your Dockerfile to use this script:
FROM python:3.6-buster LABEL image for a very management application # We copy just the requirements.txt first to leverage Docker cache COPY ./requirements.txt /app/requirements.txt WORKDIR /app # Update apt before installing packages RUN apt-get update && apt-get install -y default-libmysqlclient-dev cron RUN pip3 install -r requirements.txt RUN touch /var/log/cron.log COPY crontab /etc/cron.d/cjob RUN chmod 0644 /etc/cron.d/cjob # Load the cron job RUN crontab /etc/cron.d/cjob ENV PYTHONUNBUFFERED 1 # Copy and make startup script executable COPY start.sh /app/start.sh RUN chmod +x /app/start.sh EXPOSE 5000 COPY . . # Use the startup script to run both services CMD [ "/app/start.sh" ]
Final Notes
- You don't need to use the host port
33061for container-to-container communication—your Flask app will connect to the MySQL container's internal port3306automatically. - The health check ensures Flask doesn't try to connect until MySQL is fully initialized (which can take a few seconds even after the container starts).
内容的提问来源于stack exchange,提问作者Shwetha K

