上一篇我们用 pytest 给路由和 API 加了自动化测试。第十四篇是在服务器上 手动装 Python、配 venv、起 Gunicorn------能跑,但换一台机器往往又要重来一遍。
这一篇做一件事:用 Docker 把「应用 + 运行环境」打成一个镜像,再用 docker-compose 一键拉起 Flask 和 MySQL。
例子仍是通用的 Note 备忘录项目,不涉及任何真实业务。
1. 学完后你能做什么
- 写
Dockerfile,用 Gunicorn 启动 Flask - 写
docker-compose.yml,Flask + MySQL 一起跑 - 用 环境变量 传配置(接第十二篇)
- 知道 卷(volume) 持久化数据库
- 本地一条命令
docker compose up复现「接近生产」的环境
2. Docker 解决什么问题
| 没有 Docker | 有 Docker |
|---|---|
| 「我机器上能跑啊」 | 镜像里环境一致 |
| Python 版本、系统包装一堆 | 镜像自带依赖 |
| 新人搭环境半天 | docker compose up |
| 生产和本地差一截 | 同一套镜像可部署 |
Docker 不是必须,小项目直接 Gunicorn 也完全可以。团队变大、要 CI/CD、要多环境一致时,Docker 很省心。
3. 整体架构
docker compose up
│
├── 容器 web(Flask + Gunicorn :5000)
│ │
│ └── 连 → db:3306
│
└── 容器 db(MySQL 8)
└── volume 持久化数据
浏览器访问:http://127.0.0.1:5000(映射到 web 容器)。
4. 项目里要加哪些文件
myproject/
├── app/
├── manage.py
├── requirements.txt
├── Dockerfile # 新增
├── docker-compose.yml # 新增
├── .dockerignore # 新增(减小镜像)
└── .env.docker # 可选,compose 读环境变量
5. Dockerfile(Web 镜像)
FROM python:3.11-slim
WORKDIR /app
系统依赖(MySQL 客户端库等,按需)
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc default-libmysqlclient-dev pkg-config \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt gunicorn
COPY . .
ENV FLASK_APP=app
ENV PYTHONUNBUFFERED=1
EXPOSE 5000
CMD "gunicorn", "-w", "2", "-b", "0.0.0.0:5000", "app:app"
说明:
python:3.11-slim:体积小,够用- 先 COPY requirements 再 COPY 代码:改代码时重建层更快
CMD gunicorn:接第十四篇,不用app.run()- worker 容器里 2 个 即可,别贪多
若只用 SQLite、不连 MySQL,可去掉 gcc、mysqlclient 相关 apt 包。
6. .dockerignore
避免把垃圾打进镜像:
.venv
pycache
*.pyc
.git
.pytest_cache
instance/*.db
.env
*.md
tests/
7. docker-compose.yml
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: notes
MYSQL_USER: notes
MYSQL_PASSWORD: notespass
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
healthcheck:
test: "CMD", "mysqladmin", "ping", "-h", "localhost"
interval: 5s
timeout: 5s
retries: 10
web:
build: .
ports:
- "5000:5000"
environment:
FLASK_DEBUG: "0"
SECRET_KEY: "change-me-in-production"
DATABASE_URL: "mysql+pymysql://notes:notespass@db:3306/notes"
depends_on:
db:
condition: service_healthy
command: >
sh -c "
flask db upgrade &&
gunicorn -w 2 -b 0.0.0.0:5000 app:app
"
volumes:
mysql_data:
要点:
- 服务名
db→ Web 容器里主机名就是db(不是127.0.0.1) depends_on+ healthcheck:等 MySQL 就绪再起 Flaskcommand里先flask db upgrade(接第十五篇),再起 Gunicornmysql_datavolume:删容器数据还在
app/__init__.py 需能读 DATABASE_URL(第十二篇环境变量那套)。
8. 启动与常用命令
构建并后台启动
docker compose up -d --build
看日志
docker compose logs -f web
进 web 容器执行 CLI
docker compose exec web flask create-admin admin
停掉
docker compose down
停掉并删数据库卷(慎用!)
docker compose down -v
浏览器打开 http://127.0.0.1:5000。
9. 环境变量怎么管理
不要把真密码写进 Dockerfile 提交 Git。
| 方式 | 用法 |
|---|---|
docker-compose.yml 的 environment |
本地演示可以,生产换 secrets |
.env 文件(compose 自动读) |
SECRET_KEY=xxx 一行一个 |
服务器上 export + compose |
生产常见 |
.env 示例(加入 .gitignore):
SECRET_KEY=本地随机长字符串
MYSQL_PASSWORD=notespass
docker-compose.yml 里可写:
environment:
SECRET_KEY: ${SECRET_KEY}
DATABASE_URL: mysql+pymysql://notes:${MYSQL_PASSWORD}@db:3306/notes
10. 开发时:代码热更新(可选)
生产镜像不必挂载源码;本地开发可挂载目录,改代码重启容器即生效:
web:
build: .
volumes:
- .:/app
environment:
FLASK_DEBUG: "1"
command: flask run --host=0.0.0.0 --port=5000
注意:FLASK_DEBUG=1 只限本地 Docker 开发,生产 compose 仍用 Gunicorn + FLASK_DEBUG=0。
很多人 开发仍用本机 venv + flask run,Docker 只用来测「和生产一致」的集成------这样也行。
11. 和前面各篇怎么串起来
| 篇 | 在 Docker 里 |
|---|---|
| 十二 环境变量 | environment / .env |
| 十四 Gunicorn | CMD 或 compose command |
| 十五 CLI | docker compose exec web flask ... |
| 十六 pytest | CI 里 docker compose run web pytest(可选) |
| 七 Migrate | 启动前 flask db upgrade |
12. 流程示意
docker compose up --build
│
▼
构建 web 镜像(pip install + COPY 代码)
│
▼
启动 db(MySQL + volume)
│
▼
db healthcheck 通过
│
▼
web:flask db upgrade → gunicorn
│
▼
13. 新手常踩的 6 个坑
- Web 连
127.0.0.1:3306--- 在容器里 127.0.0.1 是自己,MySQL 要用主机名db。 - 没等 MySQL 就绪就 migrate --- 用
healthcheck+depends_on。 - 把
.env提交 Git --- 进.gitignore。 - 镜像里用
app.run(debug=True)--- 生产用 Gunicorn。 - 不设 volume --- 容器删了数据库没了。
- 镜像巨大 --- 用
.dockerignore、多阶段构建(进阶再学)。
14. 小结
记住五件事:
Dockerfile:装依赖 +gunicorn app:appdocker-compose.yml:web + db + volume- 数据库主机名用服务名
db - 启动前
flask db upgrade - 密钥走环境变量,别写进镜像
十七篇下来,你已经会:本机开发 → 测试 → Gunicorn 部署 → CLI 运维 → Docker 一键环境。
