简体   繁体   English

Docker 组成端口映射,主机端口!=容器端口

[英]Docker compose port mapping, host port != container port

How can I make curl http://barfoo:8002 work from the foobar-container, without making changes to the docker file?如何使curl http://barfoo:8002从 foobar 容器工作,而不更改 docker 文件?

I have the following compose file:我有以下撰写文件:

version: '3'
services:
  foobar:
    build:
      context: ./foobar
    ports:
      - 8001:80
    depends_on:
      - barfoo
  barfoo:
    build:
      context: ./barfoo
    ports:
      - 8002:80

And I added the following to my hosts file on my computer我将以下内容添加到计算机上的主机文件中

127.0.0.1     foobar
127.0.0.1     barfoo

Now I start this project with docker-compose up .现在我用docker-compose up开始这个项目。

When I execute the following on my terminal, this logically works without any problem: curl http://barfoo:8002当我在终端上执行以下命令时,这在逻辑上没有任何问题: curl http://barfoo:8002

When I do the same from a Bash in the foobar container ( docker-compose exec foobar /bin/bash ) I get Failed to connect to barfoo port 8002: Connection refused , If I use curl http://barfoo:80 it works. When I do the same from a Bash in the foobar container ( docker-compose exec foobar /bin/bash ) I get Failed to connect to barfoo port 8002: Connection refused , If I use curl http://barfoo:80 it works.

The reason why is that I want to simulate a production like situation, where in production there is no port needed since they use a different hostname and both can use port 80 directly原因是我想模拟类似生产的情况,在生产中不需要端口,因为它们使用不同的主机名,并且都可以直接使用端口 80

How can I make curl http://barfoo:8002 work from the foobar-container, without making changes to the docker file?如何使 curl http://barfoo:8002从 foobar 容器工作,而不更改 docker 文件?

Simple solution is to map host port 8002 to barfoo port 8002. But that's probably not what you want.简单的解决方案是将 map 主机端口 8002 到barfoo端口 8002。但这可能不是您想要的。

barfoo is service name registered in internal docker dns accessible only by the services ( foobar ) within the same docker network created when you run docker-compose up barfoo是在内部 docker dns 中注册的服务名称,只能由同一docker-compose up网络中的服务( foobar )访问

8002 is port mapped to the docker host. 8002 是映射到 docker 主机的端口。

So when you run curl http://barfoo:8002 from foobar container you try to connect to service barfoo to port 8002. However barfoo listens on port 80 inside the container and not on 8002.因此,当您从foobar容器运行curl http://barfoo:8002时,您尝试将服务barfoo连接到端口 8002。但是barfoo侦听容器内的端口 80 而不是 8002。

Another solution:另一种解决方案:

You can add network_mode: host to barfoo and foobar .您可以将network_mode: host添加到barfoofoobar

  foobar:
    build:
      context: ./foobar
    network_mode: host
    ports:
      - 8001:80
    depends_on:
      - barfoo
  barfoo:
    build:
      context: ./barfoo
    network_mode: host
    ports:
      - 8002:80

But then foobar would need to connect using localhost:8002但是foobar需要使用localhost:8002进行连接

The reason why is that I want to simulate a production like situation, where in production there is no port needed since they use a different hostname and both can use port 80 directly原因是我想模拟类似生产的情况,在生产中不需要端口,因为它们使用不同的主机名,并且都可以直接使用端口 80

If that's really what you want, a better alternative would be to use docker stack.如果这确实是您想要的,更好的选择是使用 docker 堆栈。

And your services would be docker swarm services:您的服务将是docker 群服务:

You can deploy them using:您可以使用以下方式部署它们:

docker deploy --compose-file path_to_compose_file

Then foobar would connect to barfoo using service name and port barfoo:80然后foobar将使用服务名称和端口barfoo:80连接到barfoo

For now, a possible workaround is to overwrite the command in the docker-compose.yml so that it the process in it listens to port 8002 instead of 80.目前,一种可能的解决方法是覆盖 docker-compose.yml 中的command ,以便其中的进程侦听端口 8002 而不是 80。

version: '3'
services:
  foobar:
    build:
      context: ./foobar
    ports:
      - 8001:80
    depends_on:
      - barfoo
  barfoo:
    build:
      context: ./barfoo
    ports:
      - 8002:8002
    command: 'some-service --port 8002'

But I would be more than happy to accept a better solution/answer for this one.但我很乐意为此接受一个更好的解决方案/答案。

When you execute curl http://barfoo:8002 from your terminal, you are hitting the local port 8002 of your computer, which is forwarding port 80 of your container.当您从终端执行curl http://barfoo:8002时,您将访问计算机的本地端口 8002,该端口正在转发容器的端口 80。

The foobar container, however, is hitting the container port directly, which is listening on port 80 alone.但是, foobar 容器直接访问容器端口,该端口仅在端口 80 上侦听。

You can achieve what you are trying to do by adding another container to the docker-compose.yaml, which will act as a reverse proxy in front of the barfoo container.您可以通过将另一个容器添加到 docker-compose.yaml 来实现您想要做的事情,它将充当 barfoo 容器前面的反向代理。

The new docker-compose will look something like this -新的 docker-compose 看起来像这样 -

version: '3'
services:
  foobar:
    build:
      context: ./foobar
    ports:
      - 8001:80
    depends_on:
      - barfoo
  barfoo-host:
    build:
      context: ./barfoo
    ports:
      - 8002:80
  barfoo:
    image: custom-nginx:latest

And the custom-nginx image should be built like so -并且 custom-nginx 图像应该像这样构建 -

FROM nginx:1.17-alpine
COPY nginx.conf /etc/nginx/
EXPOSE 8002
CMD ["nginx", "-g", "daemon off;"]

Using this as the nginx.conf file -将其用作nginx.conf文件 -

user                            root;
worker_processes                auto;

error_log                       /var/log/nginx/error.log warn;

events {
    worker_connections          1024;
}

http {
    include                     /etc/nginx/mime.types;
    default_type                application/octet-stream;
    sendfile                    off;
    access_log                  off;
    keepalive_timeout           3000;
    server {
        listen                  8002;
        root                    /usr/share/nginx/html;
        server_name             barfoo;
        location / {
            proxy_pass http://barfoo-host;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM