上一篇 下一篇 分享链接 返回 返回顶部

西雅图服务器用Ubuntu部署Docker网站,Nginx反向代理上线前要检查什么

发布人:Minchunlin 发布时间:8小时前 阅读量:21
西雅图服务器用Ubuntu部署Docker网站,Nginx反向代理上线前要检查什么

在一个典型的西雅图服务器上线现场,站长已经把网站容器启动,却在浏览器里看到 502 Bad Gateway。工程人员不会先反复重启服务,而是沿着一条固定链路定位:域名是否指向服务器,公网端口是否能到达 Nginx,Nginx 是否能访问 Docker 容器,容器内的网站是否真正监听了预期端口。

本文采用的目标环境是 Ubuntu 服务器、Docker Compose 运行网站、宿主机 Nginx 负责反向代理。示例将网站容器端口绑定到宿主机 127.0.0.1:8080,公网只开放 Nginx 使用的 80 和 443 端口。正式上线前,至少要完成环境、端口、域名、代理配置、HTTPS、验证和回滚检查。

先确认上线条件和链路

在西雅图服务器上执行部署前,需要先明确以下条件:

检查项需要确认的内容未满足时的表现
操作系统Ubuntu 版本、架构和软件源可用Docker 或 Nginx 安装失败
登录权限具备 sudo 权限,并保留当前 SSH 会话无法安装软件或修改服务
域名A 记录指向服务器公网 IPv4;使用 IPv6 时再核对 AAAA域名访问到旧地址或无法连接
网络策略云平台安全组、主机防火墙允许 TCP 80/443浏览器超时
Docker 应用容器内部实际监听端口已知Nginx 返回 502
Nginxserver_name 与访问域名一致出现默认页面或匹配错误站点
回滚材料旧配置、旧镜像或旧 Compose 文件可用新版本异常时无法快速恢复

应用监听端口和宿主机发布端口不是一回事。例如,容器内部监听 80,可以发布为宿主机的 127.0.0.1:8080;此时 Nginx 的上游地址应是 127.0.0.1:8080,而不是容器内部地址或公网 IP。

在 Ubuntu 上检查并安装运行环境

先查看系统信息,不要仅凭记忆判断 Ubuntu 版本和架构:

cat /etc/os-release
uname -m
dpkg --print-architecture

如果准备使用 Docker 官方软件源,可以按下面方式安装 Docker Engine、Compose 插件和 Buildx:

sudo apt update
sudo apt install -y ca-certificates curl gnupg

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  | sudo gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "${VERSION_CODENAME}") stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

sudo systemctl enable --now docker
sudo docker info
sudo docker compose version

如果 apt update 提示当前 Ubuntu 代号没有对应的软件源,不要绕过校验继续安装,应先核对系统版本和软件源配置。docker info 能正常返回,且 docker compose version 能识别 Compose 插件,才适合继续部署。

首次安装后可以进行一次基础拉取测试:

sudo docker run --rm hello-world

这个命令会拉取测试镜像并启动临时容器。它不能证明业务网站正常,只能说明 Docker 服务和镜像拉取链路基本可用。

不建议为了省略 sudo 就直接把运维账号加入 docker 用户组。Docker 用户组通常拥有接近宿主机管理员的控制能力;如果确实要使用,应先评估账号权限边界,并保留现有 sudo 登录方式。

准备网站容器并限制暴露范围

假设网站部署目录为 /opt/example-site

sudo mkdir -p /opt/example-site
sudo chown -R "$USER":"$USER" /opt/example-site
cd /opt/example-site

创建 .env 文件,替换为实际网站镜像和容器内部端口:

APP_IMAGE=your-registry/example-web:stable
APP_CONTAINER_PORT=80

这里的 APP_CONTAINER_PORT=80 只适用于网站进程在容器内监听 80 端口的情况。如果应用实际监听 3000、8080 或其他端口,应改成应用真实端口。不要因为宿主机使用 8080,就误把容器内部端口也写成 8080。

