Docker web 和 apis 拒绝连接

Posted

技术标签:

【中文标题】Docker web 和 apis 拒绝连接【英文标题】:Docker web and apis refusing connection 【发布时间】:2019-02-14 04:58:03 【问题描述】:

我对 docker 很陌生。我创建了一个 docker-compose,它有 1 个主应用程序(laravel)站点和 2 个 api。

我正在尝试从 laravel 站点访问 api,但不断得到:

cURL error 7: Failed to connect to 0.0.0.0 port 8082: Connection refused (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

我的 docker-compose.yml 是:

version: '3'
services:
  web:
    image: nginx:1.10
    volumes:
    - ./vhost.conf:/etc/nginx/conf.d/default.conf
    ports:
    - "8080:80"
    depends_on:
    - app
    restart: always

  app:
    build: . #run the dockerfile to install whatever
    env_file: .env
    volumes:
    - ./:/var/www
    depends_on:
    - database

  web-api2:
    image: nginx:1.10
    volumes:
    - ../api/api2/vhost.conf:/etc/nginx/conf.d/default.conf
    ports:
    - "8081:81"
    depends_on:
    - app-api2

  app-api2:
    build: . #run the dockerfile to install whatever
    env_file: .env
    volumes:
    - ../api/api2:/var/www
    depends_on:
    - database

  web-api1:
    image: nginx:1.10
    volumes:
    - ../api/api1/vhost.conf:/etc/nginx/conf.d/default.conf
    ports:
    - "8082:82"
    depends_on:
    - app-api1

  app-api1:
    build: . #run the dockerfile to install whatever
    env_file: ../api/api1/.env
    volumes:
    - ../api/api1:/var/www
    depends_on:
    - database

  database:
    image: mysql:5.7
    environment:
    - "MYSQL_ROOT_PASSWORD=IAmSoSecure"
    - "MYSQL_DATABASE=my_app"
    ports:
    - "33061:3306"
    volumes:
    - my_app:/var/lib/mysql
    restart: always


volumes:
  wildfire:

我研究了 docker 网络,但我的尝试失败了。我有一个网络设置,并尝试使用子网,但它没有成功:

"IPAM": 
        "Driver": "default",
        "Options": ,
        "Config": [
            
                "Subnet": "172.18.0.0/16",
                "Gateway": "172.18.0.1"
            
        ]
    ,

我也尝试过访问我启用的端口:

"Ports": 
            "443/tcp": null,
            "80/tcp": null,
            "82/tcp": [
                
                    "HostIp": "0.0.0.0",
                    "HostPort": "8082"
                
            ]
        ,

我像往常一样通过 Guzzle 请求通话:

$client = new Client();
$res = $client->get('127.0.0.1:8082/accounts');
dd($res->getBody()->getContents());

我尝试了不同的 IP,但找不到要使用的正确 IP。

我当前的 vhost.conf 是:

server 
listen 80;
index index.php server.php;
root /var/www/public;

add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";

index index.html server.php index.php;

charset utf-8;

location / 
    try_files $uri $uri/ /index.php?$query_string;


location = /favicon.ico  access_log off; log_not_found off; 
location = /robots.txt   access_log off; log_not_found off; 

error_page 404 /index.php;

location ~ \.php$ 
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass app:9000;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    #fastcgi_param PATH_INFO $fastcgi_path_info;
    include fastcgi_params;
    include  /etc/nginx/mime.types;


location ~ /\.(?!well-known).* 
    deny all;


location ~ \.css 
    add_header  Content-Type    text/css;


location ~ \.js 
    add_header  Content-Type    application/x-javascript;


【问题讨论】:

您是否尝试过运行docker-compose down,然后再次运行docker-compose up 不幸的是,将其关闭并再次打开似乎并没有奏效。大声笑... 由于您使用的是 8082 端口,我假设您有一个容器试图联系 app-api2。尝试将127.0.0.1 替换为app-api2 【参考方案1】:

在您的 docker compose 上,您启动 3 个 nginx:web、web-api2 和 web-api1。

根据你写的,web-api2 监听 81 端口,web-api1 监听 82 端口。

如果您想从 web 中的应用程序访问 api,您需要使用:

http://web-api2:81/...
http://web-api1:82/...

请注意,在您的本地计算机上,您将使用 http://localhost:8081http://localhost:8082 将 web-api2 上的端口 8081 映射到 81 以及 web-api1 上的 8082 到 82。

【讨论】:

【参考方案2】:

在 docker compose 创建的默认网络上,编排器管理的每个容器都可以通过其服务名称访问,该名称恰好与docker-compose.yaml 文件中为其指定的名称相同。因此,在您的情况下,同一网络上的每个容器都可能会到达 app-api2 作为您的问题详细信息:

http://app-api2:82/accounts

对于在容器内使用 127.0.0.1 的更完整答案意味着您正在尝试访问容器本身内的服务并在您的情况下侦听 82。由于您没有其他可执行文件在同一容器中运行并在该端口上侦听,因此您正确接收到Connection refused

了解您并不严格需要公开docker-compose.yaml文件中的端口以供同一网络上的其他容器进行通信,这对您也很有用。暴露的端口使您可以从主机发出请求(实际上您可以使用127.0.0.1)。

如果您出于某种原因确实想使用容器的 IP 地址在容器之间进行通信,那么您可以使用 docker inspect <container name> 找到特定容器的当前 IP。但请注意,此 IP 是短暂的,并且可能会在每次容器启动时发生变化。

更多详细信息可以找到https://docs.docker.com/compose/networking

【讨论】:

这是否也会影响尝试将 CSS 或公共资产加载到网页中?因为现在这似乎是一个问题...... GET localhost:8080/vendor/adminlte/dist/css/skins/… net::ERR_ABORTED 404(未找到)帐户:11 GET localhost:8080/css/app.css net::ERR_ABORTED 404(未找到)帐户:10 GET localhost:8080/vendor/adminlte/vendor/bootstrap/dist/css/… net:: ERR_ABORTED 404(未找到)我只能假设 nginx 看不到我的公共或存储目录? nginx 容器可能没有挂载你的静态资产。但是,如果没有看到 nginx 配置,很难说出这是如何设置的 将我当前的 vhost.conf 添加到原始问题中【参考方案3】:

为了解决这个问题,我将正在查看的网址更改为:

$client = new Client();
$res = $client->get('**http://web-api2:82/accounts**');
dd($res->getBody()->getContents());

为了获得最佳实践,我还将端口号更改为 8082。这也反映在我的 docker-compose.yml 中:

web 8080:8080
web-api1 8081:8081
web-api2 8082:8082

感谢大家的回答!

【讨论】:

以上是关于Docker web 和 apis 拒绝连接的主要内容,如果未能解决你的问题,请参考以下文章

尝试连接数据库和 Web 容器时 SQLAlchemy 连接被拒绝

Spring Boot,Java,Docker Compose,尝试在两个容器(mysql,my-api)之间建立连接时出现“连接被拒绝”

Cordova Angular 访问 Web Api 连接被拒绝

使用go webservice在docker中连接到mysql时连接被拒绝

如何通过 docker 将 API 与 Web SPA 连接起来

Nginx 错误失败(111:连接被拒绝)同时连接到上游,docker-compose nodejs