Docker容器中Nginx无法接收请求的问题排查与解决
将React应用基于nginx:alpine镜像部署到Docker容器后,访问对应URL时浏览器提示“无法连接”,执行docker logs -f nginx看不到任何请求日志,推测Nginx未接收到请求。
相关配置信息
docker-compose.yml中的Nginx配置
nginx: container_name: best-nginx build: context: . restart: always image: nginx:alpine volumes: - ./nginx/default.conf:/etc/nginx/default.conf - ./certs:/etc/nginx/certs ports: - "443:443"
Nginx的default.conf配置
server { root /usr/share/nginx/html; index index.html index.htm index.nginx-debian.html; server_name myservername.com; location / { try_files $uri $uri/ =404; } location /keycloak { proxy_pass http://localhost:28080/; } listen [::]:443 ssl ipv6only=on; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/nginx/certs/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/nginx/certs/privkey.pem; # managed by Certbot }
Dockerfile内容
# develop stage FROM node:18-alpine as develop-stage WORKDIR /app COPY package*.json ./ COPY tsconfig.json ./ RUN npm install COPY ./public ./public COPY ./src ./src # build stage FROM develop-stage as build-stage RUN npm run build # production stage FROM nginx:1.23.1-alpine as production-stage COPY --from=build-stage /app/build /usr/share/nginx/html CMD ["nginx", "-g", "daemon off;"]
Docker日志输出
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh /docker-entrypoint.sh: Configuration complete; ready for start up 2022/10/07 09:56:33 [notice] 1#1: using the "epoll" event method 2022/10/07 09:56:33 [notice] 1#1: nginx/1.23.1 2022/10/07 09:56:33 [notice] 1#1: built by gcc 11.2.1 20220219 (Alpine 11.2.1_git20220219) 2022/10/07 09:56:33 [notice] 1#1: OS: Linux 5.15.0-48-generic 2022/10/07 09:56:33 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 2022/10/07 09:56:33 [notice] 1#1: start worker processes 2022/10/07 09:56:33 [notice] 1#1: start worker process 32
原因分析与解决方案
1. Docker Compose镜像配置冲突,自定义镜像未生效
你的docker-compose配置同时指定了image: nginx:alpine和build: context: .,Docker会优先使用官方nginx:alpine镜像,而非你通过Dockerfile构建的包含React静态文件的自定义镜像,导致Nginx容器内没有你的应用文件,且可能覆盖了部分配置。
解决方法:
- 删除
image: nginx:alpine字段,让Docker Compose使用构建的自定义镜像;或者明确指定自定义镜像名称,比如image: my-react-nginx:latest,确保构建和运行的是同一镜像。
修改后的docker-compose.yml片段:
nginx: container_name: best-nginx build: context: . restart: always volumes: - ./nginx/default.conf:/etc/nginx/default.conf - ./certs:/etc/nginx/certs ports: - "443:443"
2. Nginx server_name与访问域名不匹配
配置中server_name myservername.com;,如果访问时用的是IP、localhost或其他未匹配的域名,Nginx找不到对应server块处理请求,会直接拒绝或忽略请求,自然不会生成日志。
解决方法:
- 本地测试时,将
server_name改为localhost _;(_匹配任何域名):server_name localhost _; - 线上环境确保访问域名与
server_name完全一致,或添加通配符如*.myservername.com覆盖子域名。
3. SSL证书异常导致连接失败
如果./certs目录下的fullchain.pem、privkey.pem不存在、权限错误或证书无效,浏览器会因SSL握手失败无法连接,且这类握手失败的请求可能不会被Nginx记录到日志中。
解决方法:
- 检查证书文件:执行
ls -l ./certs确认文件存在,且权限为可读(可临时执行chmod 644 ./certs/*.pem调整); - 本地测试可临时注释SSL配置,改用HTTP协议验证:
修改default.conf:
同时修改docker-compose.yml端口映射为server { root /usr/share/nginx/html; index index.html index.htm index.nginx-debian.html; server_name localhost _; location / { try_files $uri $uri/ /index.html; # React单页应用建议改为/index.html,避免刷新404 } # 注释SSL配置,改用HTTP # listen [::]:443 ssl ipv6only=on; # listen 443 ssl; # ssl_certificate /etc/nginx/certs/fullchain.pem; # ssl_certificate_key /etc/nginx/certs/privkey.pem; listen 80; }- "80:80",重启容器后访问http://localhost测试。
4. 宿主机端口占用或防火墙拦截
宿主机443端口可能被其他服务占用,或防火墙阻止了443端口的流量,导致请求根本无法到达Docker容器。
解决方法:
- 检查端口占用:Linux执行
netstat -tulpn | grep 443,Windows执行netstat -ano | findstr :443,确认端口是否被占用; - 临时关闭宿主机防火墙测试,或添加允许443端口的规则;
- 临时更换端口,比如docker-compose.yml中改为
- "8443:443",访问https://localhost:8443测试。
5. 反向代理配置的localhost指向错误(次要)
Nginx配置中proxy_pass http://localhost:28080/;的localhost是容器内部的localhost,而非宿主机。如果Keycloak运行在宿主机或其他容器,这个配置会导致Nginx无法连接Keycloak,但不会影响React应用的基础访问,不过建议修正:
- Keycloak在其他Docker容器时,使用容器名称作为域名(如
http://keycloak:28080/,需确保两个容器在同一Docker网络); - Keycloak在宿主机时,使用宿主机IP或
host.docker.internal(Docker Desktop环境)。
验证步骤
- 执行
docker-compose build --no-cache重新构建镜像,确保自定义镜像包含React静态文件; - 执行
docker-compose up -d启动容器; - 执行
docker inspect best-nginx查看容器网络配置和端口映射是否正确; - 在宿主机执行
curl -v https://localhost(或对应域名/端口),查看请求详细过程,确认是否能连接到Nginx。
内容的提问来源于stack exchange,提问作者Octavian Niculescu

