Docker Compose 多服务部署:一键拉起你的完整开发栈

概述

你搭过一个项目吗?先装 MySQL,再配 Redis,然后搞 Nginx,最后写代码。每次换台电脑都要重复这套流程,烦不烦?

Docker Compose 就是来解决这个问题的。一个 YAML 文件,定义所有服务的镜像、端口、环境变量,一条命令全部拉起。

今天教你从零搭建一个包含 Web 应用 + MySQL + Redis + Nginx 的反向代理的多服务架构。

准备工作

你需要一台 Linux 服务器或本地机器,满足以下条件:

  • 已安装 Docker(v20.10+)
  • 已安装 Docker Compose(v2.x,通常随 Docker 一起安装)
  • 基础的网络知识,知道端口和 IP 的概念

检查安装状态:

docker --version
docker compose version

如果没装,执行:

# Ubuntu/Debian
curl -fsSL https://get.docker.com | sh

# CentOS/RHEL
curl -fsSL https://get.docker.com | sh

步骤

第一步:创建项目目录

mkdir -p ~/myapp && cd ~/myapp

第二步:编写 docker-compose.yml

这是核心文件。直接复制以下配置:

services:
  web:
    image: nginx:alpine
    container_name: myapp-web
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./public:/usr/share/nginx/html:ro
    depends_on:
      - app
    networks:
      - frontend

  app:
    image: python:3.12-slim
    container_name: myapp-api
    working_dir: /app
    command: python -m http.server 8000
    volumes:
      - ./app:/app
    expose:
      - "8000"
    networks:
      - frontend
      - backend

  db:
    image: mysql:8.0
    container_name: myapp-db
    environment:
      MYSQL_ROOT_PASSWORD: rootpass123
      MYSQL_DATABASE: myapp_db
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppass123
    volumes:
      - db_data:/var/lib/mysql
    expose:
      - "3306"
    networks:
      - backend

  redis:
    image: redis:7-alpine
    container_name: myapp-redis
    command: redis-server --requirepass redispass123
    volumes:
      - redis_data:/data
    expose:
      - "6379"
    networks:
      - backend

networks:
  frontend:
  backend:

volumes:
  db_data:
  redis_data:

解释一下关键概念:

  • services:每个 key 就是一个容器服务
  • ports:宿主机端口映射到容器端口,外部可访问
  • expose:仅容器间通信,外部不可见
  • depends_on:启动顺序依赖
  • networks:把服务分组,frontend 给外网,backend 仅供内部通信
  • volumes:数据持久化,容器删了数据还在

第三步:创建 Nginx 配置文件

在同目录下创建 nginx.conf

server {
    listen 80;
    server_name localhost;

    location / {
        root /usr/share/nginx/html;
        index index.html;
    }

    location /api/ {
        proxy_pass http://app:8000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Nginx 会把 /api/ 开头的请求转发给 Python 应用。

第四步:创建简单页面

mkdir -p public app
echo '<h1>Hello from Docker Compose</h1>' > public/index.html
echo 'print("API running")' > app/server.py

第五步:启动服务

docker compose up -d

-d 表示后台运行。你会看到四个容器被创建并启动。

查看状态:

docker compose ps

输出类似这样:

NAME            IMAGE              STATUS
myapp-web       nginx:alpine       Up
myapp-api       python:3.12-slim   Up
myapp-db        mysql:8.0          Up
myapp-redis     redis:7-alpine     Up

验证

验证 Web 服务

curl http://localhost

应该返回 <h1>Hello from Docker Compose</h1>

验证 API 代理

curl http://localhost/api/

Nginx 会把请求转发给 Python HTTP 服务器。

验证数据库连接

docker exec -it myapp-db mysql -u appuser -papppass123 myapp_db -e "SHOW TABLES;"

验证 Redis 连接

docker exec -it myapp-redis redis-cli -a redispass123 PING

返回 PONG 就说明正常。

查看日志

docker compose logs -f

-f 是实时跟踪日志,按 Ctrl+C 退出。

常见问题

Q1:端口被占用怎么办?

docker-compose.yml 中的 ports 映射。比如 "8080:80" 就把宿主机的 8080 端口映射到容器的 80 端口。

Q2:改了配置怎么生效?

docker compose down
docker compose up -d

先停掉再重新启动。

Q3:容器里的数据丢了怎么办?

上面的配置已经用了 named volumes(db_dataredis_data),数据存在 Docker 管理的卷里,不会因为删除容器而丢失。

Q4:想加一个新服务?

docker-compose.ymlservices 下加一段配置就行。比如加一个 PostgreSQL:

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: pgpass123
    volumes:
      - pg_data:/var/lib/postgresql/data
    networks:
      - backend

Q5:生产环境怎么用?

生产环境建议加上健康检查:

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"]
  interval: 30s
  timeout: 10s
  retries: 3

以及设置 .env 文件管理敏感信息,不要把密码直接写在 compose 文件里。


搞定。一条命令启动整个技术栈,这才是开发该有的样子。

试试在你的项目里跑起来,遇到什么问题随时查日志。

这篇文章对你有帮助吗?