简体   繁体   English

Python Flask SQLAlchemy 容器无法连接到 Z62A004B95946BB73AZ 容器

[英]Python Flask SQLAlchemy container unable to connect to MySQL container

I am unable to connect to my MySQL database from Flask application.我无法从 Flask 应用程序连接到我的 MySQL 数据库。

I am learning to build web application with Python Flask from this tutorial but tried modifying some elements of it for experimenting with Docker. I am learning to build web application with Python Flask from this tutorial but tried modifying some elements of it for experimenting with Docker. Even without using docker-compose, I was unable to connect to the database from the web application.即使不使用 docker-compose,我也无法从 web 应用程序连接到数据库。

Let me first give the error traceback in the application log (flask_test container):我先在应用程序日志(flask_test 容器)中给出错误回溯:

[2021-12-20 18:13:18 +0000] [1] [INFO] Starting gunicorn 20.1.0

[2021-12-20 18:13:18 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)

[2021-12-20 18:13:18 +0000] [1] [INFO] Using worker: sync

[2021-12-20 18:13:18 +0000] [8] [INFO] Booting worker with pid: 8

[2021-12-20 18:13:19,105] INFO in __init__: Microblog startup

[2021-12-20 18:14:19,239] ERROR in app: Exception on /auth/register [POST]

