如何在使用Docker的同时为多个项目共享(暴露)端口80 [英] How to share(expose) port 80 for multiple projects while using docker

查看:1847
本文介绍了如何在使用Docker的同时为多个项目共享(暴露)端口80的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近决定将开发环境从本地Mac迁移到Mac的Docker,并且我希望多个项目公开相同的端口80,以便我可以简单地键入 http://app2 .dev/在浏览器中,而不会记住数十个端口号.

I am recently decided to migrate my dev environment from native mac to docker for mac, and I would like to have multiple projects expose the same port 80, so that I can simply type http://app1.dev/ and http://app2.dev/ in the browser without remembering dozens of port numbers.

我无需在本机环境上执行任何操作即可达到此目的.但是,由于现在nginx在每个容器中分别运行,因此它们在端口公开时会发生冲突. 我也知道我可以使用到外部容器的外部链接,但我不想拆开docker-compose.yml文件,我只想将所有内容都打包在一起.

I don't have to do anything on native environment to achieve this. But since now nginx runs separately in each container they are conflicted on port exposing. I also know that I can use an external link to an external container but I don't want to tear apart my docker-compose.yml file, I just want everything in one piece.

version: '3'
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
# ... 

〜/demo2/

中的docker-compose.yml

docker-compose.yml in ~/demo2/

version: '3'
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
# ...

当我在demo2中发出命令docker-compose up -d时,我得到了:

When I issue command docker-compose up -d in demo2 I got:

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文件中创建外部容器?

Is there any way to make them share them same port or maybe remap ports from host to container without using extra commands to create external containers? Or is there a way to create external containers within the docker-compose.yml file?

推荐答案

您不能将多个容器端口映射到同一主机端口.如果首先尝试绑定同一端口,则首先出现的任何容器都将绑定到端口80,第二个容器将抛出已经在使用中的端口.

You cannot map multiple container ports to the same host port. Whatever container that comes up first will get binded to port 80 and the second container will throw port already in use if you try binding the same port.

要解决此问题,您可以运行另一个虚拟 Nginx ,只需对 demo1 demo2 进行proxy_pass即可.在这种情况下,http://app将是父Nginx,/dev1将是proxy_pass demo1 ,而/dev2将是proxy_pass demo2 .

To Address this issue you can run another dummy Nginx which simply does proxy_pass to demo1 and demo2. In this case, http://app will be parent Nginx and /dev1 will proxy_pass to demo1 and /dev2 will proxy_pass to demo2.

在这里,您只需要将父Nginx的端口绑定到主机即可.如果您将所有子Nginx的端口连接到同一网络并使用另一个问题,即:Nginx将缓存使用服务发现解决的容器的IP,并将使用该IP IP总是会碰到容器.重新启动子容器后,子容器的IP地址可能会更改,因此父Nginx会抛出 502 .为了解决这个问题,您每次重新启动 demo1 demo2 时,都必须重新启动父Nginx.为了解决这个问题,您必须在父Nginx中使用resolver作为127.0.0.11并具有有效性.因此,每次Nginx尝试根据有效性尝试解析IP地址后解析.

Here, You just need to bind parent Nginx's port to host. You don't need to bind ports of child Nginx if you connect all these to the same network and use docker service discovery. If you follow these then you will hit another problem i.e: Nginx will cache IP of containers resolved using service discovery and will use that IP to hit the containers always. Once the child container is restarted there is a possibility that the child's IP address might get changed, So parent Nginx throws 502. To solve this you have to restart parent Nginx each time whenever you restart demo1 or demo2. To solve this you have to use resolver as 127.0.0.11 with validity in parent Nginx. So each time Nginx will try resolving the IP address post last resolution according to validity.

我添加了虚拟配置文件,总结了以上所有要点.

I've added dummy config files summarising all the above points.

父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/

version: '3'
services:
  web:
    image: nginx:alpine
  networks:
    default:
       aliases:
          - dev1
networks:
  default:
    external:
      name: dev

〜/demo2/

version: '3'
services:
  web:
    image: nginx:alpine
  networks:
    default:
       aliases:
          - dev2
networks:
  default:
    external:
      name: dev

现在,您可以通过点击URL http://app/dev1 来使用demo1,并通过使用 http://app/dev2 .

Now you can use demo1 by hitting URL http://app/dev1 and demo2 by using http://app/dev2.

参考文献:

  1. NGINX反向代理
  2. NGINX proxy_pass
  3. NGINX解析器
  4. Docker DNS的必要性
  5. Docker容器联网
  1. NGINX Reverse Proxy
  2. NGINX proxy_pass
  3. NGINX resolver
  4. Necessity of docker DNS
  5. Docker container networking

这篇关于如何在使用Docker的同时为多个项目共享(暴露)端口80的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