美国服务器部署Docker网站环境时,Ubuntu与Nginx如何配置上线

典型现场中,网站代码已经放进美国服务器的 Docker 容器,curl http://127.0.0.1:8080 也能返回页面,但域名访问仍然失败。此时通常不是 Docker 本身无法运行,而是容器监听地址、Ubuntu 防火墙、Nginx 反向代理、DNS 或 HTTPS 配置没有接通。
一个清晰且便于回滚的部署方式是:以 Ubuntu 22.04 或 24.04 作为美国服务器主机系统,Docker Compose 运行网站容器,容器端口只绑定到本机 127.0.0.1:8080,由宿主机 Nginx 对外监听 80 和 443 端口,再转发到 Docker 网站服务。下面以域名 example.com 为示例,实际操作时替换为自己的域名。
先确认上线目标和前置条件
本方案适用于静态网站、由容器提供 HTTP 服务的网站,或能够在容器内监听 HTTP 端口的 Node.js、Go、PHP 应用。整体链路如下:
用户浏览器
│
├── example.com:443
│
Ubuntu 宿主机上的 Nginx
│
└── 127.0.0.1:8080
│
Docker 容器内:80
开始前需要确认:
- 美国服务器已经安装 Ubuntu 22.04、24.04 或同一系列的受支持版本,并拥有
sudo权限。 - 可以通过 SSH 登录,且已经记录实际 SSH 端口。
- 域名的 A 记录指向服务器公网 IPv4 地址。
- 如果域名存在 AAAA 记录,服务器也必须正确提供 IPv6 访问;否则应先处理无效的 AAAA 记录。
- 服务器入站规则允许 SSH、HTTP 和 HTTPS。不要在未确认 SSH 放行的情况下直接启用防火墙。
- 现有网站、Nginx 配置和 Docker Compose 文件已经备份。
- 示例使用
example.com和www.example.com,只使用其中一个域名时,应同步删减 Nginx 和证书命令中的另一个域名。
部署组件和检查方法可以先按下表确认:
| 组件 | 用途 | 主要检查方式 |
|---|---|---|
| Ubuntu | 宿主机操作系统 | cat /etc/os-release |
| Docker Engine | 运行容器 | sudo systemctl is-active docker |
| Docker Compose Plugin | 管理网站服务 | sudo docker compose version |
| Docker 网站容器 | 提供实际页面 | curl http://127.0.0.1:8080 |
| Nginx | 对外接收请求并反向代理 | sudo nginx -t |
| DNS 与证书 | 让域名通过 HTTP/HTTPS 访问 | dig、curl -I |
先检查 Ubuntu 和端口状态
在美国服务器上执行以下命令,先确定系统版本、架构以及当前端口占用情况:
cat /etc/os-release
dpkg --print-architecture
sudo ss -lntp
重点观察以下结果:
- Ubuntu 的版本和代号应当与 Docker 软件源支持范围一致。
80、443或后面准备使用的8080如果已经被其他服务占用,需要先查明服务用途。- 不要为了让部署继续而直接停止未知服务。先使用下面的命令确认进程:
sudo ss -lntp | grep -E ':(80|443|8080)\b'
sudo systemctl list-units --type=service --state=running
域名解析可以在本地电脑或服务器上检查:
getent hosts example.com
getent hosts www.example.com
如果安装了 dig,还可以分别查看 A 和 AAAA 记录:
dig +short example.com A
dig +short example.com AAAA
解析结果尚未指向当前美国服务器时,不要急着申请证书。先完成 DNS 调整并等待解析生效,否则 Certbot 无法通过域名验证。
在 Ubuntu 上安装 Docker 和 Compose
下面的命令适用于使用 apt 和 systemd 的 Ubuntu 主机。命令会添加 Docker 官方软件源,安装 Docker Engine、Compose Plugin 和常用构建组件。
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
apt-cache policy docker-ce
执行 apt-cache policy docker-ce 后,应能看到可用的软件包候选版本。如果没有候选版本,通常是 Ubuntu 版本代号不受支持、软件源配置错误或网络无法访问软件源。此时应先修复软件源,不要把其他 Ubuntu 版本的代号强行写入当前系统。
确认软件源正常后安装:
sudo apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
sudo systemctl enable --now docker
sudo systemctl is-active docker
sudo docker compose version
如果第一条状态检查返回 active,且 Compose 能够显示版本,Docker 基础环境就已经具备。这里使用 sudo docker,可以避免把当前账号加入 docker 用户组。加入该用户组会让账号获得接近主机管理员级别的 Docker 控制能力,生产服务器上应根据权限模型谨慎处理。
创建一个可验证的 Docker 网站服务
以下示例创建一个最小静态网站,用于验证 Docker、端口映射和 Nginx 反向代理是否正常。新部署可以直接使用;如果 /opt/site 已经承载业务,请先备份文件并核对现有服务,不要直接覆盖。
sudo install -d -m 0755 /opt/site/site
创建测试首页:
sudo tee /opt/site/site/index.html > /dev/null <<'EOF'
Docker Website
网站容器已正常运行
Ubuntu、Docker 和 Nginx 反向代理链路已接通。
EOF
创建 Compose 文件:
sudo tee /opt/site/docker-compose.yml > /dev/null <<'EOF'
services:
web:
image: nginx:alpine
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
volumes:
- ./site:/usr/share/nginx/html:ro
EOF
这里有两个关键配置:
127.0.0.1:8080:80表示只有美国服务器本机可以访问宿主机的 8080 端口,外部用户不能绕过 Nginx 直接访问容器。./site:/usr/share/nginx/html:ro把宿主机网站目录以只读方式挂载到容器,避免容器内的 Web 服务修改宿主机文件。
检查 Compose 配置并启动容器:
cd /opt/site
sudo docker compose config
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps
curl -I http://127.0.0.1:8080
docker compose config 没有报错,且 curl 返回 200 OK 或其他正常 HTTP 响应,说明 Docker 容器已经能够提供页面。
如果实际网站不是静态页面,而是应用服务,需要根据应用在容器内监听的端口调整映射。例如应用在容器内监听 3000,则可以改为:
ports:
- "127.0.0.1:8080:3000"
宿主机 Nginx 仍然代理到 127.0.0.1:8080,不需要把应用端口直接暴露到公网。正式环境还应将镜像从可变的 nginx:alpine 替换为经过测试的固定版本标签或镜像摘要,避免无计划拉取到不同版本。
在 Ubuntu 上安装并配置 Nginx
安装宿主机 Nginx:
sudo apt update
sudo apt install -y nginx
sudo systemctl enable --now nginx
如果服务器上已有同名站点配置,先备份:
if [ -f /etc/nginx/sites-available/example.com ]; then
sudo cp -a /etc/nginx/sites-available/example.com \
"/etc/nginx/sites-available/example.com.bak.$(date +%F-%H%M%S)"
fi
创建反向代理配置:
sudo tee /etc/nginx/sites-available/example.com > /dev/null <<'EOF'
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;
}
}
EOF
启用站点并检查配置:
sudo ln -sfn \
/etc/nginx/sites-available/example.com \
/etc/nginx/sites-enabled/example.com
sudo nginx -t
sudo systemctl reload nginx
只有在 nginx -t 返回 syntax is ok 和 test is successful 后,才执行 reload。配置检查失败时,Nginx 不会加载新配置,原有运行中的配置通常仍然有效。不要用 systemctl restart nginx 替代检查,因为错误配置可能导致服务重启失败。
先在服务器本机模拟域名请求:
curl -I -H 'Host: example.com' http://127.0.0.1
如果返回 Docker 网站的响应,说明 Nginx 到容器的链路已经接通。如果仍然返回 Nginx 默认页面,通常是 server_name 不匹配,或者请求仍然命中了默认站点。
配置防火墙和 HTTPS
如果 Ubuntu 使用 UFW,先查看当前状态:
sudo ufw status verbose
只有在确认 SSH 已经放行后,才调整规则。例如 SSH 使用默认 22 端口时:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
Nginx Full 通常会放行 HTTP 和 HTTPS。若 SSH 使用其他端口,应先放行实际端口,再考虑启用 UFW。启用防火墙前没有控制台或带外登录方式时,不建议直接执行 sudo ufw enable,否则错误规则可能造成 SSH 断连。
确认 DNS 已经指向服务器,并且 HTTP 可以从公网访问后,安装证书工具:
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
在执行 Certbot 前再次备份 Nginx 配置:
sudo cp -a /etc/nginx/sites-available/example.com \
"/etc/nginx/sites-available/example.com.before-certbot.$(date +%F-%H%M%S)"
申请证书并让 Certbot 自动配置 HTTPS 重定向:
sudo certbot --nginx \
-d example.com \
-d www.example.com \
--redirect
如果只使用 example.com,删除 -d www.example.com。Certbot 会要求填写联系邮箱并确认服务条款。申请完成后,检查 Nginx 和证书续期任务:
sudo nginx -t
sudo systemctl reload nginx
sudo certbot renew --dry-run
proxy_set_header X-Forwarded-Proto $scheme 不能省略。应用需要判断原始请求是否为 HTTPS、生成绝对 URL 或处理安全 Cookie 时,会依赖这个请求头。若应用自身没有正确处理反向代理,还需要在应用配置中启用可信代理设置。
按层验证上线是否成功
上线判断不要只看浏览器页面,应从容器、宿主机 Nginx、域名和 HTTPS 逐层确认。
先看容器状态和日志:
cd /opt/site
sudo docker compose ps
sudo docker compose logs --tail=100 web
curl -I http://127.0.0.1:8080
再确认监听端口:
sudo ss -lntp | grep -E ':(80|443|8080)\b'
正常情况下,8080 只应绑定在 127.0.0.1,而 80、443 由宿主机 Nginx 监听。最后从外部网络测试:
curl -I http://example.com
curl -I https://example.com
常见结果可以按以下方式判断:
| 现象 | 优先检查位置 | 常见含义 |
|---|---|---|
curl 127.0.0.1:8080 连接失败 | Docker 容器和端口映射 | 容器未启动、应用未监听或端口写错 |
| 本机 8080 正常,域名返回 502 | Nginx 与 proxy_pass | Nginx 无法连接后端,或后端刚刚退出 |
| 返回 Nginx 默认页面 | server_name、站点软链接、DNS | 请求未命中目标站点配置 |
| 返回 404 | 容器内容或应用路由 | 网站文件路径、前端路由或应用入口不正确 |
| 外部连接超时 | UFW、服务器入站规则、DNS | 80/443 未放行,或域名未指向当前服务器 |
| HTTP 正常、HTTPS 失败 | 证书和 443 监听 | Certbot 未完成,或 443 规则未加载 |
| 容器不断重启 | docker compose logs web | 镜像启动命令、配置文件或应用依赖出错 |
配置失败时的回滚方式
回滚应尽量恢复单个变更,不要直接删除整个 Docker 目录或使用 docker compose down -v。后者可能删除 Compose 管理的卷,造成数据损失。
Nginx 配置失败
如果新配置尚未通过测试,不要 reload:
sudo nginx -t
如果已经修改并确认需要恢复,使用之前生成的备份文件覆盖,再检查并加载:
sudo cp -a \
/etc/nginx/sites-available/example.com.bak.实际时间 \
/etc/nginx/sites-available/example.com
sudo nginx -t && sudo systemctl reload nginx
备份文件名中的“实际时间”应替换为服务器上真实存在的文件名。若只是临时下线该站点,可以移除软链接,但应先确认不会影响其他站点:
sudo rm /etc/nginx/sites-enabled/example.com
sudo nginx -t && sudo systemctl reload nginx
Docker 服务启动失败
先查看日志,不要马上删除容器:
cd /opt/site
sudo docker compose logs --tail=200 web
sudo docker compose ps
如果确认需要停止当前版本,可以执行:
sudo docker compose down
该命令会停止并移除当前 Compose 容器和网络,但不会删除绑定挂载的 site 文件。恢复旧版 Compose 文件后重新启动:
sudo docker compose up -d
生产环境修改 docker-compose.yml 前,应保存一份带时间标记的副本,并记录镜像标签、端口和环境变量。不要使用 docker compose down -v 作为普通回滚命令,除非已经确认卷内没有需要保留的数据。
防火墙调整后无法访问
如果问题出在刚添加的 Nginx 规则,可以删除对应规则:
sudo ufw delete allow 'Nginx Full'
删除前应确认 SSH 仍然保持放行。不要为了恢复网站而删除全部 UFW 规则;先查看编号:
sudo ufw status numbered
复盘这个美国服务器部署现场时,最容易遗漏的不是某一条命令,而是链路边界:容器是否只绑定本机、Nginx 是否代理到正确端口、域名是否解析到当前地址、IPv6 是否存在无效记录、80/443 是否放行,以及 Certbot 修改后 Nginx 配置是否仍能通过测试。只有本机后端、宿主机代理、外部域名和 HTTPS 四层都验证通过,Docker 网站环境才算真正上线。