Flask 的 Docker 部署指南

在云原生时代,容器化已成为应用部署的标准实践。风云将带你系统掌握如何将 Flask 应用优雅地部署到 Docker 容器中,让你的 Python Web 项目具备"一次构建,到处运行"的能力。

一、为什么要容器化 Flask 应用?

在深入实践之前,我们先理解容器化的价值,首先是环境一致性要求,告别"在我机器上能跑"的尴尬,开发、测试、生产环境完全一致,在敏捷开发时代,快速部署非常关键,秒级启动,轻松实现水平扩展,资源隔离:每个容器独立运行,互不干扰,版本管理:镜像即版本,回滚就是切换镜像。

二、准备工作:一个典型的 Flask 项目

假设我们有一个简单但完整的 Flask 项目,目录结构如下:

flask-app/

├── app.py # 主应用文件

├── requirements.txt # 依赖清单

├── config.py # 配置文件

├── templates/ # 模板目录

│ └── index.html

├── static/ # 静态资源

│ ├── css/

│ └── js/

└── Dockerfile # 容器构建文件(待创建)

2.1 示例应用代码

app.py - 一个简单的 Flask 应用:

python 复制代码
from flask import Flask, render_template, jsonify
import os


app = Flask(__name__)

@app.route('/')
def index():

    return render_template('index.html')

@app.route('/api/health')
def health_check():

    return jsonify({
        'status': 'healthy',

        'environment': os.getenv('FLASK_ENV', 'production')
    })

@app.route('/api/info')
def info():

    return jsonify({
        'app': 'Flask Docker Demo',

        'version': '1.0.0'
    })

if __name__ == '__main__':
    # 注意:容器内需要监听 0.0.0.0,而不是默认的 127.0.0.1

    app.run(
        host='0.0.0.0',
        port=int(os.getenv('PORT', 5000)),
        debug=os.getenv('FLASK_DEBUG', 'False') == 'True'
    )

requirements.txt - 依赖管理:

Flask==3.0.0

gunicorn==21.2.0

python-dotenv==1.0.0

技术细节:这里引入 gunicorn 是生产环境的最佳实践。Flask 自带的开发服务器不适合生产使用,而 gunicorn 是一个高性能的 WSGI HTTP 服务器。

三、核心:编写 Dockerfile

Dockerfile 是容器化的灵魂,它定义了如何构建镜像。让我们逐步构建一个生产级的 Dockerfile。

3.1 基础版 Dockerfile

第一步:选择基础镜像

FROM python:3.11-slim

第二步:设置工作目录

WORKDIR /app

第三步:复制依赖文件并安装

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

第四步:复制应用代码

COPY . .

第五步:暴露端口

EXPOSE 5000

第六步:定义启动命令

CMD ["python", "app.py"]

逐行解析:

FROM python:3.11-slim:选择官方 Python 3.11 的精简版镜像,体积小且安全

WORKDIR /app:在容器内创建 /app 目录并设为工作目录

COPY requirements.txt:先单独复制依赖文件,利用 Docker 的层缓存机制

RUN pip install:安装 Python 依赖,--no-cache-dir 减少镜像体积

COPY . .:复制所有应用代码到容器

EXPOSE 5000:声明容器监听的端口(文档性质,实际映射需要 -p 参数)

CMD:容器启动时执行的命令

3.2 生产级优化版 Dockerfile

使用多阶段构建(可选,适用于需要编译的场景)

FROM python:3.11-slim as base

设置环境变量

ENV PYTHONUNBUFFERED=1 \

PYTHONDONTWRITEBYTECODE=1 \

PIP_NO_CACHE_DIR=1 \

PIP_DISABLE_PIP_VERSION_CHECK=1

创建非 root 用户(安全最佳实践)

RUN groupadd -r appuser && useradd -r -g appuser appuser

设置工作目录

WORKDIR /app

安装系统依赖(如果需要)

RUN apt-get update && apt-get install -y --no-install-recommends \

gcc \

