实战:前后端分别打包,用 docker compose 一键启动

需求是:我有一个后端 为 python flask ,前端为 vue3 的网页应用,目前在本地运行,想打包给同事用,在不给同事配置编程环境的前提下, 怎么用docker?

目录结构(示例)

project-root/
  backend/
    app.py
    requirements.txt
    Dockerfile
  frontend/
    package.json
    vite.config.ts
    src/...
    Dockerfile
  nginx/
    default.conf
  docker-compose.yml

backend/Dockerfile(Flask 用 Gunicorn 生产启动)

# 使用更小的基础镜像
FROM python:3.10-slim

WORKDIR /app
# 减少重复构建时间
COPY backend/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt && \
    pip install --no-cache-dir gunicorn

COPY backend/ ./

# 以 Gunicorn 方式对外(假设 Flask app = app:app)
EXPOSE 5000
CMD ["gunicorn", "-w", "2", "-k", "gthread", "-b", "0.0.0.0:5000", "app:app"]

如果你的 Flask 入口不叫 app:app,把最后一行对应改成 模块名:对象名

frontend/Dockerfile(Vue3 构建为静态资源)

# 构建阶段
FROM node:20 AS builder
WORKDIR /app
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run build

# 运行阶段,用 Nginx 托管静态文件
FROM nginx:1.27-alpine
# 将构建产物复制到默认静态目录
COPY --from=builder /app/dist/ /usr/share/nginx/html/
# 自定义 Nginx 站点配置(反向代理到后端)
COPY nginx/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

nginx/default.conf(前端静态 + 反向代理 API)

请把 backend:5000 和你的实际 API 路径对齐(下例假设 /api 前缀)。

server {
  listen 80;
  server_name _;

  # 前端静态资源
  root /usr/share/nginx/html;
  index index.html;

  # Vue SPA 刷新 404 处理
  location / {
    try_files $uri $uri/ /index.html;
  }

  # 反向代理到 Flask
  location /api/ {
    proxy_pass http://backend:5000/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_http_version 1.1;
  }
}

你的前端里把接口基址配置为 '/api'(相对路径)即可,Compose 会把 backend 这个服务名解析成容器内可达的主机名。

docker-compose.yml(一键编排)

version: "3.9"
services:
  backend:
    build:
      context: .
    # 指明后端 Dockerfile 路径
      dockerfile: backend/Dockerfile
    container_name: myapp-backend
    ports:
      - "5000:5000"   # 如不需要在宿主单独访问后端,可去掉这行
    environment:
      - PYTHONUNBUFFERED=1
      # - FLASK_ENV=production
      # 你的自定义环境变量...

  frontend:
    build:
      context: .
      dockerfile: frontend/Dockerfile
    container_name: myapp-frontend
    depends_on:
      - backend
    ports:
      - "8080:80"     # 给同事访问的端口:http://localhost:8080

打包与运行

在项目根目录执行:

# 第一次构建(或代码有变更时重建)
docker compose build

# 启动
docker compose up -d

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

给同事交付

  • 打包方式 A:把整个仓库发给同事(含上述 Dockerfile、compose 文件),同事执行 docker compose up -d 即可。

  • 打包方式 B:你先在本地构建并推送镜像到私有镜像库(如阿里云/ghcr),同事只需 docker compose pull && docker compose up -d

  • 配置项(如后端数据库地址、密钥)统一用 环境变量,并在 docker-compose.yml 里通过 .env 引入,便于不同同事/环境的差异化。


你碰到的报错怎么解决

docker : 无法将“docker”项识别为 cmdlet...

说明你的 Windows 机器未安装或未启动 Docker Desktop,或 PowerShell 没找到可执行文件。

处理步骤:

  1. 安装 [Docker Desktop for Windows](需要启用 WSL2 或 Hyper-V,Win10/11 都支持)。

  2. 安装完成后重启电脑,确认 Docker Desktop 已启动(系统托盘里有鲸鱼图标)。

  3. 打开新的 PowerShell 窗口,执行:

    docker --version
    docker compose version
    

    能看到版本号就可以继续 docker compose up -d 了。

如果公司政策禁止安装 Docker Desktop:可以改用 单文件交付(后端用 PyInstaller 打包为 EXE,前端构建后用一个便携 Nginx 或直接用 http-server 托管),但这条线路在跨平台、可复现性、依赖一致性上不如 Docker。


什么时候用“单容器”?

如果你希望更简(牺牲一点可维护性),也可以把前端构建产物和后端一起塞进一个镜像,用 Nginx 代理静态和 /api,再用 supervisord 同时拉起 Gunicorn+Nginx。优点是只有一个镜像、一个容器;缺点是职责耦合、更新不够灵活。团队协作/长期维护我更推荐上面的双容器方案。


小结(给你做决策用)

  • 是否合适:✅ 绝对合适,是团队内“零环境交付”的标准做法。

  • 前置条件:同事机器需安装 Docker(Desktop/Engine)。

  • 落地方案:用 docker compose 管理前后端两个容器,前端 Nginx 反代到 Flask。

  • 优点:环境一致、启动简单、平台通用、便于后续 CI/CD。

  • 备选:若无法装 Docker,再考虑 EXE + 便携 Nginx 的“半静态”交付。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值