Docker,PHP PDO和单个MySQL容器(无法通过容器名称连接)

时间:2019-04-12 11:47:52

标签: php docker docker-compose

我遇到了一个有趣的问题,在docker run命令和使用docker-compose之间似乎有所不同。

我有两个Docker容器,一个是带有PHP的Apache网站,另一个是MySQL。我使用以下命令来运行容器:

网站:

docker run -p 8080:80 -d website_local

MySQL:

docker run -e MYSQL_ROOT_PASSWORD=RamaLamaDingDong --name=mysql5725 -d mysql:5.7.25

看看Docker生态系统,我可以看到它们都在运行:

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
849c421e750b        website_local       "/usr/sbin/apache2ct…"   19 minutes ago      Up 19 minutes       0.0.0.0:8080->80/tcp   pedantic_tesla
ccebba95693b        mysql:5.7.25        "docker-entrypoint.s…"   23 minutes ago      Up 23 minutes       3306/tcp, 33060/tcp    mysql5725

我已经使用MySQL Docker容器的名称建立了到数据库的PDO连接:

PHP:(USERPASS是正确的,是的,我知道我不应该使用根的凭据)

try {
        $dbh = new PDO('mysql:host=mysql5725;dbname=grocery;charset=utf8', USER, PASS);
        $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    catch(PDOException $e) {
        echo $e->getMessage();
        $errorCode = $e->getCode();
    }

尝试连接数据库时,出现以下错误:

  

SQLSTATE [HY000] [2002] php_network_getaddresses:getaddrinfo失败:名称或服务未知

如果我将连接字符串中的host替换为容器的Docker IP地址(172.17.0.3),则它会正确连接。

现在变得有趣了。如果我使用Docker Compose调出容器,则:

version: '3'

services:
  db:
    image: mysql:5.7.25
    container_name: mysql5725
    environment:
      MYSQL_ROOT_PASSWORD: RamaLamaDingDong
    ports:
      - "3306:3306"

  web:
    image: website_local:latest
    container_name: website_local
    depends_on:
      - db
    volumes:
      - ./website/www:/var/www/html/
    ports:
      - "8080:80"

PHP函数使用Docker容器的名称(mysql5725)正确连接,但是无法使用Docker容器的IP地址连接。

在测试环境中,很多时候我只想停止并重建某些容器,尤其是在处理两个以上的Docker映像时。连接时我只需要使用资源的名称,因为不能保证网络每次都会为容器分配相同的IP地址。

为什么这两种启动Docker容器的方法会产生不同的结果?有一种方法可以对此进行“规范化”,因此无论容器如何启动,通过名称进行连接都将起作用?

1 个答案:

答案 0 :(得分:3)

Docker Compose automatically sets up a network for you

  

默认情况下,Compose为您的应用设置一个network。服务的每个容器都加入默认网络,并且在该网络上的其他容器都可以可访问,在与该容器名称相同的主机名下,它们也可以可发现

Docker在自己的doesn't provide DNS上创建的默认桥接网络,因此您不能使用它来使用它们的名称连接到容器。您可能需要自己建立一个网络,例如与

docker network create mynetwork

,然后connect your containers,例如与

docker network connect mynetwork mysql5725
docker network connect mynetwork php-container

请注意,this isn't the only difference在Docker Compose和手动运行的容器之间。

相关问题