创建 compose.yaml

services:
  web:
    image: ${APP_IMAGE}
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:${APP_CONTAINER_PORT}"

这种写法的关键点是 127.0.0.1:8080。它只让宿主机本地的 Nginx访问网站,避免应用端口直接暴露到公网。不要随意改成 0.0.0.0:8080,否则云平台安全组和主机防火墙之外,还会多出一个直接访问应用的入口。

先检查 Compose 展开结果,再启动:

cd /opt/example-site
sudo docker compose config
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps

如果使用普通用户执行 Docker,会把命令中的 sudo 去掉;但同一项目最好保持权限方式一致,避免 /opt/example-site 下的文件出现难以管理的属主问题。

容器状态正常后,先绕过 Nginx访问上游:

curl -I http://127.0.0.1:8080/
sudo docker compose logs --tail=100 web
sudo ss -lntp | grep -E ':(8080|80|443)\b'

这里的结果需要结合应用特性判断。200301 或应用预期的其他 HTTP 状态,可能都属于正常响应;如果连接被拒绝,优先检查容器是否运行、端口映射是否正确,以及应用是否在容器内监听了 0.0.0.0 而不是仅监听容器内部的 127.0.0.1

安装 Nginx并配置反向代理

安装并启动宿主机 Nginx:

sudo apt update
sudo apt install -y nginx
sudo systemctl enable --now nginx

修改下面配置中的域名。配置文件放在 /etc/nginx/sites-available/example.com

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 60s;
    }
}

配置中的 HostX-Forwarded-ForX-Forwarded-Proto 不应省略。许多应用会依据 Host 判断站点域名,依据 X-Forwarded-Proto 判断原始请求是否为 HTTPS;缺少这些头部时,可能出现跳转循环、生成错误绝对链接或日志中只看到代理地址。

启用站点前先备份 Nginx 配置:

sudo cp -a /etc/nginx "/root/nginx-backup-$(date +%F-%H%M%S)"

sudo ln -s /etc/nginx/sites-available/example.com \
  /etc/nginx/sites-enabled/example.com

如果软链接已经存在,不要重复创建;先检查它是否指向预期文件:

readlink -f /etc/nginx/sites-enabled/example.com

测试并加载配置:

sudo nginx -t
sudo systemctl reload nginx

只有 nginx -t 成功后才执行 reload。若测试失败,不要使用 systemctl restart nginx 强行覆盖运行状态,应先根据错误行号修复配置。若服务器没有启用 IPv6,listen [::]:80; 可能导致监听失败,此时应先用 ss -lntp 检查现有监听,再决定是否删除该 IPv6 监听行。

检查域名、防火墙和公网访问

在 DNS 管理处确认域名的 A 记录指向西雅图服务器公网 IPv4。若配置了 AAAA 记录,还要确保服务器确实配置了可用 IPv6;否则部分客户端可能优先访问 AAAA 地址而失败。

在服务器或可访问该 DNS 的环境中检查解析结果:

dig +short A example.com
dig +short AAAA example.com

主机防火墙和云平台安全组需要分别核对。若使用 UFW,先查看当前状态,确认仍能通过 SSH 登录,再放行 Nginx 所需端口:

sudo ufw status verbose
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx HTTP'

准备直接提供 HTTPS 时,再放行:

sudo ufw allow 'Nginx Full'

这些命令会修改主机防火墙规则,执行前应确认 SSH 规则存在,并保留云平台控制台或带外登录方式。云平台安全组也必须允许 TCP 80/443;只修改 UFW 而没有修改外层安全组,公网仍可能无法访问。

DNS完全生效前,可以用 curl --resolve 直接把域名临时指向服务器,用于区分“DNS问题”和“Nginx问题”:

curl -i --resolve example.com:80:SERVER_PUBLIC_IP \
  http://example.com/