Traceback (most recent call last):

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/connection.py", line 174, in _new_conn

    conn = connection.create_connection(

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/util/connection.py", line 96, in create_connection

    raise err

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/util/connection.py", line 86, in create_connection

    sock.connect(sa)

ConnectionRefusedError: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:


Traceback (most recent call last):

  File "/home/flasktest/venv/lib/python3.10/site-packages/elasticsearch/connection/http_urllib3.py", line 255, in perform_request

    response = self.pool.urlopen(

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 755, in urlopen

    retries = retries.increment(

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/util/retry.py", line 507, in increment

    raise six.reraise(type(error), error, _stacktrace)

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/packages/six.py", line 770, in reraise

    raise value

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 699, in urlopen

    httplib_response = self._make_request(

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/connectionpool.py", line 394, in _make_request

    conn.request(method, url, **httplib_request_kw)

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/connection.py", line 239, in request

    super(HTTPConnection, self).request(method, url, body=body, headers=headers)

  File "/usr/local/lib/python3.10/http/client.py", line 1282, in request

    self._send_request(method, url, body, headers, encode_chunked)

  File "/usr/local/lib/python3.10/http/client.py", line 1328, in _send_request

    self.endheaders(body, encode_chunked=encode_chunked)

  File "/usr/local/lib/python3.10/http/client.py", line 1277, in endheaders

    self._send_output(message_body, encode_chunked=encode_chunked)

  File "/usr/local/lib/python3.10/http/client.py", line 1037, in _send_output

    self.send(msg)

  File "/usr/local/lib/python3.10/http/client.py", line 975, in send

    self.connect()

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/connection.py", line 205, in connect

    conn = self._new_conn()

  File "/home/flasktest/venv/lib/python3.10/site-packages/urllib3/connection.py", line 186, in _new_conn

    raise NewConnectionError(

urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7f73470be7d0>: Failed to establish a new connection: [Errno 111] Connection refused

And this is the MySQL container (mysql_test) log:这是 MySQL 容器(mysql_test)日志:

2021-12-20T18:13:14.094155Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.

2021-12-20T18:13:14.098891Z 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.

2021-12-20T18:13:14.110089Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock

2021-12-20T18:13:14.110149Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.27'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.

mbind: Operation not permitted

mbind: Operation not permitted

2021-12-20 18:13:10+00:00 [Note] [Entrypoint]: Creating database test_db

2021-12-20 18:13:10+00:00 [Note] [Entrypoint]: Creating user test_user

2021-12-20 18:13:10+00:00 [Note] [Entrypoint]: Giving user test_user access to schema test_db


2021-12-20 18:13:10+00:00 [Note] [Entrypoint]: Stopping temporary server

2021-12-20 18:13:13+00:00 [Note] [Entrypoint]: Temporary server stopped


2021-12-20 18:13:13+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.

Here is the starting point of Python application (microblog.py):这里是Python应用的起点(microblog.py):

from app_pkg import create_app, cli

app = create_app()
cli.register(app)

Here is the model class:这是 model class:

class User(UserMixin, SearchableMixin, db.Model):
    __searchable__ = ['username']
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    posts = db.relationship('Post', backref='author', lazy='dynamic')
    about_me = db.Column(db.String(140))
    last_seen = db.Column(db.DateTime, default=datetime.utcnow)
    followed = db.relationship(
        'User', secondary=followers,
        primaryjoin=(followers.c.follower_id == id),
        secondaryjoin=(followers.c.followed_id == id),
        backref=db.backref('followers', lazy='dynamic'), lazy='dynamic')

This is my compose.yaml:这是我的 compose.yaml:

version: '3'

services:

  python_app:
    container_name: flask_test
    build: .
    env_file: .env
    ports:
      - 8000:5000
    links:
      - mysqldb:dbserver
    depends_on:
      mysqldb:
        condition: service_healthy

  mysqldb:
    container_name: mysql_test
    image: mysql:latest
    env_file: database.conf
    volumes:
      - db-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
      interval: 3s
      retries: 5
      start_period: 30s

volumes:
  db-data:

This is my Dockerfile:这是我的 Dockerfile:

FROM python:slim

RUN useradd flasktest

WORKDIR /home/flasktest

COPY requirements.txt requirements.txt
RUN python -m venv venv
RUN venv/bin/pip install -r requirements.txt
RUN venv/bin/pip install gunicorn pymysql cryptography

COPY app_pkg app_pkg
COPY migrations migrations
COPY microblog.py config.py boot.sh ./
RUN chmod +x boot.sh

ENV FLASK_APP microblog.py

RUN chown -R flasktest:flasktest ./
USER flasktest

EXPOSE 5000
ENTRYPOINT ["./boot.sh"]

And finally, this is the boot.sh:最后,这是 boot.sh:

#!/bin/bash

source venv/bin/activate
while true; do
    flask db upgrade
    if [[ "$?" == "0" ]]; then
        break
    fi
    echo Upgrade command failed, retrying in 5 secs...
    sleep 5
done
exec gunicorn -b :5000 --access-logfile - --error-logfile - microblog:app

And these are some necessary environment variables that are being used in the application:这些是应用程序中使用的一些必要的环境变量:

DATABASE_URL=mysql+pymysql://test_user:abc123@dbserver/test_db
MYSQL_ROOT_PASSWORD=root123
MYSQL_DATABASE=test_db
MYSQL_USER=test_user
MYSQL_PASSWORD=abc123

Sorry if the question has become too lengthy.对不起,如果问题变得太长了。 I wanted to give as much detail as possible in the question.我想在问题中提供尽可能多的细节。 Let me know if any other details is required.让我知道是否需要任何其他详细信息。 I have been trying to debug this issue for the past week, but am unable to find a way to connect the app with the sql server.过去一周我一直在尝试调试此问题,但无法找到将应用程序与 sql 服务器连接的方法。

Also let me know if I should try any specific method to try to debug this issue.也让我知道我是否应该尝试任何特定的方法来尝试调试此问题。

You are currently using the docker-compose dns feature in which you can use the container name as domain name for services running in docker-compose, thats neat - unless when you rename containers;) Did you rename the mysqldb from dbserver?您当前正在使用 docker-compose dns 功能,其中您可以使用容器名称作为在 docker-compose 中运行的服务的域名,这很整洁 - 除非您从 dbserver 重命名 mysqldb;)您是否重命名了 mysqldb?

If you want to continue using this feature, modify the env vars as so: (change dbserver to mysqldb)如果您想继续使用此功能,请将环境变量修改为:(将 dbserver 更改为 mysqldb)

DATABASE_URL=mysql+pymysql://test_user:abc123@mysqldb/test_db
...

If you instead what to use a more explicit approach:如果您改为使用更明确的方法:

In your docker-compose, you need to bind the port 3306 to your host network by在您的 docker-compose 中,您需要通过以下方式将端口 3306 绑定到您的主机网络

version: '3'

services:

  python_app:
    container_name: flask_test
    build: .
    env_file: .env
    ports:
      - 8000:5000
    links:
      - mysqldb:dbserver
    depends_on:
      mysqldb:
        condition: service_healthy

  mysqldb:
    container_name: mysql_test
    image: mysql:latest
    env_file: database.conf
    volumes:
      - db-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
      interval: 3s
      retries: 5
      start_period: 30s
    ports:
      - 3306:3306
...

Then change the env var to:然后将环境变量更改为:

DATABASE_URL=mysql+pymysql://test_user:abc123@0.0.0.0/test_db

Thanks for all the info, you did not post too much - needed it all:)感谢您提供的所有信息,您没有发布太多信息 - 全部需要:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM