简体   繁体   English

如何从Docker容器中的python脚本连接到localhost上的mysql数据库

[英]How to connect to a mysql database on localhost from a python script in a docker container

I have a mysql database running on a localhost (ubuntu 16.04). 我有一个在本地主机(ubuntu 16.04)上运行的mysql数据库。 On the same host I have a docker container in which a python script is running. 在同一主机上,我有一个运行python脚本的docker容器。 This script has to connect to the mysqldb on the local host. 该脚本必须连接到本地主机上的mysqldb。 As was described in these posts ( post1 , post2 ) I set bind-address=0.0.0.0 for my local database and found the ip-address of my local host and used it in my python script to connect to the database, but it did not work. 如这些帖子( post1post2 )中所述,我为本地数据库设置了bind-address = 0.0.0.0,找到了本地主机的ip地址,并在python脚本中使用了它来连接到数据库,但是它确实不行。 Below I show my set-up and how I run the docker container. 下面显示了我的设置以及如何运行docker容器。 My python script (analysis.py) looks as follows: 我的python脚本(analysis.py)如下所示:

import pandas as pd
import sqlalchemy as db

def find_max_age():
   cnx = db.create_engine('mysql+mysqlconnector://root:password@172.17.0.1:3306/datasets')
   cnx_res = db.create_engine('mysql+mysqlconnector://root:password@172.17.0.1:3306/results')
   df = pd.read_sql("select * from test_table", cnx)
   idx = df['age'].idxmax() == df.index
   df_res = df[idx]

   df_res.to_sql('max_age4', con=cnx_res, index=False)


if __name__ == '__main__':
   find_max_age()

My Dockerfile looks as follwos: 我的Dockerfile看起来像:

FROM python:2.7-slim
EXPOSE 80 3306
WORKDIR /app
COPY requirements.txt /app
RUN pip install -r requirements.txt
COPY analysis.py /app
CMD python analysis.py

Finally, the requirements.txt looks like 最后,requirements.txt看起来像

mysql-connector-python
sqlalchemy
pandas

I build the docker image as follows: 我按如下方式构建docker映像:

docker build -t max_age_app .

Then I start the container using this image as follows: 然后,我使用此图像启动容器,如下所示:

docker run -d max_age_app:latest

The container exits with exit code 1 and when I take a look at the respective log of the container I find the following error in it: 容器以退出代码1退出,当我查看容器的相应日志时,发现其中存在以下错误:

> Traceback (most recent call last):
  File "analysis.py", line 24, in <module>
    find_max_age()
  File "analysis.py", line 11, in find_max_age
    df = pd.read_sql("select * from test_table", cnx)
  File "/usr/local/lib/python2.7/site-packages/pandas/io/sql.py", line 397, in read_sql
    chunksize=chunksize)
  File "/usr/local/lib/python2.7/site-packages/pandas/io/sql.py", line 1063, in read_query
    result = self.execute(*args)
  File "/usr/local/lib/python2.7/site-packages/pandas/io/sql.py", line 954, in execute
    return self.connectable.execute(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 2074, in execute
    connection = self.contextual_connect(close_with_result=True)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 2123, in contextual_connect
    self._wrap_pool_connect(self.pool.connect, None),
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 2162, in _wrap_pool_connect
    e, dialect, self)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1476, in _handle_dbapi_exception_noconnection
    exc_info
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 265, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 2158, in _wrap_pool_connect
    return fn()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.py", line 400, in connect
    return _ConnectionFairy._checkout(self)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.py", line 788, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.py", line 529, in checkout
    rec = pool._do_get()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.py", line 1193, in _do_get
    self._dec_overflow()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 66, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.py", line 1190, in _do_get
    return self._create_connection()
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.py", line 347, in _create_connection
    return _ConnectionRecord(self)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.py", line 474, in __init__
    self.__connect(first_connect_check=True)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/pool.py", line 671, in __connect
    connection = pool._invoke_creator(self)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/strategies.py", line 106, in connect
    return dialect.connect(*cargs, **cparams)
  File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 412, in connect
    return self.dbapi.connect(*cargs, **cparams)
  File "/usr/local/lib/python2.7/site-packages/mysql/connector/__init__.py", line 172, in connect
    return CMySQLConnection(*args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/mysql/connector/connection_cext.py", line 78, in __init__
    self.connect(**kwargs)
  File "/usr/local/lib/python2.7/site-packages/mysql/connector/abstracts.py", line 731, in connect
    self._open_connection()
  File "/usr/local/lib/python2.7/site-packages/mysql/connector/connection_cext.py", line 179, in _open_connection
    sqlstate=exc.sqlstate)
