如果我在内部网络中尝试 运行,为什么 "port is already allocated"?

Why "port is already allocated" if I try run within inner network?

我尝试 运行 3 个容器:nginx 和两个带有 flask-uwsgi 的容器,但一个用于暂存,一个用于实时。

在 docker 我创建网络:

docker network create --attachable --subnet 1.1.1.0/29 some-network

和 运行 容器,例如:

# nginx
docker run -d --rm \
       --net some-network --ip 1.1.1.2 \
       -p 80:80 -p 443:443 \
       --name my-nginx "$REGISTRY/$IMAGE"

# flask+uwsgi on :8080 (live)
docker run -d --rm \
      --net some-network --ip 1.1.1.3 \
      -p 8080:8080 \
      --name flask-live "$REGISTRY/$IMAGE"

而且我有上游的默认服务器配置:

upstream flask_live {
    server  1.1.1.3:8080;
}

upstream flask_dev {
    server  1.1.1.4:8080;
}


server {
    listen 80;
    server_name hostname.com;
    location / {
        include uwsgi_params;
        uwsgi_pass flask_live;
    }
}

server {
    listen 80;
    server_name develop.hostname.com;

    location / {
        include uwsgi_params;
        uwsgi_pass flask_dev;
    }
}

但是当我尝试 运行 第三个带有烧瓶的容器时,开发如下:

docker run -d --rm \
      --net some-network --ip 1.1.1.4 \
      -p 8080:8080 \
      --name flask-live "$REGISTRY/$IMAGE"

我收到错误消息:绑定 0.0.0.0:8080 失败:端口已分配
如果我尝试在 1.1.1.0/29 子网
上发布,我不明白为什么要分配端口 我阅读了 docker 有关网络的文档,我 google 的东西,但我只是盲目或行动迟缓,但我不明白如何“隔离”容器或类似的东西。

-p 8080:8080 等于 -p 0.0.0.0:8080:8080 其中:

  • 0.0.0.0 - 重定向自的主机地址
  • 第一个 8080 - 重定向端口
  • second 8080 - 集装箱港口(在 docker 网络内)

因此,您的错误消息表明您无法绑定到主机的端口 8080(不是您的内部 docker 网络)。

此命令允许您从主机网络访问容器(例如,从 localhost:8080 到容器的 8080 端口)。基本上,它使用 iptables 将数据包从一个网络重定向到另一个网络。因此,当您调用 -p 8080:8080 时,它会将数据包从端口 8080 重定向到您的第一个容器,而当您为第二个容器调用相同的命令时,它会失败,因为端口 8080 已被使用。您不能将单个端口同时重定向到两个容器。

根据您的描述,您甚至不需要将端口发布到您的 flask-uwsgi 容器,因为您有一个 nginx 代理,它允许您根据主机名访问它们。这些端口在您的 Docker 网络中仍然可用,您只是不会发布到您的主机 OS.

如果您仍然需要直接访问您的 flask-uwsgi 容器(没有 nginx),那么您可以将它们发布到不同的端口。例如。第一个 - -p 8081:8080,第二个 - -p 8082:8080).

docker run -p 选项在主机 上打开一个端口,转发到容器中的一个端口。这通常意味着您不能 运行 两个具有相同第一个 -p 端口号的容器,并且第一个端口号也不能与 运行 上的非容器进程冲突主持人

另外,Docker 维护自己的网络层。知道这一点很有用,作为一个实现细节,每个容器恰好都有自己的 IP 地址,因此您可以 运行 在单独的容器中处理,每个容器都侦听端口 8080,并且它们不会发生冲突。您不需要 -p 选项来执行此操作。

因此:连接 来自外部 Docker...

  • 使用主机的 DNS 名称或 IP 地址
  • 使用第一个 docker run -p 端口号(在所有容器和主机进程中必须是唯一的)
  • 容器内的进程必须侦听第二个 -p 端口号和特殊的 0.0.0.0“无处不在”IP 地址

连接容器之间...

  • 必须在同一个 docker run --net 网络上
  • 使用其他容器的 docker run --name 作为 DNS 名称
  • 使用目标容器进程正在侦听的端口号;它还必须监听特殊的 0.0.0.0“无处不在”IP 地址
  • 忽略 docker run -p 端口映射

请注意,这两种情况实际上都不需要知道容器私有 IP 地址,并且指定这些或查找它们通常没有用。在您的示例中,我将删除 docker network create --subnet 选项和 docker run --ip 选项。