
字节笔记本
2026年10月6日 · 约 21 分钟读完
AI 工作流 06:Docker 容器化与 CI/CD
本文是「AI 工作流」专栏的一篇,补上工程交付的关键一环:用 Docker 把应用容器化,再用 CI/CD 让测试与部署在每次 push 代码后自动完成。
本文你会看到:Docker 核心概念与上手命令、写 Dockerfile 的正确姿势、docker-compose 编排多服务、GitHub Actions 自动测试与部署,以及 AI 应用部署特有的三个坑。
一、"在我电脑上能跑",Docker 来终结
在自己电脑上写好的项目发给同事,对方回复:跑不起来,缺这个库、那个版本不对。把代码部署到服务器,又发现服务器是 Ubuntu、本地是 macOS,服务器 Python 是 3.8、本地是 3.12,还缺一堆系统依赖,折腾一天才能跑起来。
根本原因只有一个:代码依赖一整套环境,换了地方环境不一致就崩。
Docker 的解法,是把代码、依赖、操作系统环境一起打包成一个标准"集装箱",官方叫镜像(Image)。镜像搬到任何一台装了 Docker 的机器上,都能开箱即跑。
三个核心概念必须先分清:
| 概念 | 类比 | 一句话 |
|---|---|---|
| 镜像(Image) | 蛋糕配方 | 只读模板,包含代码与环境 |
| 容器(Container) | 烤出的蛋糕 | 镜像跑起来的实例,可启停 |
| 仓库(Registry) | 蛋糕店 | 存放镜像,最出名的是 Docker Hub |
关系是 镜像 --run--> 容器,类比面向对象里的 类 --new--> 对象。
和虚拟机对比,容器胜在轻:
| 维度 | 虚拟机 | Docker 容器 |
|---|---|---|
| 启动时间 | 分钟级 | 秒级 |
| 体积 | GB 级 | MB 级 |
| 资源占用 | 高(每个带完整操作系统) | 低(共享内核) |
| 隔离性 | 强 | 中等 |
一句话记忆:虚拟机像租一整套独立公寓,Docker 像合租一个房间,便宜够用。