sqlalchemy.exc.DatabaseError: (mysql.connector.errors.DatabaseError) 2003 (HY000): Can't connect to MySQL server on '172.17.0.1' (111) (Background on this error at: http://sqlalche.me/e/4xp6)

In order to determine the ip of the localhost I used ifconfig command, which yielded something like this: 为了确定本地主机的IP,我使用了ifconfig命令,它产生了如下所示的内容:

docker0   Link encap:Ethernet  HWaddr 02:42:a2:a6:d7:ff  
          inet addr:172.17.0.1 

enp0s3    Link encap:Ethernet  HWaddr 08:00:27:bb:7e:b5  
          inet addr:10.0.2.15 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1 

So I tried 172.17.0.1 in order to connect to the local database from within the container but it did not work. 因此,我尝试了172.17.0.1,以便从容器内连接到本地数据库,但是它不起作用。

Do I have to match any ports between the container and the localhost via the -p option when I start the container? 启动容器时,是否需要通过-p选项匹配容器和localhost之间的任何端口?

I would appreciate any help. 我将不胜感激任何帮助。

You shouldn't EXPOSE the port 3306 on the container, since the MySQL server is listening outside it, on the localhost. 您不应该在容器上EXPOSE端口3306,因为MySQL服务器正在本地主机上监听它。 I suspect it's a networking issue, so try to see if the localhost has the interface with the address 172.17.0.1 and if you can reach this address from inside your container (ex. try docker exec -ti _your_container_name /bin/sh and then try ping 172.17.0.1 ). 我怀疑这是网络问题,因此请尝试查看本地主机是否具有地址为172.17.0.1的接口,以及是否可以从容器内部访问此地址(例如,尝试docker exec -ti _your_container_name /bin/sh ,然后尝试ping 172.17.0.1 )。 You should also check the mysql logs to see if you have some error reported there. 您还应该检查mysql日志,看看那里是否报告了一些错误。

In order to solve this problem one has to correctly configure the mysql database on the localhost. 为了解决这个问题,必须在本地主机上正确配置mysql数据库。 In addition to what was discussed above one has to do the following steps: 除了上面讨论的内容外,还必须执行以下步骤:

  • Find the IP-address of your docker container with the python app. 使用python应用程序找到您的Docker容器的IP地址。 You can use docker inspect <container_name> . 您可以使用docker inspect <container_name>
  • Create in your local mysql database a new user (and a respective password) for that IP-address. 在本地mysql数据库中为该IP地址创建一个新用户(和相应的密码)。 Info on how to do it you can find in this post . 如何做到这一点的信息,你可以在此找到职位 How to set password policies in mysql is described here . 这里描述如何在mysql中设置密码策略。

Afterwards, simply starting the container with the command docker run -d max_age_app will suffice for the python script to write the data into the database on the localhost. 然后,只需使用命令docker run -d max_age_app启动容器,Python脚本就足以将数据写入本地主机上的数据库。

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

相关问题 无法使用 Python 脚本连接到 Docker 上的 MySQL 数据库容器 - Cannot connect to MySQL database container on Docker with Python script 将 python 脚本连接到 docker 中的 mysql - Connect python script to mysql in docker 如何从 ZC5FD214CDD0D2B3B4272E 中的 python 容器脚本连接到 Ubuntu 上的本地 SQL 服务器 - How do I connect to the local SQL server on Ubuntu from a python script in Docker container Python脚本(PyMySQL)无法连接到本地主机上的数据库 - Python script (PyMySQL) does not connect to database on localhost 如何使用 DATABASE_URL 将 Docker 容器连接到在本地主机上运行的 PostgreSQL? - How to connect a Docker container to PostgreSQL running on the localhost using a DATABASE_URL? 使用Python连接到Docker容器中的MySQL - Connect to MySQL in Docker container using Python Ansible 可以从 localhost 连接到 windows 机器,但不能从 docker 容器连接 - Ansible can connect to windows machine from localhost but not from docker container 如何在docker容器中连接外部mysql服务器 - How to connect external mysql server in docker container 如何通过运行带有URL的docker容器来连接docker容器中的python应用 - how to connect python app in docker container with running docker container with url 如何使用 Python 脚本从 Docker 容器中保存输出 JSON 文件 - How to save output JSON file from a Docker container with Python script
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM