我最近决定将开发环境从本地Mac迁移到Mac的docker,我希望多个项目公开相同的端口80,以便我可以简单地键入http://app1.dev/和{{3} },而不会记住数十个端口号。
我无需在本机环境上执行任何操作即可达到此目的。但是,由于现在nginx在每个容器中分别运行,因此它们在端口公开时会发生冲突。 我也知道我可以使用到外部容器的外部链接,但我不想拆开docker-compose.yml文件,我只想将所有内容都打包在一起。
version: '3'
services:
web:
image: nginx:alpine
ports:
- "80:80"
# ...
version: '3'
services:
web:
image: nginx:alpine
ports:
- "80:80"
# ...
当我在demo2中发出命令docker-compose up -d
时,我得到了:
Creating network "demo2_default" with the default driver
Creating demo2_web_1 ... error
ERROR: for demo2_web_1 Cannot start service web: driver failed
programming external connectivity on endpoint demo2_web_1
(cbfebd1550e944ae468a1118eb07574029a6109409dd34799bfdaf72cdeb3d35):
Bind for 0.0.0.0:80 failed: port is already allocated
ERROR: for web Cannot start service web: driver failed programming
external connectivity on endpoint demo2_web_1
(cbfebd1550e944ae468a1118eb07574029a6109409dd34799bfdaf72cdeb3d35):
Bind for 0.0.0.0:80 failed: port is already allocated
ERROR: Encountered errors while bringing up the project.
是否有任何方法可以使它们共享相同的端口,或者可以将端口从主机重新映射到容器,而无需使用额外的命令来创建外部容器? 还是有办法在docker-compose.yml文件中创建外部容器?
答案 0 :(得分:2)
您不能将多个容器端口映射到同一主机端口。如果首先尝试绑定同一端口,则首先出现的任何容器都将绑定到端口80,第二个容器将抛出已经在使用中的端口。
要解决此问题,您可以运行另一个虚拟 Nginx ,只需对{strong> demo1 和 demo2 做proxy_pass
。在这种情况下,http://app
将是父Nginx,/dev1
将是proxy_pass
至 demo1 ,而/dev2
将是proxy_pass
至 demo2 。
在这里,您只需要将父Nginx的端口绑定到主机即可。如果将所有这些端口都连接到同一网络并使用docker service discovery,则不需要绑定子Nginx的端口。如果遵循这些规则,那么您将命中another problem,即:Nginx将缓存使用服务发现解决的容器的IP,并将始终使用该IP来访问容器。重新启动子容器后,子容器的IP地址可能会更改,因此父Nginx会抛出 502 。为了解决这个问题,您每次重新启动 demo1 或 demo2 时,都必须重新启动父级Nginx。为了解决这个问题,您必须在父Nginx中使用resolver
作为127.0.0.11
并具有有效性。因此,每次Nginx尝试根据有效性尝试解析IP地址后解析。
我添加了虚拟配置文件,总结了以上所有要点。
父Nginx撰写:
version: '3'
services:
parent:
image: nginx:alpine
volume:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:80
networks:
default:
external:
name: dev
父Nginx配置(./nginx.conf):
server {
listen 80;
resolver 127.0.0.11 valid=5s; #this is local docker DNS and the internal IP getting resolved will be valid only for 5 seconds.
location /app/dev1 {
proxy_pass http://dev1:80;
}
location /app/dev2 {
proxy_pass http://dev2:80;
}
}
〜/ demo1 /
中的docker-compose.ymlversion: '3'
services:
web:
image: nginx:alpine
networks:
default:
aliases:
- dev1
networks:
default:
external:
name: dev
〜/ demo2 /
中的docker-compose.ymlversion: '3'
services:
web:
image: nginx:alpine
networks:
default:
aliases:
- dev2
networks:
default:
external:
name: dev
现在,您可以通过点击URL http://app/dev1来使用demo1,而使用http://app/dev2来访问demo2。
参考文献: