在阿里云 ECS 实例中部署多个 Docker 应用,核心思路并非简单地在同一台机器上运行多个 docker run 命令,而是通过容器编排或反向XX + 网络隔离来实现资源的合理分配、端口管理以及服务发现。
作为有经验的运维或开发者,我们通常会根据业务规模选择以下三种主流方案。我将按从“轻量级”到“企业级”的顺序进行解析,并重点说明阿里云环境下的最佳实践。
方案一:Docker Compose(适合中小规模、单机部署)
这是最经典且上手最快的方式。适用于微服务数量较少(如 < 20 个)、资源竞争不激烈的场景。
1. 核心逻辑
利用 docker-compose.yml 文件定义多个服务的依赖关系、网络配置和卷挂载。Compose 会自动创建一个自定义网络,使容器间可以通过服务名互相访问。
2. 实施步骤
第一步:准备目录结构
mkdir -p /opt/docker-apps/myproject
cd /opt/docker-apps/myproject
第二步:编写 docker-compose.yml
假设我们要部署一个 Nginx 前端、一个 Node.js API 和一个 MySQL 数据库。
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80" # 对外暴露 HTTP
- "443:443" # 对外暴露 HTTPS
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./html:/usr/share/nginx/html
depends_on:
- api
networks:
- app-network
api:
image: node:16-alpine
command: npm start
volumes:
- ./api:/app
- /app/node_modules
networks:
- app-network
environment:
- DB_HOST=db
- DB_USER=root
- DB_PASS=secret
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: mydb
volumes:
- db-data:/var/lib/mysql
networks:
- app-network
volumes:
db-data:
networks:
app-network:
driver: bridge
第三步:启动服务
docker compose up -d
3. 阿里云 ECS 注意事项
- 安全组配置:务必在阿里云控制台的安全组中开放 80/443 端口。不要直接暴露数据库端口(3306)。
- 资源限制:在
docker-compose.yml中为每个服务添加deploy.resources.limits或使用mem_limit/cpus防止某个应用耗尽 ECS 内存导致其他应用崩溃。
方案二:Nginx 反向XX + 独立容器(适合多域名/子路径路由)
如果你希望多个应用共享同一个 IP,但通过不同的域名或 URL 路径访问,这是标准做法。
1. 架构设计
- 入口层:一个 Nginx 容器作为反向XX,监听 80/443。
- 应用层:各个业务应用以独立容器运行,内部端口随机或不冲突即可,无需暴露给公网。
- 网络层:所有容器加入同一个 Docker 自定义网络,实现 DNS 解析互通。
2. 关键配置示例
Nginx 配置 (default.conf)
server {
listen 80;
server_name app1.example.com;
location / {
proxy_pass http://app1_container:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name app2.example.com;
location / {
proxy_pass http://app2_container:8080;
proxy_set_header Host $host;
}
}
启动脚本
# 创建网络
docker network create shared-net
# 启动 App1
docker run -d --name app1 --network shared-net -p 3000:3000 myapp:v1
# 启动 App2
docker run -d --name app2 --network shared-net -p 8080:8080 myapp:v2
# 启动 Nginx (挂载上述配置文件)
docker run -d --name nginx-proxy
-p 80:80
-v ./nginx/conf.d:/etc/nginx/conf.d
--network shared-net
nginx:alpine
提示:对于生产环境,建议使用 Traefik 或 Caddy 替代手动配置 Nginx,它们支持自动 SSL 证书申请(Let’s Encrypt),极大简化运维。
方案三:Kubernetes (ACK) 或 Swarm(适合大规模、高可用)
当应用数量超过数十个,或需要自动扩缩容、故障自愈时,单机 Docker Compose 不再适用。此时应转向集群化部署。
选项 A:阿里云 ACK (托管 Kubernetes)
- 优势:完全托管,无需维护 Master 节点;与阿里云 VPC、SLB、云盘深度集成;符合国内合规要求。
- 部署流程:
- 在阿里云控制台创建 ACK 集群。
- 使用
kubectl连接集群。 - 将你的应用打包为 Helm Chart 或直接编写 YAML 部署文件。
- 利用 Ingress Controller 实现外部访问。
选项 B:Docker Swarm
- 优势:比 K8s 轻量,配置简单,原生支持滚动更新和服务发现。
- 适用场景:小型团队快速搭建高可用集群。
# 初始化 Swarm
docker swarm init
# 部署服务
docker service create --name web --replicas 3 -p 80:80 nginx
阿里云 ECS 专属优化建议(Pro Tips)
无论采用哪种方案,以下操作能显著提升稳定性和安全性:
1. 磁盘性能与数据持久化
- 问题:ECS 系统盘通常为高效云盘或 SSD,但频繁读写日志可能导致 IOPS 瓶颈。
- 解决:
- 将数据库等写密集型数据挂载到 ESSD 云盘。
- 使用
docker volume或绑定宿主机的独立数据盘目录。 - 定期清理
/var/lib/docker下的未使用镜像和容器,避免撑爆系统盘。
2. 安全组最小化原则
- 严禁:不要在安全组中开放 2375/2376(Docker API)端口。
- 推荐:只开放 Web 服务所需的 80/443 端口。数据库、Redis 等服务仅允许在 Docker 内部网络通信,不映射到宿主机端口。
3. 日志管理
- Docker 默认日志驱动为
json-file,长期运行会占用大量磁盘空间。 - 修改 daemon.json:
{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } } - 进阶:在阿里云环境中,可考虑安装 SLS Agent(阿里云日志服务),将 Docker 日志直接采集到 SLS,便于集中监控和分析。
4. 资源隔离与监控
- 使用
htop或阿里云云监控插件实时监控 ECS 的 CPU、内存和网络流量。 - 为 Docker 设置 cgroup 限制,防止单个容器 OOM(Out of Memory)影响宿主机稳定性。
总结建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 个人项目、测试环境、<5 个服务 | Docker Compose | 简单、易维护、一键启停 |
| 多域名、中等复杂度、需统一出口 | Nginx/Traefik + 独立容器 | 灵活的路由控制,清晰的边界 |
| 企业级、高可用、自动扩缩容 | 阿里云 ACK (Kubernetes) | 生态完善、官方支持、符合生产标准 |
最后提醒:在阿里云 ECS 上部署前,请确保已购买足够的带宽和数据盘容量,并根据业务峰值预留至少 20%-30% 的资源余量,以应对突发流量。
云技术博客