我的目标是拥有两个docker容器:
- nginx 容器(基于 nginx:latest)用作反向代理
- 带有静态网站的容器(基于 nginx:alpine)
稍后我将添加 1+ .net core 后端服务(目前不重要)。目前,当我尝试使用公共 IP 地址访问我的 Web 服务器时,会出现 502 Bad gateway。这是我当前的配置:
docker-compose.yaml
version: '3'
services:
reverse-proxy:
image: nginx:latest
container_name: reverse_proxy
depends_on:
- static-website
volumes:
- ./reverse_proxy/nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:80
static-website:
image: sm-static-website
build:
context: ./website
container_name: sm_static_website
ports:
- "8080:80"
nginx.conf 用于反向代理:
worker_processes auto;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
}
http {
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name x.x.x.x; # my_public_ip
location / {
proxy_pass http://sm_static_website:8080;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
}
静态网站的 Dockerfile:
FROM nginx:alpine
WORKDIR /html
COPY . /var/www/html
EXPOSE 8080
从我的网站容器中我可以看到 nginx 正在 80 上运行/监听:
netstat -tulpn | grep LISTEN
tcp 0 0 127.0.0.11:41389 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/nginx: master pro
tcp 0 0 :::80 :::* LISTE 1/nginx: master pro
从我的服务器我可以看到 remote_proxy 和 website 容器分别正在监听 80/8080:
netstat -tulpn | grep LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 13936/docker-proxy
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 13797/docker-proxy
tcp6 0 0 :::80 :::* LISTEN 13942/docker-proxy
tcp6 0 0 :::8080 :::* LISTEN 13804/docker-proxy
服务器上的 ps -aux 返回:
root 13936 0.0 0.0 1075140 3580 ? Sl 00:24 0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.18.0.3 -container-port 80
root 13797 0.0 0.0 1148872 3624 ? Sl 00:24 0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8080 -container-ip 172.18.0.2 -container-port 80
网站容器的日志显示没有错误,工作进程正在运行。但是,反向代理日志显示:
2022/05/20 01:20:29 [error] 31#31: *1 connect() failed (111: Connection refused) while connecting to upstream, client: x.x.x.x, server: x.x.x.x, request: "GET / HTTP/1.1", upstream: "http://172.19.0.2:8080/", host: "x.x.x.x"
知道我做错了什么吗?如果我从 docker-compose.yml 中删除 volumes: 行,那么我会从反向代理容器中获取默认的 nginx 页面。这表明它正在正确监听,接受请求,但不会将其重定向到网站容器。
答案1
docker-compose 中的指令port
定义了哪个端口暴露给外部。当它们链接在一起时,您的反向代理容器可以直接访问内部的服务static-website
,因此您在这里不使用暴露的端口。
由于容器内的网站static-website
正在监听端口 80,因此您需要使用该端口而不是暴露的端口。
首先,您需要将容器链接在一起,为此您需要将其添加到reverse-proxy
块中:
links:
- static-website
你的proxy_pass
指令应该是:
proxy_pass http://sm_static_website;
如果您实际上不想将static-website
容器暴露在外面,您可以删除ports
那里的指令。
因此docker-compose.yml
看起来应该是这样的:
version: '3'
services:
reverse-proxy:
image: nginx:latest
container_name: reverse_proxy
depends_on:
- static-website
volumes:
- ./reverse_proxy/nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:80
links:
- sm_static_website
static-website:
image: sm-static-website
build:
context: ./website
container_name: sm_static_website
老实说:我从未发现使用container_name
指令有什么用,我不确定是否必须使用定义的容器名称sm_static_website
,还是只在指令中static-website
使用。如果你省略它,它就只是。links
proxy_pass
static-website