努力
加油

如何在Ubuntu服务器上同时运行多个Docker容器?

在 Ubuntu 服务器上同时运行多个 Docker 容器,核心逻辑其实非常清晰:Docker 本身就是为了隔离和并发设计的。只要你的宿主机(Ubuntu)资源(CPU、内存、磁盘 I/O)足够,你可以轻松启动几十甚至上百个容器。

这里不整虚的,直接分场景给你几种最主流、最稳妥的操作方案,从手动到自动化,按复杂度递增。

1. 基础版:手动并行启动(适合少量服务)

这是最直接的方式。每个容器都有独立的名称和网络空间,互不干扰。

关键原则:

  • 必须指定 --name:如果不指定,Docker 会随机生成名字,后期管理极其痛苦。
  • 端口映射要错开:如果两个容器都对外暴露了同一个宿主机端口(如 80),第二个容器启动时会报错 port is already allocated。

示例命令:

# 启动第一个 Web 服务 (Nginx),占用宿主机 8080 端口
docker run -d --name web-app-1 -p 8080:80 nginx:latest

# 启动第二个数据库服务 (MySQL),占用宿主机 3306 端口
docker run -d --name mysql-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=yourpassword mysql:8.0

# 启动第三个应用服务,使用自定义网络以便内部通信
docker network create my-net
docker run -d --name app-backend --network my-net your-custom-image

验证是否都在跑:

docker ps

你会看到多个 STATUS: Up 的状态。


2. 进阶版:使用 Docker Compose(推荐用于多服务关联)

当你的应用由多个部分组成(比如前端 Nginx + 后端 Node.js + 数据库 MySQL),手动敲 docker run 容易出错且难以维护。Docker Compose 是行业标准解决方案。

它通过一个 YAML 文件定义所有容器的配置、依赖关系和网络。

步骤:

  1. 确保 Ubuntu 安装了 Docker Compose(通常安装 Docker 时已附带 docker-compose-plugin)。

    docker compose version
  2. 创建 docker-compose.yml 文件:

version: '3.8'

services:
  # 前端服务
  frontend:
    image: nginx:alpine
    ports:
      - "80:80"
    networks:
      - app-network

  # 后端 API
  backend:
    image: node:18-alpine
    command: npm start
    depends_on:
      - database
    networks:
      - app-network

  # 数据库
  database:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - app-network

volumes:
  db-data:

networks:
  app-network:
    driver: bridge
  1. 一键启动所有容器:
    docker compose up -d

优势:

  • 原子性:一起启动,一起停止。
  • 依赖管理:depends_on 保证数据库先于后端启动。
  • 网络互通:默认在同一网络下,容器间可以通过服务名(如 database)直接访问,无需配置复杂 IP。

3. 生产环境版:集群与编排(Kubernetes / Docker Swarm)

如果你是在阿里云 ECS、腾讯云 CVM 或 AWS EC2 上部署大规模应用,单机手动管理几十个容器会陷入混乱。这时需要引入编排工具。

A. Docker Swarm(轻量级,内置于 Docker)

适合中小规模集群,配置简单。

# 初始化 swarm 集群
docker swarm init

# 部署 stack(基于 compose 文件)
docker stack deploy -c docker-compose.yml mystack

B. Kubernetes (K8s)(工业标准,复杂但强大)

国内大厂普遍采用 K8s。你需要搭建 K8s 集群(可以使用 kubeadm、kops 或直接购买云厂商的 ACK/TKE 托管版)。

在 K8s 中,你不再直接操作“容器”,而是操作 Pod 和 Deployment。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-web-app
spec:
  replicas: 3  # 自动运行 3 个副本,实现高可用
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

为什么选 K8s?

  • 自愈能力:容器挂了自动重启。
  • 水平扩展:流量大了自动增加 Pod 数量。
  • 资源调度:智能分配 CPU/内存,避免单机过载。

4. 关键注意事项(避坑指南)

在实际操作中,很多人遇到“容器跑不起来”或“性能差”,通常是以下原因:

  1. 资源限制(Cgroups):

    • 不要无限制地拉取镜像和启动容器。务必为每个容器设置资源上限,防止某个容器吃光服务器内存导致 OOM(Out of Memory)。
      docker run -d --name limited-app --memory="512m" --cpus="1.0" my-image
  2. 持久化数据:

    • 绝对不要把重要数据存在容器的可写层里!容器一删,数据全没。
    • 使用 Volume(卷)或挂载宿主机的目录。
      docker run -d -v /host/data:/container/data my-image
  3. 日志管理:

    • 多个容器同时输出日志,很快会撑爆 /var/log/docker.log。
    • 建议配置 logrotate,或者将日志输出到 ELK(Elasticsearch, Logstash, Kibana)等集中式日志系统。
  4. 防火墙与安全组:

    • Ubuntu 自带 ufw,云服务器有安全组。
    • 只开放必要的端口(如 80, 443, 22)。不要随意 -p 0.0.0.0:8080:80 暴露调试端口到公网。
  5. 网络模式选择:

    • bridge(默认):大多数情况够用。
    • host:性能最好,无 NAT 开销,但端口冲突风险极高,慎用。
    • none:完全无网络,用于离线计算任务。

总结建议

  • 个人项目/测试环境:直接用 docker compose,一个 YAML 文件搞定所有依赖,省心省力。
  • 小型生产环境:继续使用 docker compose,配合 systemd 守护进程,确保开机自启。
  • 大型分布式系统:上 Kubernetes(K8s),或者直接使用云厂商的容器服务(如阿里云 ACK、腾讯云 TKE),免去运维底层基础设施的麻烦。

记住,Docker 只是容器运行时,真正的挑战在于架构设计和运维规范。先从 Compose 开始,逐步演进到更复杂的编排体系。