别再手动改配置了!用Docker Compose一键部署你的第一个Web应用(附完整YAML文件)

每次搭建开发环境都要重复安装依赖、配置数据库连接、调试端口冲突?一个简单的Web项目还没开始写业务代码,就被环境问题消耗半天精力。传统开发流程中,这些重复劳动不仅低效,还会导致"在我机器上能跑"的经典问题。容器化技术正是为了解决这类痛点而生,而Docker Compose则将容器化的便利性提升到新高度——用声明式配置描述整个应用栈,一键启动所有服务。

想象一下这样的场景:你正在开发一个包含前端、后端和数据库的完整应用。只需一个命令,所有服务自动启动并互联;修改代码后,依赖项和网络配置始终保持一致;团队成员共享同一套环境定义,彻底告别"配置漂移"。这就是Docker Compose带来的开发体验升级。本文将从一个真实的Python Flask应用案例出发,带你逐步构建完整的容器化解决方案,最后提供可直接复用的YAML模板。

1. 为什么需要Docker Compose?

手动管理多个Docker容器时,开发者需要记忆大量命令参数:-p指定端口映射、-v挂载数据卷、--link连接容器...这些操作不仅繁琐,还难以版本化管理。更麻烦的是,当应用包含数据库、缓存等辅助服务时,启动顺序和网络依赖会让手工操作变得异常复杂。

Docker Compose通过YAML文件定义多容器应用,解决了三大核心问题:

  • 环境标准化:所有服务配置(镜像版本、端口、卷等)以代码形式保存
  • 服务编排:自动处理容器启动顺序和网络连接
  • 开发效率:单条命令即可启停整个应用栈

对比实验:手动启动一个包含PostgreSQL的Flask应用需要执行以下命令:

# 启动数据库容器
docker run -d --name db -e POSTGRES_PASSWORD=123456 -v pg_data:/var/lib/postgresql/data postgres:13

# 启动应用容器并连接数据库
docker run -d --name web -p 5000:5000 --link db -e DATABASE_URL=postgresql://postgres:123456@db:5432/mydb my-flask-app

而使用Docker Compose只需:

docker-compose up -d

背后的docker-compose.yml文件明确定义了服务关系和配置,成为团队共享的唯一真相源。

2. 从零构建容器化Web应用

2.1 准备示例Flask应用

我们先创建一个最简单的Python Web应用来演示完整流程。项目结构如下:

myapp/
├── app.py          # Flask主程序
├── requirements.txt # Python依赖
└── Dockerfile      # 应用容器定义

app.py内容:

from flask import Flask
import os
app = Flask(__name__)

@app.route('/')
def hello():
    db_url = os.getenv('DATABASE_URL', '未配置数据库')
    return f'当前数据库连接: {db_url}'

if __name__ == '__main__':
    app.run(host='0.0.0.0')

requirements.txt

flask==2.0.1

2.2 编写Dockerfile

在项目根目录创建Dockerfile

# 使用官方Python轻量级镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 先复制依赖文件,利用Docker缓存层
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 5000

# 启动命令
CMD ["python", "app.py"]

这个Dockerfile遵循了容器构建的最佳实践:

  1. 使用轻量级基础镜像减少体积
  2. 分离依赖安装和代码复制步骤,利用缓存加速重建
  3. 明确声明需要暴露的端口

3. 编写Docker Compose配置

现在进入核心环节——创建docker-compose.yml文件。我们将定义两个服务:Web应用和PostgreSQL数据库。

version: '3.8'

services:
  web:
    build: .
    ports:
      - "5000:5000"
    environment:
      - DATABASE_URL=postgresql://postgres:123456@db:5432/mydb
    depends_on:
      - db
    volumes:
      - .:/app  # 开发时挂载代码目录,实现热更新

  db:
    image: postgres:13
    environment:
      - POSTGRES_PASSWORD=123456
      - POSTGRES_DB=mydb
    volumes:
      - pg_data:/var/lib/postgresql/data

volumes:
  pg_data:

关键配置解析:

配置项 说明
build: . 指定使用当前目录的Dockerfile构建镜像
depends_on 声明服务依赖关系,确保db先于web启动
volumes 数据卷挂载,db服务用于持久化数据,web服务用于开发时代码热加载
environment 设置容器环境变量,这里配置了数据库连接字符串

4. 高级配置技巧

4.1 多环境配置管理

实际项目中,我们通常需要区分开发、测试和生产环境。Compose支持通过-f参数指定多个配置文件:

# 基础配置(公共部分)
docker-compose.yml

# 开发环境扩展配置
docker-compose.override.yml

# 生产环境配置
docker-compose.prod.yml

示例开发环境扩展配置:

# docker-compose.override.yml
services:
  web:
    environment:
      - FLASK_ENV=development
    ports:
      - "5000:5000"
      - "5678:5678"  # 调试端口

启动时自动合并配置:

docker-compose -f docker-compose.yml -f docker-compose.override.yml up

4.2 健康检查与服务依赖

确保数据库完全就绪后再启动应用:

services:
  web:
    depends_on:
      db:
        condition: service_healthy

  db:
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5

4.3 网络配置最佳实践

默认情况下,Compose会为每个项目创建独立网络。我们可以自定义网络配置:

networks:
  app_net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24

services:
  web:
    networks:
      app_net:
        ipv4_address: 172.20.0.2
  
  db:
    networks:
      app_net:
        ipv4_address: 172.20.0.3

5. 实战操作流程

现在让我们完整走一遍开发工作流:

  1. 启动所有服务
docker-compose up -d
  1. 查看运行状态
docker-compose ps
  1. 查看应用日志
docker-compose logs -f web
  1. 修改代码后自动重载(得益于volume挂载)
# 修改app.py后保存,Flask开发服务器会自动重启
  1. 停止服务并清理
docker-compose down
  1. 保留数据卷的情况下重启
docker-compose up -d

常见问题排查技巧:

  • 如果修改了Dockerfile或Compose配置,需要重建镜像:
    docker-compose up -d --build
    
  • 进入运行中的容器调试:
    docker-compose exec web bash
    
  • 重置所有状态(包括数据卷):
    docker-compose down -v
    

6. 完整YAML模板参考

以下是一个功能更全面的模板,包含Redis缓存和Celery后台任务:

version: '3.8'

services:
  web:
    build: .
    ports:
      - "5000:5000"
    environment:
      - DATABASE_URL=postgresql://postgres:123456@db:5432/mydb
      - REDIS_URL=redis://redis:6379/0
    depends_on:
      - db
      - redis
    volumes:
      - .:/app

  db:
    image: postgres:13
    environment:
      - POSTGRES_PASSWORD=123456
      - POSTGRES_DB=mydb
    volumes:
      - pg_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5

  redis:
    image: redis:6
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

  worker:
    build: .
    command: celery -A app.celery worker --loglevel=info
    environment:
      - DATABASE_URL=postgresql://postgres:123456@db:5432/mydb
      - REDIS_URL=redis://redis:6379/0
    depends_on:
      - db
      - redis

volumes:
  pg_data:
  redis_data:

这个模板展示了Compose处理复杂应用架构的能力,所有服务通过内部DNS自动发现彼此,开发者只需关注业务逻辑的实现。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