二、5 分钟跑起第一个容器
安装:macOS 和 Windows 直接下载 Docker Desktop;Linux 一行命令搞定:
curl -fsSL https://get.docker.com | sh装完打开终端验证:
docker --version # 看版本
docker run hello-world # 跑官方测试镜像看到 "Hello from Docker!" 就成功了。再玩一个现成镜像,跑一个 nginx:
# 拉取 nginx 镜像
docker pull nginx
# 把容器的 80 端口映射到主机 8080
docker run -d -p 8080:80 --name my-nginx nginx
# 浏览器打开 http://localhost:8080 就能看到 nginx 欢迎页下面这些常用命令值得形成肌肉记忆:
docker ps # 看正在跑的容器
docker ps -a # 看所有容器(包括停止的)
docker stop my-nginx # 停止
docker start my-nginx # 启动
docker rm my-nginx # 删除容器
docker logs my-nginx # 看日志
docker exec -it my-nginx bash # 进入容器(调试必备)
docker images # 看本地镜像
docker rmi nginx # 删除镜像三、写 Dockerfile:把应用容器化
假设项目是一个 FastAPI 写的待办清单后端,结构如下:
my-server/
├── main.py
└── requirements.txt在项目根目录新建一个无后缀的 Dockerfile:
# 基础镜像:用官方 Python 精简版
FROM python:3.12-slim
# 设置工作目录
WORKDIR /app
# 先复制依赖文件(利用 Docker 缓存层,加速构建)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 再复制源代码
COPY . .
# 暴露端口(文档作用,实际映射靠 -p)
EXPOSE 8000
# 启动命令
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]构建并运行:
# 构建镜像(注意最后那个点,表示当前目录)
docker build -t my-todo-server:1.0 .
# 运行容器
docker run -d -p 8000:8000 --name todo-server my-todo-server:1.0
# 测试接口
curl http://localhost:8000/api/todos分层缓存:构建快的关键
Dockerfile 的每条指令(FROM / RUN / COPY)都会生成一层(layer),层是只读的、可缓存的。这也是为什么把 COPY requirements.txt 和 COPY . . 分开写:依赖不常变,能命中缓存,构建明显加快。
三个实用优化:
- 指令按变化频率从低到高排列:基础镜像、系统依赖、应用依赖、代码。
- 用
.dockerignore排除不需要进入镜像的文件,写法类似 .gitignore:
.git
node_modules
__pycache__
*.pyc
.env
.venv- 用多阶段构建减小镜像体积(进阶技巧)。
四、docker-compose:一键启动整个系统
真实项目通常多个服务一起跑:前端、后端、数据库、Redis。一个个 docker run 太累,docker-compose 用一个 YAML 文件管理所有服务。新建 docker-compose.yml:
version: "3.9"
services:
# 数据库
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: "123456"
POSTGRES_DB: myapp
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data # 数据持久化
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
# Redis
redis:
image: redis:7
ports:
- "6379:6379"
# 后端(用上面写好的 Dockerfile 构建)
server:
build: ./server # 指向 Dockerfile 所在目录
ports:
- "8000:8000"
environment:
DATABASE_URL: postgres://postgres:123456@db:5432/myapp
REDIS_URL: redis://redis:6379/0
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
# 前端
web:
build: ./web
ports:
- "5173:5173"
volumes:
pgdata: # 声明数据卷,防止容器删了数据没了常用操作一行命令:
# 一键启动所有服务(后台)
docker compose up -d
# 看日志
docker compose logs -f server
# 停止所有
docker compose down
# 改了代码后重新构建并启动
docker compose up -d --build一个 up -d 把整个多服务架构跑起来。新同事入职、CI 环境、生产部署,用同一个 compose 文件,环境绝对一致。
五、CI/CD:让代码自动测试、自动部署
CI(Continuous Integration,持续集成):代码 push 后自动跑测试和构建,保证"代码一直是好的"。
CD(Continuous Deployment/Delivery,持续部署/交付):测试通过后自动部署到生产,保证"上线不靠人肉"。
为什么建议掌握:远程岗位的 JD 里经常明确写着"熟悉 Docker 容器化与 CI/CD 流程"。原因有三:没有 CI/CD 时,谁合并代码谁手动测试,效率低且易出错;AI 应用迭代快,Prompt 和模型经常调整,需要频繁上线,必须自动化;团队协作里,push 代码后自动测试、通过后自动部署,全团队受益。
GitHub Actions 是 GitHub 内置的 CI/CD 工具,个人项目免费额度够用,是最推荐的入门选择。在项目根目录新建 .github/workflows/ci.yml:
name: CI
# 什么时候触发:push 到 main 分支 或 提 PR 时
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest # 跑在 GitHub 提供的 Linux 机器上
steps:
# 第 1 步:拉代码
- uses: actions/checkout@v4
# 第 2 步:装 Python
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
# 第 3 步:装依赖
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install pytest
# 第 4 步:跑测试
- name: Run tests
run: pytest tests/ -v
# 第 5 步:构建 Docker 镜像(验证能构建成功)
- name: Build Docker image
run: docker build -t my-todo-server:ci .保存后,每次 push 代码到 GitHub,GitHub 会自动开一台 Linux 机器,拉代码、装依赖、跑测试、构建 Docker 镜像。任何一步失败,PR 上显示红叉;全绿显示绿勾。