如果这个请求能返回网站内容,而普通域名访问失败,问题重点在 DNS 或客户端缓存;如果这个请求也失败,则继续检查安全组、UFW、Nginx监听和容器上游。

HTTPS上线前的检查

只有 HTTP 反向代理和域名解析已经正常,才适合申请证书。证书工具会修改 Nginx 配置,操作前应保留刚才的备份:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

只有在 www.example.com 也已解析到同一服务器时,才把它作为证书域名传入。证书申请要求域名能够从公网访问服务器的验证入口,DNS、云防火墙或 UFW 任一环节未放行,都可能导致申请失败。

完成后检查 Nginx 配置和 HTTPS响应:

sudo nginx -t
sudo systemctl reload nginx

curl -I https://example.com/
sudo certbot renew --dry-run

如果网站应用需要 WebSocket,还应在 Nginx 中补充 Upgrade 相关配置;如果应用上传大文件或长轮询,也要根据业务需求检查 client_max_body_sizeproxy_read_timeout 等参数,不能直接套用默认值。

按由外到内的顺序处理异常

上线验证时,现场工程人员通常按以下顺序判断,避免把网络问题误判成容器问题:

  1. 先查 DNS。 dig 返回旧 IP,说明域名记录或缓存尚未切换;没有 A/AAAA 结果,说明解析记录不完整。
  2. 再查公网端口。 浏览器超时,重点看云安全组、UFW和 Nginx 是否监听 80/443;连接被拒绝,重点看服务是否启动或端口是否被其他程序占用。
  3. 再查 Nginx 配置。 sudo nginx -t 失败是语法、路径或重复监听问题;出现默认欢迎页,通常是域名未匹配到目标 server_name,可用 sudo nginx -T 查看最终配置。
  4. 最后查上游容器。 Nginx 返回 502,常见原因是 127.0.0.1:8080 没有服务、端口映射错误、容器已退出或应用只监听了错误地址。此时直接执行 curl http://127.0.0.1:8080/docker compose logs
  5. 区分应用错误。 Nginx能连到上游但返回 404403 或业务错误时,代理链路可能已经正常,应转而检查应用路由、Host判断、静态文件和应用日志。

新版本异常时如何回滚

升级网站镜像前,至少保存 Compose 文件和 Nginx站点配置:

cd /opt/example-site
cp -a compose.yaml "compose.yaml.backup.$(date +%F-%H%M%S)"
sudo cp -a /etc/nginx/sites-available/example.com \
  "/root/example.com.nginx.$(date +%F-%H%M%S)"

正式环境应尽量使用可追溯的镜像标签或摘要,并保留上一版本镜像。发现新版本导致网站异常时,先恢复旧的 Compose 文件,再重新启动服务:

cd /opt/example-site
cp compose.yaml.backup.YYYY-MM-DD-HHMMSS compose.yaml

sudo docker compose config
sudo docker compose up -d
sudo docker compose ps

如果必须停止当前项目,docker compose down 会停止并移除该 Compose 项目管理的容器,但不应随意加 -v-v 可能删除项目关联的数据卷,数据库或上传文件未完成备份时不能执行。

Nginx 配置异常时,先恢复对应站点文件,再测试并 reload:

sudo cp /root/example.com.nginx.YYYY-MM-DD-HHMMSS \
  /etc/nginx/sites-available/example.com

sudo nginx -t
sudo systemctl reload nginx

如果只是误启用了新的站点软链接,应仅处理确认过的那个链接,不要使用通配符删除整个 sites-enabled 目录。回滚完成后,再依次验证本机上游、HTTP域名和 HTTPS域名。

容易被忽略的最后一项,是“服务能启动”不等于“网站已上线”:还要确认应用重启后能自动恢复、证书续期演练没有失败、AAAA记录与IPv6实际状态一致、容器端口没有意外暴露公网,以及旧版本配置和数据确实可以在当前服务器上重新使用。

目录结构
全文