阿里云服务器docker部署多个网站?

在阿里云 ECS 上通过 Docker 部署多个网站,核心逻辑其实就一句话:复用宿主机的 80/443 端口,利用 Nginx(或 Caddy)做反向X_X,根据域名将流量分发到不同的容器。

别整虚的,直接上最稳妥、最易维护的方案。我们分三步走:准备环境、配置 Nginx、启动服务。

第一步:基础设施准备

  1. 阿里云安全组:确保你的 ECS 实例安全组开放了 80 (HTTP) 和 443 (HTTPS) 端口。
  2. 域名解析:假设你有两个域名 a.com 和 b.com,将它们都 A 记录解析到你的 ECS 公网 IP。
  3. 安装 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 的重试机制通常能兜底。

第五步:启动与验证

  1. 进入目录并启动:
    cd /opt/docker-sites
    docker compose up -d
  2. 检查状态:
    docker compose ps

    确保三个容器都是 Up 状态。

  3. 浏览器访问 a.com 和 b.com,应该能看到各自对应的内容。

进阶:如何搞定 HTTPS?

手动管理证书很麻烦,推荐使用 Traefik 或 Caddy 替代上面的 Nginx 方案,它们支持自动申请 Let’s Encrypt 证书。但如果坚持用 Nginx,推荐搭配 Certbot 自动化脚本。

这里提供一个简化的 Certbot 流程思路:

  1. 先不加 SSL,确保 HTTP 通。
  2. 安装 certbot:sudo apt install certbot python3-certbot-nginx (宿主机上)。
  3. 运行 sudo certbot --nginx -d a.com -d b.com。
  4. Certbot 会自动修改宿主机上的 Nginx 配置或生成新配置。
  5. 关键点:为了让 Docker 里的 Nginx 也能用这个证书,你需要将 /etc/letsencrypt/live/ 下的证书软链接或复制到 ./nginx/certs/ 目录,并修改 default.conf 中的 server 块,添加 listen 443 ssl; 以及证书路径。

避坑指南

  1. 端口冲突:如果你的某个网站内部也用了 80 端口,没关系,因为它是通过 Docker 内部网络通信,外部只暴露给 Nginx 容器。只要 docker-compose.yml 里没写 ports: ["80:80"] 就行。
  2. 静态资源缓存:如果前端有大量 JS/CSS,记得在 Nginx 配置里加上 expires 指令,否则每次请求都回源会非常慢。
  3. Docker 网络:默认情况下,Compose 会自动创建一个网络,服务间可以通过 service-name 互相访问。不要试图用 localhost 去访问其他容器,必须用容器名。
  4. 阿里云内网 vs 网络:如果这些网站只是你自己用,且都在同一台 ECS 上,上述方案完美。如果你未来要扩展多台服务器,需要考虑负载均衡器(SLB/ALB),那时 Nginx 容器可能需要改为监听内网 IP 或被 SLB 接管。

这套方案成本低、资源占用少、易于横向扩展。每个网站独立容器,挂了互不影响,重启单个网站也不会影响其他站点。

未经允许不得转载:云知道CLOUD » 阿里云服务器docker部署多个网站?