人人都能学编程
English 开始学习
专项 · DevOps第 3 课 / 共 5 课免费阅读

Docker Compose · DevOps:容器、CI 与 Kubernetes

一个需要数据库、缓存和后台任务的应用,怎么跑起来?

课程目录

为什么需要它

真实的应用由好几个程序组成:Web 服务器、数据库、缓存、后台任务。用正确的设置一个一个手动启动,很容易出错。Docker Compose 用一个文件描述所有服务,在任何机器上一条命令就能把整套系统启动起来。

直觉理解

compose.yaml 里列出了服务。每个服务就是一个容器:

services:
  web:
    build: .                 # 用这里的 Dockerfile 构建
    ports:
      - "8080:8000"          # 你电脑的 8080 → 容器的 8000
    environment:
      DATABASE_URL: postgres://shop:shop@db:5432/shop
    depends_on: [db]         # 先启动 db
  db:
    image: postgres:16       # 用现成的镜像
    volumes:
      - dbdata:/var/lib/postgresql/data
volumes:
  dbdata:
  • 服务之间用服务名互相访问:在 web 里,数据库的主机名是 db,而不是 localhost(每个容器都有自己的 localhost)。
  • ports 把端口发布到你的电脑上:"主机端口:容器端口"。
  • 命名的卷(volume)在容器重建时保留数据。
  • depends_on 控制启动顺序。(它只等容器启动,不等数据库准备好接受连接;要等就得加健康检查。)

docker compose up 启动全部服务;docker compose down 停止它们。

YAML 对缩进很敏感:用空格,永远不要用 Tab。

定义

服务

One container in a Compose file, with its image or build, ports, environment and volumes.
Compose 文件里的一个容器,带着它的镜像或构建方式、端口、环境变量和卷。

卷

Storage that lives outside a container, so data survives when the container is replaced.
存在容器之外的存储,容器被替换时数据仍然保留。

端口映射

"8080:8000" forwards port 8080 on your machine to port 8000 inside the container.
"8080:8000" 把你电脑上的 8080 端口转发到容器里的 8000 端口。

示例

一个 Web 应用和它的数据库

在互动课里运行

运行它,查看启动顺序和解析后的文件。

services:
  web:
    build: .
    ports:
      - "8080:8000"
    environment:
      DATABASE_URL: postgres://shop:shop@db:5432/shop
    depends_on: [db]
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: shop
      POSTGRES_PASSWORD: shop
    volumes:
      - dbdata:/var/lib/postgresql/data
volumes:
  dbdata:
逐步执行
  1. L3web 用这个目录里的 Dockerfile 构建。
  2. L5在你的电脑上打开 http://localhost:8080,就能访问容器里的 8000 端口。
  3. L7主机名是服务名 db。
  4. L8db 先于 web 启动。
  5. L15数据库文件放在命名卷里,重启后还在。

常见错误

在容器里用 localhost

在容器里,localhost 指的是这个容器自己。用另一个服务的名字(db、redis)作为主机名。

数据没放进卷

没有卷的数据库,容器一重建,数据就全没了。在它的数据目录上挂一个命名卷。

以为 depends_on 会等服务就绪

depends_on 只管启动顺序。应用应该重试数据库连接,或者配合健康检查使用 condition: service_healthy。

小测验

1. 在 `api` 容器里,用什么主机名访问 `redis` 服务?

  1. Aredis
  2. Blocalhost
  3. C127.0.0.1
查看答案

答案:A

Compose 给每个服务一个名字,其他服务可以把它当主机名用。

2. `ports: ["5000:80"]`。浏览器要访问哪里?

  1. Ahttp://localhost:5000
  2. Bhttp://localhost:80
  3. Chttp://localhost:5080
查看答案

答案:A

主机:容器:你电脑的 5000 转发到容器的 80。

动手练习

3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。

  1. 预测输出启动顺序

    Compose 会按什么顺序启动这些服务?(几个服务同时可以启动时,这里按字母顺序启动。)

  2. 改需求web 连不上数据库

    web 连接数据库时报错 "connection refused"。修好 DATABASE_URL 里的数据库主机名,并确保 db 先于 web 启动。

  3. 从零写三个服务的系统

    写一个有三个服务的 Compose 文件:

    • web:用 . 构建,发布 8080:8000,在 api 之后启动
    • api:镜像 shop-api:1.4,环境变量 DB_HOST: db,在 db 之后启动
    • db:镜像 postgres:16,把命名卷 dbdata 挂到 /var/lib/postgresql/data

    在顶层也要声明 dbdata 这个卷。

在互动课里练这一课

打开互动课,这些例子都能直接改、直接运行,练习题提交马上判题。免费开始,不用注册。

互动课按顺序解锁:前面的课还没学,会先带你到课程地图。

本课术语

术语中文英文定义
Docker ComposeDocker ComposeRuns several containers described in one YAML file.
Volume卷Storage that outlives a container.
YAMLYAMLAn indentation-based text format for configuration.