华为云 Flexus L 实例从零部署 Docker 与 Nginx 反向代理
背景与目标
我使用华为云 Flexus L 实例部署一个简单的 Web 服务,系统选择 Ubuntu 22.04 LTS,公网 IPv4 地址通过控制台查看。目标是让 Nginx 运行在 Docker 容器中,对外监听 80 端口,再把请求转发到同一 Compose 网络中的后端容器。
最终结构如下:
浏览器 -> Flexus L 公网 IP:80 -> nginx-proxy:80 -> web:80
Flexus L 实例本身只需要开放 SSH 和 HTTP 端口。HTTPS 证书暂未配置,443 端口不提前放行。
准备安全组和系统
在华为云控制台进入 Flexus L 实例的安全组规则,增加以下入方向规则:
| 协议 | 端口 | 来源 |
|---|---:|---|
| TCP | 22 | 我的办公公网 IP/32 |
| TCP | 80 | 0.0.0.0/0 |
不建议直接把 22 端口对所有地址开放。修改规则后,在本地测试:
ssh ubuntu@公网IP
登录实例后确认系统版本和架构:
cat /etc/os-release
uname -m
据我实测,本文使用的 Ubuntu 22.04.5 LTS 和 x86_64 架构可以正常安装 Docker Engine。先更新系统并安装依赖:
sudo apt update
sudo apt install -y ca-certificates curl
配置 Docker 官方软件源:
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu \
-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 "$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 systemctl status docker --no-pager
docker --version
docker compose version
我实测输出类似:
Docker version 27.5.1, build 9f9e405
Docker Compose version v2.32.4
版本号会随软件源更新而变化,关键是确认 docker.service 为 active (running)。
创建 Nginx 反向代理
为了避免每次使用 sudo,把当前用户加入 Docker 用户组:
sudo usermod -aG docker $USER
newgrp docker
docker ps
创建项目目录:
mkdir -p ~/reverse-proxy/html
cd ~/reverse-proxy
创建后端页面:
cat > html/index.html <<'EOF'
<!doctype html>
<html lang="zh-CN">
<head><meta charset="utf-8"><title>Flexus L</title></head>
<body><h1>Hello from backend container</h1></body>
</html>
EOF
创建 compose.yaml:
services:
web:
image: nginx:1.27-alpine
container_name: demo-web
restart: unless-stopped
volumes:
- ./html:/usr/share/nginx/html:ro
expose:
- "80"
proxy:
image: nginx:1.27-alpine
container_name: nginx-proxy
restart: unless-stopped
depends_on:
- web
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
这里使用 expose 暴露后端容器端口,它只在 Docker 网络内部可访问;proxy 使用 ports 将容器 80 端口映射到实例的 80 端口。
创建 Nginx 配置:
cat > nginx.conf <<'EOF'
server {
listen 80;
server_name _;
location / {
proxy_pass http://web:80;
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;
}
}
EOF
web 是 Compose 服务名,Docker 内置 DNS 会把它解析到后端容器地址,不应填写 127.0.0.1。在代理容器中,127.0.0.1:80 指向代理容器自身,而不是 web 容器。
启动服务并检查状态:
docker compose up -d
docker compose ps
docker compose logs --tail=50 proxy
预期两个服务状态均为 Up。在实例本机测试:
curl -I http://127.0.0.1
curl http://127.0.0.1
然后在本地电脑访问:
curl http://公网IP
页面应返回 Hello from backend container。
遇到的问题及解决方法
1. 浏览器访问超时
如果实例本机 curl http://127.0.0.1 正常,但公网访问超时,优先检查华为云安全组是否放行 TCP 80。随后检查 Docker 端口映射:
docker ps
sudo ss -lntp | grep ':80'
应看到类似:
0.0.0.0:80->80/tcp
Ubuntu 如果启用了 UFW,还要检查:
sudo ufw status
sudo ufw allow 80/tcp
2. `bind: address already in use`
启动时出现:
Error response from daemon: driver failed programming external connectivity:
Bind for 0.0.0.0:80 failed: port is already allocated
说明宿主机 80 端口已被其他服务占用。执行:
sudo ss -lntp | grep ':80'
如果是系统 Nginx,可以停止它:
sudo systemctl disable --now nginx
docker compose up -d
也可以把 Compose 中的映射改为 "8080:80",但访问地址需要变为 http://公网IP:8080,同时安全组放行 TCP 8080。
3. Nginx 返回 502 Bad Gateway
查看代理日志:
docker compose logs proxy
确认后端容器是否运行:
docker compose ps
docker compose exec proxy getent hosts web
docker compose exec proxy wget -qO- http://web:80
如果 web 无法解析,通常是服务名写错或两个容器不在同一个 Compose 项目网络中。配置中的 proxy_pass http://web:80; 必须与 services 下的 web 名称一致。
结论
这套部署只依赖 Flexus L 实例、Ubuntu 22.04、Docker Engine 和 Compose,代理与后端均由容器管理。日常更新可以在项目目录执行:
docker compose pull
docker compose up -d
docker image prune
生产环境还应配置域名和 HTTPS,并将安全组规则收紧;修改 Nginx 配置后,可先执行 docker compose exec proxy nginx -t,确认语法通过后再重建或重启代理容器。
- 点赞
- 收藏
- 关注作者
评论(0)