Docker 无法将应用程序连接到 MySQL

and*_*rew 2 python mysql docker dockerfile docker-compose

我正在尝试运行依赖于 mysql 的集成测试(在 python 中)。目前它们依赖于在本地运行的 SQL,但我希望它们依赖于在 docker 中运行的 MySQL。

Dockerfile 的内容:

FROM continuumio/anaconda3:4.3.1
WORKDIR /opt/workdir
ADD . /opt/workdir
RUN python setup.py install
Run Code Online (Sandbox Code Playgroud)

Docker Compose 的内容:

version: '2'

services:
   mysql:
     image: mysql:5.6
     container_name: test_mysql_container
     environment:
       - MYSQL_ROOT_PASSWORD=test
       - MYSQL_DATABASE=My_Database
       - MYSQL_USER=my_user
       - MYSQL_PASSWORD=my_password
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     expose:
       - "3306"

   my_common_package:
     image: my_common_package
     depends_on:
       - mysql
     restart: always
     links:
       - mysql

volumes:
  db_data:
Run Code Online (Sandbox Code Playgroud)

现在,我尝试使用以下命令在我的包中运行测试:

docker-compose run my_common_package python testsql.py
Run Code Online (Sandbox Code Playgroud)

我收到错误

pymysql.err.OperationalError: (2003, "无法连接到 MySQL 服务器上的 'localhost' ([Errno 99] 无法分配请求的地址)")

Gri*_*mmy 5

docker-compose 默认会创建虚拟网络,如果 compose 文件中的所有容器/服务都可以通过 IP 地址相互访问。通过使用links,depends_on或网络别名,他们可以通过主机名相互联系。在您的情况下,主机名是服务名称,但这可以被覆盖。(见:文档

然后,您在my_common_package容器/服务中的脚本应根据您的设置连接到mysql端口3306。(不在localhost端口3306

另请注意,expose仅当服务的 Dockerfile 没有EXPOSE声明时才需要使用。标准的 mysql 镜像已经做到了这一点。

如果要将容器端口映射到localhost您需要使用ports,但仅在必要时才执行此操作。

services:
   mysql:
     image: mysql:5.6
     container_name: test_mysql_container
     environment:
       - MYSQL_ROOT_PASSWORD=test
       - MYSQL_DATABASE=My_Database
       - MYSQL_USER=my_user
       - MYSQL_PASSWORD=my_password
     volumes:
       - db_data:/var/lib/mysql
     ports:
       - "3306:3306"
Run Code Online (Sandbox Code Playgroud)

这里我们说 mysql 容器中的端口 3306 应该映射到端口 3306 上的 localhost。

现在您可以使用localhost:3306docker 之外的方式连接到 mysql 。例如,您可以尝试在testsql.py本地运行(不在容器中)。

容器到容器的通信将始终使用每个容器的主机名进行。将容器视为虚拟机。

您甚至可以找到使用docker network list以下命令创建的网络 docker-compose :

1b1a54630639        myproject_default             bridge              local
82498fd930bb        bridge                        bridge              local
Run Code Online (Sandbox Code Playgroud)

..然后用docker network inspect <id>来看细节。

为容器分配的 IP 地址可能非常随机,因此容器到容器通信的唯一可行方法是使用主机名。