duanjian4698
duanjian4698
2019-04-12 11:47
浏览 619

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

I've run into an interesting issue where there seems to be a difference between the docker run command and using docker-compose.

I have two Docker containers, one is an Apache website with PHP, the other a MySQL. I use the following commands to run the containers:

Website:

docker run -p 8080:80 -d website_local

MySQL:

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

Looking at the Docker ecosystem I can see them both running:

$ 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

I have setup a PDO connection to the database, using the name for the MySQL Docker container:

PHP: (the USER and PASS are correct and yes, I know I shouldn't use the root's credentials)

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();
    }

When attempting to connect to the database I get the following error:

SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: Name or service not known

If I replace host in the connections string with the Docker IP address (172.17.0.3) of the container it connects properly.

Now it gets interesting. If I bring up the containers using 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"

The PHP function connects correctly using the name of the Docker container (mysql5725), but cannot connect using the IP address of the Docker container.

Many times in a testing environment I only want to stop and rebuild certain containers, especially when dealing with more than two Docker images. I should only have to use the resource's name when making a connection because there is no guarantee the network will assign the same IP addresses to containers every time.

Why should these two methods of launching Docker containers produce different results? Is there a way to 'normalize' this, so connecting by name will work no matter how the container is launched?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • doudongdang4483
    doudongdang4483 2019-04-12 12:33
    已采纳

    Docker Compose automatically sets up a network for you:

    By default Compose sets up a single network for your app. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name.

    The default bridge network that Docker creates on its own doesn't provide DNS so you can't use it to connect to containers using their names. You'll probably want to set up a network yourself, e.g. with

    docker network create mynetwork
    

    and then connect your containers to it, e.g. with

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

    Note that this isn't the only difference between Docker Compose and manually running containers.

    点赞 评论

相关推荐