Docker, PHP PDO и Single MySQL Container (невозможно подключиться по имени контейнера) - PullRequest
2 голосов
/ 12 апреля 2019

Я столкнулся с интересной проблемой, в которой, кажется, есть разница между командой docker run и использованием docker-compose.

У меня есть два контейнера Docker, один из них - веб-сайт Apache с PHP,другой - 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

Я установил соединение PDO с базой данных, используя имя контейнера MySQL Docker:

PHP: (USER и PASS верны и да,Я знаю, что не должен использовать учетные данные root)

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 fail: Имя или служба не известны

Если я заменим host в строке соединений на IP-адрес Docker (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), но не может подключиться с использованием IP-адреса контейнера Docker.

Часто в тестовой среде я хочу останавливать и перестраивать только определенные контейнеры, особенно когда имеешь дело с более чем двумя образами Docker.Я должен использовать имя ресурса только при установлении соединения, потому что нет гарантии, что сеть будет каждый раз назначать контейнеры одни и те же IP-адреса.

Почему эти два метода запуска контейнеров Docker дают разные результаты?Есть ли способ «нормализовать» это, поэтому подключение по имени будет работать независимо от того, как запущен контейнер?

1 Ответ

3 голосов
/ 12 апреля 2019

Docker Compose автоматически настраивает сеть для вас :

По умолчанию Compose настраивает одну сеть для вашего приложения.Каждый контейнер для службы присоединяется к сети по умолчанию и одновременно доступен другими контейнерами в этой сети и обнаруживается ими с именем хоста, идентичным имени контейнера.

Мостовая сеть по умолчанию, которую Docker создает самостоятельно , не предоставляет DNS , поэтому вы не можете использовать его для подключения к контейнерам, используя их имена.Возможно, вы захотите настроить сеть самостоятельно, например, с помощью

docker network create mynetwork

, а затем подключите к ней свои контейнеры , например, с помощью

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

Обратите внимание, что это не единственное отличие между Docker Compose и контейнерами, запускаемыми вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...