ReactPHP和docker:无法解析从php到nginx容器的主机

时间:2017-09-05 11:31:19

标签: php docker nginx dns reactphp

我使用docker和微服务。想象一下,我们有3项服务:

          user API
        /
gateway API
        \
          hotel API

请求通过服务的网关。我有phpnginx的容器,其中卷是相同的。接下来我给出配置列表:

server {
    server_name gateway.api.loc;

    root /var/www/der-ibe/ibe-gateway-api/web;
    client_max_body_size 32m;

    location / {
        try_files $uri @rewriteapp;
    }

    location @rewriteapp {
        rewrite ^(.*)$ /app.php/$1 last;
    }

    location ~ ^/(app|app_dev|config)\.php(/|$) {
       ...
    }
}
server {
    server_name hotel.api.loc;
    root /var/www/der-ibe/ibe-hotel-api/web;
    client_max_body_size 32m;

    location / {
        try_files $uri @rewriteapp;
    }

    location @rewriteapp {
        rewrite ^(.*)$ /app.php/$1 last;
    }

    location ~ ^/(app|app_dev|config)\.php(/|$) {
        ...
    }
}

...

搬运工-compose.yml

version: "3.1" 
services:

    tphp:
        build: docker/php
        restart: always
        container_name: my_tphp
        extra_hosts:
            - gateway.api.loc:172.14.10.10
            - user.api.loc:172.14.10.10
            - hotel.api.loc:172.14.10.10
        networks:
            - test
        volumes:
            - ../user-api:/var/www/user-api
            - ../hotel-api:/var/www/hotel-api
            - ./:/var/www/gateway-api

    tnginx:
        build: docker/nginx
        restart: always
        container_name: my_tnginx
        ports:
            - 80:80
        networks:
            test:
                 ipv4_address: 172.14.10.10
        volumes:
            - ../user-api:/var/www/user-api
            - ../hotel-api:/var/www/hotel-api
            - ./:/var/www/gateway-api

networks:
    ibe:
      driver: bridge
      ipam:
        driver: default
        config:
          - subnet: 172.14.10.0/24

如果我使用简单的cURL,我可以联系酒店和用户api,我可以得到他们的回复,但是如果我尝试用reactPHP做的话 - 我不能!我的代码和平:

 public function asyncGetRequest(Route $route, $params, $token)
{
    $url = $this->buildURL($route, $params);

    $loop = React\EventLoop\Factory::create();

    $dns = '172.14.10.10';
    $sender = Clue\React\Buzz\Io\Sender::createFromLoopDns($loop, $dns);

    //$url = 'http://172.14.10.10:3000/api/quota/list';

    $client = new Clue\React\Buzz\Browser($loop, $sender);
    //$client = new Clue\React\Buzz\Browser($loop);

    $promise = $client->get($url,
        [
            'Authorization' => $token,
        ]
    );

    /** @var Response $response */
    $response = new Response();

    try {
        $response = Clue\React\Block\await($promise, $loop);
    } catch (ResponseException $e) {
        $this->logger->error($e->getMessage());
    }

    dump($response->getBody()->getContents()); // I work on symfony 3.2
    die;
}

线索库只是react的包装器。所以我得到的错误是: DNS query for hotel.api.loc timed out和最后一个错误An error occurred in the underlying stream

所以我有一个问题:我做错了什么?为什么我可以通过curl访问nginx容器,但是不能通过reactPHP访问?即使是点dns!

但如果我使用裸ip与端口我可以达到它。我不是dns的专家,只是基础知识。

更新

我使用Linux Debian(在容器中)。在Mac上工作。

关于逻辑:当请求URI在网关内gateway.api.loc/api/hotel/list时,我们向hotel.api.loc发送请求到同一个URL(/api/hotel/list),接受响应并返回它。

我再说一遍,我可以通过cURL访问域名,但无法使用reactPHP进行访问,并且不明白为什么......

2 个答案:

答案 0 :(得分:1)

您的问题是gateway.api.lochotel.api.loc没有DNS解析,它们在您的Nginx配置中定义用于路由,但在其他任何地方都没有用于DNS解析。您需要将撰写更改为以下,以便在docker DNS解析中解决它们

version: "3.1" 
services:

    tphp:
        build: docker/php
        restart: always
        container_name: my_tphp
        extra_hosts:
            - gateway.api.ibe.lazy-ants.loc:172.14.10.10
            - user.api.ibe.lazy-ants.loc:172.14.10.10
            - hotel.api.ibe.lazy-ants.loc:172.14.10.10
        networks:
            - test
        volumes:
            - ../user-api:/var/www/user-api
            - ../hotel-api:/var/www/hotel-api
            - ./:/var/www/gateway-api

    tnginx:
        build: docker/nginx
        restart: always
        container_name: my_tnginx
        ports:
            - 80:80
        networks:
            test:
                 ipv4_address: 172.14.10.10
                 aliases:
                     - hotel.api.loc
                     - gateway.api.loc
        volumes:
            - ../user-api:/var/www/user-api
            - ../hotel-api:/var/www/hotel-api
            - ./:/var/www/gateway-api

networks:
    ibe:
      driver: bridge
      ipam:
        driver: default
        config:
          - subnet: 172.14.10.0/24

此DNS解析仅适用于撰写内部而非外部。因此,如果您在外面使用它,那么您将必须进行主机条目

修改-1

看来你的问题可能只是代码。当它不是DNS服务器时,您尝试将网关IP用作DNS。

更改

$loop = React\EventLoop\Factory::create();

$dns = '172.14.10.10';
$sender = Clue\React\Buzz\Io\Sender::createFromLoopDns($loop, $dns);

//$url = 'http://172.14.10.10:3000/api/quota/list';

$client = new Clue\React\Buzz\Browser($loop, $sender);

$loop = React\EventLoop\Factory::create();

$dns = '172.14.10.10';
//$sender = Clue\React\Buzz\Io\Sender::createFromLoopDns($loop, $dns);
//$url = 'http://172.14.10.10:3000/api/quota/list';

$client = new Clue\React\Buzz\Browser($loop);

看看是否有帮助

答案 1 :(得分:0)

您看到的问题是ReactPHP的DNS实施不完整。它不尊重/etc/resolv.conf,最近只添加了对/etc/hosts的支持。如果你没有使用react/dns v0.4.11 or later那么这可能就是问题,你应该尝试升级。

我不确定Docker如何为链接容器解析DNS。多年前,它使用了一个提供主机名和相应IP的钩子/etc/hosts。但我想现在Docker正在使用内部DNS服务器。由于ReactPHP不会自动选择它,因此您必须在创建DNS解析器时明确设置它。

尝试将127.0.0.11设置为名称服务器,这是Docker的内部DNS。