在阿里云 ECS 上通过 Docker 部署多个网站,核心逻辑其实就一句话:复用宿主机的 80/443 端口,利用 Nginx(或 Caddy)做反向X_X,根据域名将流量分发到不同的容器。
别整虚的,直接上最稳妥、最易维护的方案。我们分三步走:准备环境、配置 Nginx、启动服务。
第一步:基础设施准备
- 阿里云安全组:确保你的 ECS 实例安全组开放了
80(HTTP) 和443(HTTPS) 端口。 - 域名解析:假设你有两个域名
a.com和b.com,将它们都 A 记录解析到你的 ECS 公网 IP。 - 安装 Docker 和 Docker Compose:
# 如果还没装,执行以下命令 curl -fsSL https://get.docker.com | bash sudo systemctl enable --now docker # 安装 docker-compose (v2 版本通常内置在 docker-cli 中,若需独立二进制文件可自行下载)
第二步:目录结构规划
保持清晰的结构是后期维护的关键。建议按项目隔离:
/opt/docker-sites/
├── nginx/
│ ├── conf.d/
│ │ └── default.conf # 核心配置文件
│ └── certs/ # SSL 证书存放处
├── site-a/ # 网站 A 的代码或构建产物
├── site-b/ # 网站 B 的代码或构建产物
└── docker-compose.yml # 编排文件
第三步:编写 Nginx 反向X_X配置
这是最关键的一步。我们需要一个通用的 Nginx 容器作为“网关”,它不跑业务,只负责转发。
创建 /opt/docker-sites/nginx/conf.d/default.conf:
# 全局设置
worker_processes auto;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
# 站点 A: a.com
server {
listen 80;
server_name a.com www.a.com;
location / {
proxy_pass http://site-a-container:80; # 指向下方 docker-compose 中定义的 service name
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;
}
# HTTP 强制跳转 HTTPS (可选)
location /.well-known/acme-challenge/ {
root /usr/share/nginx/html;
}
}
# 站点 B: b.com
server {
listen 80;
server_name b.com www.b.com;
location / {
proxy_pass http://site-b-container:80;
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;
}
}
# 如果有 HTTPS 需求,后续再补充 server 块监听 443 ssl
}
第四步:编写 Docker Compose 文件
在 /opt/docker-sites/docker-compose.yml 中定义所有服务:
version: '3.8'
services:
# 1. Nginx 网关
nginx:
image: nginx:alpine
container_name: nginx-proxy
ports:
- "80:80"
# - "443:443" # 如果配了 SSL,开启此项
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/certs:/etc/nginx/certs # 用于存放证书
depends_on:
- site-a
- site-b
restart: always
# 2. 网站 A (以简单的静态 HTML 为例,实际可替换为你的应用镜像)
site-a:
image: nginx:alpine
container_name: site-a-app
volumes:
- ./site-a/www:/usr/share/nginx/html # 挂载网站 A 的文件
restart: always
# 3. 网站 B
site-b:
image: nginx:alpine
container_name: site-b-app
volumes:
- ./site-b/www:/usr/share/nginx/html # 挂载网站 B 的文件
restart: always
注意:depends_on 只是控制启动顺序,不会等待服务完全就绪。对于生产环境,建议在你的应用镜像中加入健康检查,或者使用 wait-for-it.sh 等工具,但对于简单部署,Nginx 的重试机制通常能兜底。
第五步:启动与验证
- 进入目录并启动:
cd /opt/docker-sites docker compose up -d - 检查状态:
docker compose ps确保三个容器都是
Up状态。 - 浏览器访问
a.com和b.com,应该能看到各自对应的内容。
进阶:如何搞定 HTTPS?
手动管理证书很麻烦,推荐使用 Traefik 或 Caddy 替代上面的 Nginx 方案,它们支持自动申请 Let’s Encrypt 证书。但如果坚持用 Nginx,推荐搭配 Certbot 自动化脚本。
这里提供一个简化的 Certbot 流程思路:
- 先不加 SSL,确保 HTTP 通。
- 安装 certbot:
sudo apt install certbot python3-certbot-nginx(宿主机上)。 - 运行
sudo certbot --nginx -d a.com -d b.com。 - Certbot 会自动修改宿主机上的 Nginx 配置或生成新配置。
- 关键点:为了让 Docker 里的 Nginx 也能用这个证书,你需要将
/etc/letsencrypt/live/下的证书软链接或复制到./nginx/certs/目录,并修改default.conf中的 server 块,添加listen 443 ssl;以及证书路径。
避坑指南
- 端口冲突:如果你的某个网站内部也用了 80 端口,没关系,因为它是通过 Docker 内部网络通信,外部只暴露给 Nginx 容器。只要
docker-compose.yml里没写ports: ["80:80"]就行。 - 静态资源缓存:如果前端有大量 JS/CSS,记得在 Nginx 配置里加上
expires指令,否则每次请求都回源会非常慢。 - Docker 网络:默认情况下,Compose 会自动创建一个网络,服务间可以通过
service-name互相访问。不要试图用localhost去访问其他容器,必须用容器名。 - 阿里云内网 vs 网络:如果这些网站只是你自己用,且都在同一台 ECS 上,上述方案完美。如果你未来要扩展多台服务器,需要考虑负载均衡器(SLB/ALB),那时 Nginx 容器可能需要改为监听内网 IP 或被 SLB 接管。
这套方案成本低、资源占用少、易于横向扩展。每个网站独立容器,挂了互不影响,重启单个网站也不会影响其他站点。
云知道CLOUD