Docker 组成端口映射,主机端口!=容器端口
Docker compose port mapping, host port != container port
如何在不更改 docker 文件的情况下使 curl http://barfoo:8002
从 foobar-container 工作?
我有以下撰写文件:
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
目前,一个可能的解决方法是覆盖 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'
但我很乐意接受一个更好的solution/answer。
当您从终端执行 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
自定义 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;
}
}
}
How can I make curl http://barfoo:8002 work from the foobar-container, without making changes to the docker file?
简单的解决方案是将主机端口 8002 映射到 barfoo
端口 8002。但这可能不是您想要的。
barfoo
是在内部 docker dns 中注册的服务名称,只能由您 [=59= 创建的同一 docker 网络中的服务 (foobar
) 访问] docker-compose up
8002 是映射到 docker 主机的端口。
因此,当您从 foobar
容器 运行 curl http://barfoo:8002
尝试连接到服务 barfoo
到端口 8002 时。但是 barfoo
侦听端口 80在容器内而不是在 8002 上。
另一个解决方案:
您可以将 network_mode: host
添加到 barfoo
和 foobar
。
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
进行连接
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
如果这确实是您想要的,更好的选择是使用 docker 堆栈。
您的服务将是 docker swarm 服务:
您可以使用以下方式部署它们:
docker deploy --compose-file path_to_compose_file
然后 foobar
将使用服务名称和端口 barfoo:80
连接到 barfoo
如何在不更改 docker 文件的情况下使 curl http://barfoo:8002
从 foobar-container 工作?
我有以下撰写文件:
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
目前,一个可能的解决方法是覆盖 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'
但我很乐意接受一个更好的solution/answer。
当您从终端执行 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
自定义 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;
}
}
}
How can I make curl http://barfoo:8002 work from the foobar-container, without making changes to the docker file?
简单的解决方案是将主机端口 8002 映射到 barfoo
端口 8002。但这可能不是您想要的。
barfoo
是在内部 docker dns 中注册的服务名称,只能由您 [=59= 创建的同一 docker 网络中的服务 (foobar
) 访问] docker-compose up
8002 是映射到 docker 主机的端口。
因此,当您从 foobar
容器 运行 curl http://barfoo:8002
尝试连接到服务 barfoo
到端口 8002 时。但是 barfoo
侦听端口 80在容器内而不是在 8002 上。
另一个解决方案:
您可以将 network_mode: host
添加到 barfoo
和 foobar
。
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
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
如果这确实是您想要的,更好的选择是使用 docker 堆栈。
您的服务将是 docker swarm 服务:
您可以使用以下方式部署它们:
docker deploy --compose-file path_to_compose_file
然后 foobar
将使用服务名称和端口 barfoo:80
barfoo