首先完成“从原型到生产:部署思维”即可解锁本课程。转到上一课

简介

当你在笔记本电脑上构建一个 AI 生成的 Web 应用时,它能够运行是因为已安装 Python、依赖项位于正确的位置,并且环境变量已恰当设置。但如果把这个应用迁移到服务器、同事的电脑或云平台上,往往突然就什么都跑不起来了。Docker 通过将应用程序及其所需的一切打包到一个称为容器的单一可移植单元中来解决这个问题。

在本课中,你将为典型的 Python Web 应用编写 Dockerfile,将其构建为镜像,并使用 Docker Compose 将应用与其依赖的任何服务(如数据库或 Redis)一起运行。重点在于实践:到课程结束时,你应该能够自信地将一个小型 AI 生成的 Web 应用容器化。

编写你的第一个 Dockerfile

Dockerfile 是一个文本文件,Docker 读取其中的指令来组装镜像。可以将其理解为一份配方:每一行添加一个层。对于 AI 生成的 Web 应用,最常见的设置是由 Uvicorn 提供服务的 FastAPI 或 Flask 应用。

下面是一个用于 Python Web 应用的最小化 Dockerfile:

dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

让我们逐行解析。`FROM python:3.11-slim` 从官方的轻量级 Python 镜像开始。`WORKDIR /app` 设置容器内的工作目录,以便后续命令在该目录中执行。`COPY requirements.txt .` 首先仅复制依赖文件,这使得 Docker 能够缓存 `pip install` 步骤,在你只修改代码时跳过该步骤。然后 `COPY . .` 复制你的源代码。`EXPOSE 8000` 声明应用监听的端口。`CMD` 定义容器启动时运行的命令。

一个常见的错误是先复制所有文件再安装依赖。这会导致每次你修改单个 Python 文件时,Docker 都必须重建那个庞大的 `pip install` 层。顺序对构建速度至关重要。

构建上述 Dockerfile 时 Docker 镜像各层示意图,从基础镜像 python:3.11-slim 到应用代码

构建与运行镜像

Dockerfile 写好之后,只需两条命令就能把它变成运行中的容器。首先,构建镜像并为其打上名称标签:

bash
docker build -t my-ai-app:1.0 .

其中 `.` 告诉 Docker 在哪里查找 Dockerfile(即当前目录)。`-t` 参数用于指定镜像的名称和版本标签,方便日后引用。然后运行它:

bash
docker run -p 8000:8000 my-ai-app:1.0

`-p 8000:8000` 参数将主机的 8000 端口映射到容器内的 8000 端口。如果不加这个参数,应用虽然会运行,但你无法通过浏览器访问它。打开 `http://localhost:8000`,你应该能看到应用正常响应。

若要验证镜像是否构建成功,可列出所有镜像:

bash
docker images

若要查看正在运行的容器,使用 `docker ps`。加上 `-a` 可以同时显示已停止的容器。

使用 Docker Compose 管理多服务应用

大多数 AI Web 应用并非独立运行。它们通常需要数据库(如 PostgreSQL)、缓存(如 Redis),或两者兼有。如果每项服务都用单独的 `docker run` 命令来管理,很快就会变得一团糟。Docker Compose 允许你在一个 YAML 文件中声明所有服务,然后一并启动。

新建一个名为 `docker-compose.yml` 的文件:

yaml
services:
web:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:16
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:

注意 `web` 服务是如何通过主机名引用 `db` 的。Docker Compose 会创建一个私有网络,服务之间可通过服务名称互相访问。`depends_on` 指令告诉 Docker 先启动数据库,再启动 Web 应用。命名数据卷 `pgdata` 即使在容器被移除后也能保证数据库数据不丢失。

启动所有服务:

bash
docker compose up --build

加上 `-d` 参数即可在后台运行。要停止并移除容器,可执行:

bash
docker compose down

常见错误及如何避免

忘记创建 `.dockerignore` 文件是一个常见的疏忽。请与 Dockerfile 一起创建它:

bash
echo -e "__pycache__\n.git\n.env\n*.pyc" > .dockerignore

没有它,你的镜像会携带不必要的文件,减慢构建速度,并存在泄露 `.env` 等包含 API 密钥的敏感信息的风险。

另一个陷阱是将密钥硬编码到镜像中。绝对不要将 API 密钥或数据库密码直接写入 Dockerfile。使用环境变量,或在运行时挂载密钥文件。

最后,默认以 root 用户运行容器在生产环境中存在安全风险。当你准备正式部署时,请在 Dockerfile 中添加一个非 root 用户。

总结

Dockerfile 描述了如何将你的应用打包成镜像。Docker Compose 通过一个 YAML 文件将多个容器编排在一起。对于 AI 生成的网络应用,典型的工作流程是:编写一个 Dockerfile 先复制依赖项,通过 `docker build` 构建镜像,使用 `docker run -p` 运行它,并在添加数据库等服务时扩展到 Compose。掌握这四个命令和一种 YAML 结构,就能让你完成 90% 的容器化应用准备工作,可部署到任何云平台。

课后练习

课程检查点

巩固所学知识,获取作业反馈。

0/1
已回答 · 0/1
使用 Docker 将应用程序容器化