CI 跑通后可以加 CD:测试通过后自动部署。下面是 SSH 部署到自有服务器的例子:
name: CI/CD
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
# 这里简化处理,实际可用 needs 让部署依赖测试任务
steps:
- uses: actions/checkout@v4
- name: Build and push image
run: |
echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker build -t myuser/todo-server:latest .
docker push myuser/todo-server:latest
- name: Deploy to server
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
cd /opt/myapp
docker compose pull
docker compose up -d
docker image prune -f两个关键点:
- 密码和密钥绝不写在 yml 里,统一用 GitHub 的 Secrets(仓库 Settings 里的 Secrets and variables)配置。
- 整体流程:CI 构建镜像,推到 Docker Hub,SSH 到服务器拉新镜像并重启服务。
六、部署上云:最省钱的路径
个人项目的低成本组合:
| 服务 | 推荐 | 价格 |
|---|---|---|
| 服务器 | 阿里云/腾讯云轻量应用服务器、Hetzner、DigitalOcean | ¥24/月起 / $4/月起 |
| 域名 | Cloudflare / 阿里云 | ¥30/年起 |
| HTTPS | Cloudflare 免费证书 / Caddy 自动证书 | 免费 |
| 镜像仓库 | Docker Hub(公开免费)/ 阿里云 ACR | 免费 |
部署流程(简化版):
# 1. 买台云服务器,装 Docker
ssh root@your-server
curl -fsSL https://get.docker.com | sh
# 2. 上传项目代码(或用 git clone)
git clone https://github.com/you/myapp.git
cd myapp
# 3. 配置生产环境变量
cp .env.example .env
vim .env # 填生产环境的数据库密码、API Key
# 4. 启动
docker compose up -d
# 5. 配置反向代理 + HTTPS(用 Caddy 最简单)
# Caddyfile:
# yourdomain.com {
# reverse_proxy localhost:8000
# }走到这里,项目就从"本地能跑"变成了"全世界能访问"。
七、AI 应用部署的三个坑
7.1 API Key 安全
绝不能把 API Key 写进代码或打进 Docker 镜像。正确做法是用环境变量:
import os
api_key = os.getenv("OPENAI_API_KEY")Dockerfile 里不要写 ENV OPENAI_API_KEY=xxx,要么运行时用 docker run -e 传入,要么在 docker-compose.yml 里从 .env 文件读取:
services:
server:
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}.env 文件必须加进 .gitignore,绝不能提交到 Git。
7.2 长时间任务
大模型生成可能要几十秒,HTTP 请求超时设置要给够:
import openai
client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"), timeout=120)或者改成异步任务:请求扔进 Redis 队列慢慢处理,前端轮询结果。
7.3 流式输出的代理
如果应用用 SSE 流式输出,反向代理(nginx/Caddy)要关掉缓冲,否则流式输出会失效:
location /api/chat {
proxy_pass http://localhost:8000;
proxy_buffering off;
proxy_cache off;
chunked_transfer_encoding on;
}八、要点回顾
- Docker 把"代码加环境"打包成镜像,做到一次构建、到处运行。
- 三个核心概念:镜像(模板)、容器(运行实例)、仓库(存镜像)。
- Dockerfile 用指令描述构建过程,分层缓存加速构建,变化频率低的写前面。
- docker-compose 用一个 yml 管理多个服务,
docker compose up -d一键启动整个系统。 - CI 自动测试构建,CD 自动部署,GitHub Actions 是最易上手的 CI/CD 工具。
- AI 应用部署额外注意:API Key 走环境变量、超时给够、流式输出关代理缓冲。
动手练习
- 给一个前后端分离的待办清单项目写 Dockerfile(前端一个、后端一个),再加 docker-compose.yml(含 PostgreSQL),
docker compose up -d一键跑起来。 - 把项目推到 GitHub,加
.github/workflows/ci.yml,让每次 push 自动跑测试;还没有测试就先加一个简单的导入测试。 - 买一台最便宜的云服务器,或用免费的 Render/Railway,把项目部署上线,让朋友能通过公网访问。
- 进阶:给项目加
.dockerignore,用多阶段构建把镜像体积从 1GB 压到 200MB 以内。
延伸阅读
- Docker 官方文档:https://docs.docker.com
- Docker Compose 参考:https://docs.docker.com/compose/
- GitHub Actions 文档:https://docs.github.com/actions
- Caddy 服务器(最简单的反代与自动 HTTPS):https://caddyserver.com
- 书:《Docker 容器与容器云》,深入原理
容器与流水线打稳了工程地基,接下来就可以放心进入模型侧:用尽量少的数学,理解 Token、Embedding 和注意力机制到底在做什么。