&& rm -rf /var/lib/apt/lists/*

复制并安装 Python 依赖

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

复制应用代码

COPY --chown=appuser:appuser . .

切换到非 root 用户

USER appuser

暴露端口

EXPOSE 5000

使用 gunicorn 启动(生产环境推荐)

CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "--threads", "2", "--timeout", "60", "app:app"]

优化要点解读:

环境变量设置:

PYTHONUNBUFFERED=1:实时输出日志,便于调试

PYTHONDONTWRITEBYTECODE=1:不生成 .pyc 文件,减少镜像体积

非 root 用户:提升安全性,防止容器逃逸攻击

Gunicorn 配置:

--workers 4:4 个工作进程,通常设置为 CPU核心数 * 2 + 1

--threads 2:每个进程 2 个线程

--timeout 60:请求超时时间

四、构建 Docker 镜像

4.1 基础构建命令

在项目根目录执行

docker build -t flask-app:v1.0 .

参数说明:

-t flask-app:v1.0:为镜像打标签,格式为 名称:版本

.:指定 Dockerfile 所在目录(当前目录)

4.2 查看构建结果

查看本地镜像列表

docker images

输出示例:# REPOSITORY TAG IMAGE ID CREATED SIZE# flask-app v1.0 abc123def456 10 seconds ago 180MB

4.3 构建优化技巧

使用 .dockerignore 文件:

创建 .dockerignore 文件,排除不必要的文件:

pycache*.pyc

*.pyo*.pyd

.Python

env/

venv/

.venv

.git

.gitignore

.dockerignore

.env

*.log*.db

*.sqlite

.pytest_cache

.coverage

htmlcov/

dist/

build/

*.egg-info

这能显著减少构建上下文大小,加快构建速度。

五、运行 Docker 容器

5.1 基础运行命令

docker run -d \

--name flask-container \

-p 8080:5000 \

flask-app:v1.0

参数详解:

-d:后台运行(detached 模式)

--name flask-container:为容器命名,便于管理

-p 8080:5000:端口映射,宿主机端口:容器端口

flask-app:v1.0:使用的镜像

5.2 验证部署

方法1:使用 curl 测试

curl http://localhost:8080/api/health

方法2:浏览器访问# 打开 http://localhost:8080

方法3:查看容器日志

docker logs flask-container

方法4:查看容器状态

docker ps

5.3 高级运行配置

挂载数据卷(持久化数据):

docker run -d \

--name flask-container \

-p 8080:5000 \

-v $(pwd)/data:/app/data \

-v $(pwd)/logs:/app/logs \

flask-app:v1.0

传递环境变量:

docker run -d \

--name flask-container \

-p 8080:5000 \

-e FLASK_ENV=production \

-e DATABASE_URL=postgresql://user:pass@db:5432/mydb \

--env-file .env \

flask-app:v1.0

资源限制:

docker run -d \

--name flask-container \

-p 8080:5000 \

--memory="512m" \

--cpus="1.0" \

flask-app:v1.0

六、容器管理常用命令

查看运行中的容器

docker ps

查看所有容器(包括停止的)

docker ps -a

停止容器

docker stop flask-container

启动已停止的容器

docker start flask-container

重启容器

docker restart flask-container

查看容器日志

docker logs -f flask-container # -f 参数实时跟踪日志

进入容器内部(调试用)

docker exec -it flask-container /bin/bash

查看容器资源使用情况

docker stats flask-container

删除容器

docker rm flask-container # 需要先停止容器

docker rm -f flask-container # 强制删除运行中的容器

七、生产环境最佳实践

7.1 使用 Docker Compose 编排

创建 docker-compose.yml 文件:

version: '3.8'

services:

web:

build: .

image: flask-app:v1.0

container_name: flask-web

ports:

  • "8080:5000"

environment:

  • FLASK_ENV=production

  • DATABASE_URL=postgresql://postgres:password@db:5432/myapp

volumes:

  • ./logs:/app/logs

depends_on:

  • db

restart: unless-stopped

networks:

  • app-network

db:

image: postgres:15-alpine

container_name: flask-db

environment:

  • POSTGRES_USER=postgres

  • POSTGRES_PASSWORD=password

  • POSTGRES_DB=myapp

volumes:

  • postgres-data:/var/lib/postgresql/data

networks:

  • app-network

volumes:

postgres-data:

networks:

app-network:

driver: bridge

使用 Compose 管理:

启动所有服务

docker-compose up -d

查看服务状态

docker-compose ps

查看日志

docker-compose logs -f web

停止所有服务

docker-compose down

重新构建并启动

docker-compose up -d --build

7.2 健康检查配置

在 Dockerfile 中添加健康检查:

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \

CMD curl -f http://localhost:5000/api/health || exit 1

或在 docker-compose.yml 中配置:

services:

web:

... 其他配置

healthcheck:

test: ["CMD", "curl", "-f", "http://localhost:5000/api/health"]

interval: 30s

timeout: 3s

retries: 3

start_period: 5s

7.3 日志管理

配置日志驱动:

docker run -d \

--name flask-container \

-p 8080:5000 \

--log-driver json-file \

--log-opt max-size=10m \

--log-opt max-file=3 \

flask-app:v1.0

7.4 多阶段构建优化镜像体积

构建阶段

FROM python:3.11 as builder

WORKDIR /app

COPY requirements.txt .

RUN pip install --user --no-cache-dir -r requirements.txt

运行阶段

FROM python:3.11-slim

WORKDIR /app

从构建阶段复制依赖

COPY --from=builder /root/.local /root/.local

ENV PATH=/root/.local/bin:$PATH

COPY . .

EXPOSE 5000

CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]

八、常见问题排查

8.1 容器无法访问

问题:浏览器访问 localhost:8080 无响应

排查步骤:

1. 检查容器是否运行

docker ps

2. 查看容器日志

docker logs flask-container

3. 检查端口映射

docker port flask-container

4. 进入容器测试

docker exec -it flask-container curl http://localhost:5000

5. 检查防火墙规则

sudo ufw status

常见原因:

Flask 监听地址不是 0.0.0.0

端口映射配置错误

容器内应用启动失败

8.2 依赖安装失败

问题:构建镜像时 pip 安装报错

解决方案:

使用国内镜像源

RUN pip install --no-cache-dir -r requirements.txt \

-i https://pypi.tuna.tsinghua.edu.cn/simple

或者安装系统依赖

RUN apt-get update && apt-get install -y \

gcc \

python3-dev \

&& rm -rf /var/lib/apt/lists/*

8.3 容器频繁重启

查看容器退出原因

docker inspect flask-container --format='{{.State.Status}}'

查看详细日志

docker logs --tail 100 flask-container

九、性能优化建议

9.1 使用 Alpine 镜像(更小体积)

FROM python:3.11-alpine

Alpine 使用 apk 包管理器

RUN apk add --no-cache gcc musl-dev linux-headers

9.2 启用 Gunicorn 的异步 Worker

安装 gevent

pip install gevent

启动命令

CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "--worker-class", "gevent", "app:app"]

9.3 配置反向代理(Nginx)

docker-compose.yml 添加 Nginx:

services:

nginx:

image: nginx:alpine

ports:

  • "80:80"

volumes:

  • ./nginx.conf:/etc/nginx/nginx.conf:ro

depends_on:

  • web

networks:

  • app-network

十、总结与思考

通过本文的实践,我们完成了从零到一的 Flask 应用容器化部署。这个过程不仅是技术操作的堆砌,更是对现代软件工程理念的践行.容器化是云原生时代的基本功,掌握它,你就掌握了现代应用部署的钥匙。技术的魅力在于不断实践、不断优化,希望这篇文章能成为你容器化之旅的起点。从虚拟机到容器,从单体到微服务,技术的演进始终围绕着"更快、更稳、更省"的目标。每一次部署方式的变革,都是工程师对效率极致追求的体现。容器化不是终点,而是通往云原生架构的必经之路。

相关推荐
飞天小蜈蚣2 小时前
django的模板渲染、for循环标签、继承模板
数据库·python·django
飞Link2 小时前
【Anaconda】Linux(CentOS7)下安装Anaconda教程
linux·运维·python
web3.08889992 小时前
小红书笔记评论API接口详情展示
开发语言·笔记·python
Ama_tor2 小时前
docker|F盘安装の1键部署软件及数据储存+2个保姆级运行实例
运维·docker·容器
手抄二进制2 小时前
使用Anaconda创建python环境并链接到Jupyter
开发语言·python·jupyter
知凡D2 小时前
python脚本打包成exe后,对其引用的日历库实时更新-动态化加载模块
python·测试工具
可爱又迷人的反派角色“yang”2 小时前
GitLab配置与git集成实践
linux·网络·git·docker·云计算·gitlab
kobe_OKOK_2 小时前
快递鸟对接发快递后端设计系统
python·django
阿蔹2 小时前
UI测试自动化-Web-Python-Selenium-2-元素操作、浏览器操作
前端·python·selenium·ui·自动化