Docker撰写端口映射,主机端口!=容器端口

时间:2019-11-04 11:37:04

标签: docker docker-compose docker-networking

如何在不更改docker文件的情况下使curl http://barfoo:8002从foobar容器工作?

我有以下撰写文件:

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

然后我将以下内容添加到计算机上的主机文件中

127.0.0.1     foobar
127.0.0.1     barfoo

现在,我从docker-compose up开始这个项目。

当我在终端上执行以下命令时,这在逻辑上没有任何问题:curl http://barfoo:8002

当我从foobar容器(docker-compose exec foobar /bin/bash)中的Bash进行相同操作时,我得到Failed to connect to barfoo port 8002: Connection refused,如果我使用curl http://barfoo:80,它将起作用。

原因是我想模拟一个类似生产的情况,在生产中不需要端口,因为它们使用不同的主机名,并且两者都可以直接使用端口80

3 个答案:

答案 0 :(得分:1)

目前,可能的解决方法是覆盖docker-compose.yml中的logout().type,以使其中的进程侦听端口8002而不是端口80。

command

但是我很乐意接受一个更好的解决方案/答案。

答案 1 :(得分:1)

当您从终端执行curl http://barfoo:8002时,您正在命中计算机的本地端口8002,该端口正在转发容器的端口80。

但是,foobar容器正在直接命中容器端口,该端口仅在端口80上侦听。

您可以通过在docker-compose.yaml中添加另一个容器来实现您想要的工作,该容器将充当barfoo容器前面的反向代理。

新的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

并且应该像这样构建custom-nginx图像-

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

将其用作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;
        }
    }
}

答案 2 :(得分:0)

  

如何在不更改docker文件的情况下使foobar容器中的curl http://barfoo:8002工作?

简单的解决方案是将主机端口8002映射到barfoo端口8002。但这可能不是您想要的。

barfoo是在内部docker dns中注册的服务名称,该名称只能由运行foobar

时创建的同一docker网络中的服务(docker-compose up)访问。

8002已端口映射到Docker主机。

因此,当您从curl http://barfoo:8002容器运行foobar时,您尝试将服务barfoo连接到端口8002。但是barfoo监听容器内部的端口80,而不监听8002。

另一种解决方案:

您可以将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

但是foobar则需要使用localhost:8002

进行连接
  

原因是我想模拟类似生产的情况,   在生产中不需要端口的地方,因为它们使用不同的端口   主机名,都可以直接使用端口80

如果这确实是您想要的,一个更好的选择是使用docker stack。

您的服务将是docker swarm服务:

您可以使用以下方法部署它们:

docker deploy --compose-file path_to_compose_file

然后foobar将使用服务名称和端口barfoo连接到barfoo:80