Jiwon Min Developer

使用 Docker Compose 构建生产级的本地开发环境

“在我电脑上可以正常运行啊?” 这句话,作为开发者,您可能都说过或者听过。开发环境与实际服务运行的生产环境之间的细微差异,是导致意外错误和部署失败的主要原因。因为存在库版本、操作系统、系统配置等众多变量。为解决这些问题而出现的技术就是 Docker

Docker 将应用程序及其所有依赖项打包到一个名为“容器”的隔离空间中,确保在任何环境下都能以相同的方式运行。这使得开发者可以在本地 PC 上轻松构建与生产环境几乎一致的环境,并与团队成员共享统一的开发环境。本文将通过分步指南,介绍如何使用 Docker Compose 构建一个由 Python Django Web 框架、PostgreSQL 数据库和 Redis 缓存服务器组成的多容器开发环境。

Building a Production-Ready Local Development Environment with Docker Compose

© AI Generated by Imagen 4.0


为什么要使用 Docker?

在开始构建之前,我们先来明确一下使用 Docker 的理由。

  • 环境一致性: Docker 将应用程序运行所需的一切(代码、运行时、系统工具、库等)都打包到一个容器镜像中。通过这个镜像,可以确保在开发、预发布和生产环境中都拥有一致的环境,从而从根本上杜绝“因环境差异导致”的错误。
  • 隔离的环境: 每个容器都在与主机系统及其他容器隔离的环境中运行。这可以防止不同项目的不同版本的库或数据库之间发生冲突。
  • 快速配置与部署: 通过基于代码的配置文件 Dockerfiledocker-compose.yml,可以实现开发环境的自动化构建。即使有新团队成员加入,也无需经历复杂的安装过程,只需几个命令即可立即配置好整个开发环境。
  • 云友好: 诸如 AWS 的 ECS (Elastic Container Service)EKS (Elastic Kubernetes Service) 等现代云服务都是基于容器运行的。在本地使用 Docker 是迈向云部署流水线的第一步。

项目结构设计

为了进行高效管理,我们将采用以下目录结构来开始项目。

my-project/
├── .env          # 环境变量文件
├── docker-compose.yml # Docker Compose 配置文件
└── app/
    ├── Dockerfile    # Django 应用的 Dockerfile
    ├── manage.py
    ├── myproject/
    │   ├── settings.py
    │   └── ...
    └── requirements.txt # Python 依赖列表

第 1 步:为 Django 应用程序编写 Dockerfile

首先,我们来编写一个 Dockerfile,它定义了用于运行 Django 应用程序的容器镜像。该文件位于 app/ 目录下。

app/Dockerfile

# 1. 选择基础镜像
FROM python:3.11-slim

# 2. 设置 Python 相关环境变量
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# 3. 创建并设置工作目录
WORKDIR /app

# 4. 复制并安装依赖文件
COPY requirements.txt .
RUN pip install --upgrade pip && pip install -r requirements.txt

# 5. 复制应用程序代码
COPY . .

# 6. 运行 Django 开发服务器
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

app/requirements.txt

Django>=4.2
psycopg2-binary
redis
gunicorn

上述 Dockerfile 以 Python 3.11 镜像为基础,定义了安装所需软件包、复制应用程序代码以及启动开发服务器的过程。

第 2 步:使用 Docker Compose 进行服务编排

现在,在项目的根目录下创建一个 docker-compose.yml 文件,用它来一次性定义并连接多个服务(Web、数据库、缓存)。

docker-compose.yml

version: '3.8'

services:
  # 1. Django Web 服务
  web:
    build:
      context: ./app
      dockerfile: Dockerfile
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - ./app:/app  # 将本地代码与容器内代码实时同步
    ports:
      - "8000:8000" # 连接主机的 8000 端口和容器的 8000 端口
    env_file:
      - ./.env      # 加载环境变量文件
    depends_on:
      - db
      - redis

  # 2. PostgreSQL 数据库服务
  db:
    image: postgres:15
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment:
      - POSTGRES_DB=${SQL_DATABASE}
      - POSTGRES_USER=${SQL_USER}
      - POSTGRES_PASSWORD=${SQL_PASSWORD}

  # 3. Redis 缓存服务
  redis:
    image: redis:7

volumes:
  postgres_data: # 用于持久化存储数据库数据的卷

这个配置文件定义了三个服务:webdbredis

  • web:通过构建 app/Dockerfile 来创建。它将本地的 app 目录挂载到容器内的 /app 目录,使得代码的修改能够实时反映出来。
  • db:使用官方的 PostgreSQL 镜像,并通过一个名为 postgres_data卷 (volume) 来确保即使容器被删除,数据也能持久化保存。
  • redis:使用官方的 Redis 镜像。
  • depends_on:设置了依赖关系,以确保 web 服务在 dbredis 服务启动之后再启动。

第 3 步:管理环境变量(.env 文件)

对于数据库连接信息等敏感数据,使用环境变量而不是直接硬编码到代码中,是更安全、更可取的做法。在项目根目录下创建一个 .env 文件。

.env

# PostgreSQL Settings
SQL_DATABASE=mydb
SQL_USER=myuser
SQL_PASSWORD=mypassword

# Django Settings
SECRET_KEY=your-django-secret-key-here
DEBUG=1

这些分离出来的环境变量会通过 docker-compose.yml 文件中的 env_file 指令注入到 web 服务中。您需要在 Django 的 settings.py 文件中进行修改,使用 os.environ.get() 来读取这些值。

运行与验证

所有配置都已完成。现在,在终端中运行以下命令来启动整个开发环境。

# 构建并运行容器镜像(添加 -d 选项可在后台运行)
docker-compose up --build

# 查看正在运行的容器列表
docker-compose ps

# 运行 Django 数据库迁移
docker-compose exec web python manage.py migrate

docker-compose up 命令成功执行后,您就可以在 Web 浏览器中访问 http://localhost:8000,确认 Django 应用程序已与 PostgreSQL 数据库和 Redis 正常联动并运行。修改代码后,无需额外的构建过程,更改会立即反映在容器中。

如此一来,利用 Docker Compose,即使是复杂的多服务架构,也可以通过几个配置文件和命令轻松管理。这不仅适用于个人项目,在多人协作的团队项目中,它也是实现开发环境标准化最大化生产力的强大工具。此外,这样容器化的应用程序在未来迁移到 AWS 等云环境时,将占据非常有利的位置。

参考资料