Docker 无法将应用程序连接到 MySQL
我正在尝试运行依赖于 mysql 的集成测试(在 python 中).目前它们依赖于在本地运行的 SQL,但我希望它们依赖于在 docker 中运行的 MySQL.
I am trying to run integration tests (in python) which depend on mysql. Currently they depend on SQL running locally, but I want them to depend on a MySQL running in docker.
Dockerfile 的内容:
Contents of Dockerfile:
FROM continuumio/anaconda3:4.3.1
WORKDIR /opt/workdir
ADD . /opt/workdir
RUN python setup.py install
Docker Compose 的内容:
Contents of 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:
现在,我尝试使用以下命令在我的包中运行测试:
Now, I try to run the tests in my package using:
docker-compose run my_common_package python testsql.py
我收到错误
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on'localhost' ([Errno 99] 无法分配请求的地址)")
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 99] Cannot assign requested address)")
推荐答案
docker-compose 默认会创建虚拟网络,如果 compose 文件中的所有容器/服务可以通过 IP 地址相互访问.通过使用links
、depends_on
或网络别名,他们可以通过主机名相互联系.在您的情况下,主机名是服务名称,但这可以被覆盖.(参见:docs)
docker-compose will by default create virtual network were all the containers/services in the compose file can reach each other by an IP address. By using links
, depends_on
or network aliases they can reach each other by host name. In your case the host name is the service name, but this can be overridden. (see: docs)
您在 my_common_package
容器/服务中的脚本应该根据您的设置连接到端口 3306
上的 mysql
.(不是端口 3306
上的 localhost
)
Your script in my_common_package
container/service should then connect to mysql
on port 3306
according to your setup. (not localhost
on port 3306
)
另请注意,仅当服务的 Dockerfile 没有 EXPOSE
语句时才需要使用 expose
.标准的 mysql 镜像已经这样做了.
Also note that using expose
is only necessary if the Dockerfile for the service don't have an EXPOSE
statement. The standard mysql image already does this.
如果要将容器端口映射到 localhost
,则需要使用 ports
,但仅在必要时才这样做.
If you want to map a container port to localhost
you need to use ports
, but only do this if it's necessary.
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"
这里我们说mysql容器中的3306端口应该映射到localhost的3306端口.
Here we are saying that port 3306 in the mysql container should be mapped to localhost on port 3306.
现在您可以在 docker 之外使用 localhost:3306
连接到 mysql.例如,您可以尝试在本地(不在容器中)运行 testsql.py
.
Now you can connect to mysql using localhost:3306
outside of docker. For example you can try to run your testsql.py
locally (NOT in a container).
容器到容器的通信将始终使用每个容器的主机名进行.将容器视为虚拟机.
Container to container communication will always happen using the host name of each container. Think of containers as virtual machines.
你甚至可以找到使用docker network list
创建的网络docker-compose:
You can even find the network docker-compose created using docker network list
:
1b1a54630639 myproject_default bridge local
82498fd930bb bridge bridge local
...然后使用docker network inspect
查看详情.
.. then use docker network inspect <id>
to look at the details.
分配给容器的 IP 地址可能非常随机,因此容器到容器通信的唯一可行方法是使用主机名.
Assigned IP addresses to containers can be pretty random, so the only viable way for container to container communication is using hostnames.
相关文章