概述
你搭过一个项目吗?先装 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_data、redis_data),数据存在 Docker 管理的卷里,不会因为删除容器而丢失。
Q4:想加一个新服务?
在 docker-compose.yml 的 services 下加一段配置就行。比如加一个 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 文件里。
搞定。一条命令启动整个技术栈,这才是开发该有的样子。
试试在你的项目里跑起来,遇到什么问题随时查日志。