如果我在内部网络中尝试 运行,为什么 "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
选项。
我尝试 运行 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
选项。