把离线 Python 项目塞进 Docker:从 0 到 1 的踩坑实录,一口气讲透 10 个最常见困惑


写在前面:为什么要读这篇博文?

你可能遇到过这些场景:

  • 公司内网不通 Docker Hub,拉不到镜像;
  • 项目要跑在 port1 端口,同时还得访问宿主机 port2 的服务;
  • 字体、时区、依赖统统要离线搞定;
  • 领导一句「用 Docker 部署」,你却连 Dockerfile 都没写过。

别怕!本文用一个真实项目「data_tools」做主线,手把手带你走完「本地打包 → 离线镜像 → 端口映射 → 数据持久 → 一键启动」全流程。读完你就能独立把自己的 Python 项目装进容器并上线运行。


目录

  1. 思路总览:一张图看懂整个流程
  2. 环境准备:你需要提前下载好的 3 个文件
  3. Dockerfile 拆解:逐行解释,小白也能改
  4. 构建镜像:离线也能玩 docker build
  5. docker-compose.yml:端口、挂载、时区一次配齐
  6. 启动与验证:3 条命令让服务跑起来
  7. 常见坑 & 解决方案:字体 404、端口不通、时区不对
  8. 进阶技巧:如何只更新单个容器而不动其它服务
  9. 总结 & 思维导图

1️⃣ 思路总览:一张图看懂整个流程

lua 复制代码
┌─────────────┐      ┌──────────────┐      ┌──────────────┐
│  python310  │─────▶│  docker load │─────▶│  本地镜像    │
│   .tar      │      │              │      │ python:3.10  │
└─────────────┘      └──────────────┘      └──────┬───────┘
                                                  │
                    ┌───────────────────────────────┴────────────┐
                    │  Dockerfile + docker-compose.yml            │
                    │  - 安装字体、依赖                         │
                    │  - 暴露 prot1                             │
                    │  - 映射 prot2                            │
                    └──────┬────────────────────────┬───────────┘
                           │                        │
                 ┌─────────▼────────┐      ┌───────▼────────┐
                 │  data_tools│      │  宿主机 port2   │
                 │    容器          │◀─────┤   服务         │
                 └──────────────────┘      └────────────────┘

2️⃣ 环境准备:提前下载好的 3 个文件

文件名 用途 获得方式示例
python310.tar 离线 Python 3.10 镜像(或源码包) 公司镜像库、U 盘拷贝
SimHei.ttf 中文字体 gitee.com/x-itg/font/...
wheelhouse/ 所有 pip 依赖的离线 whl 文件 提前执行 pip download -d wheelhouse -r requirements.txt

把这 3 个文件连同项目源码放在同一个目录:

arduino 复制代码
data_tools/
├── Dockerfile
├── docker-compose.yml
├── python310.tar
├── fonts/
│   └── SimHei.ttf
├── wheelhouse/
├── requirements.txt
├── main.py
└── config.yaml

3️⃣ Dockerfile 拆解:逐行解释

完整文件都在上面对话里,这里用「白话」再讲一遍

css 复制代码
FROM python:3.10-slim
  • 用官方精简镜像当「地基」。如果你离线导入了同名镜像,Docker 会优先用本地版,不会联网。
sql 复制代码
RUN apt-get update && apt-get install -y wget fontconfig
  • wget 是为了下载字体,fontconfig 是让系统识别字体。
bash 复制代码
COPY fonts/SimHei.ttf /usr/share/fonts/truetype/custom/
RUN fc-cache -fv
  • 把字体文件直接拷进去,刷新缓存。离线场景下就把 wget 那句删掉即可。
sql 复制代码
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
  • 安装依赖。离线时把 pip install -r 换成
    pip install --no-index --find-links=./wheelhouse -r requirements.txt
css 复制代码
EXPOSE port1
ENTRYPOINT ["python", "main.py"]
  • 告诉 Docker「我监听 port1」,但真正暴露端口要在 docker-compose.yml 里做映射。

4️⃣ 构建镜像:离线也能玩 docker build

  1. 导入离线镜像(若有)
css 复制代码
docker load -i python310.tar

看到 Loaded image: python:3.10-slim 即可。

  1. 开始构建
erlang 复制代码
docker build -t data_tools .

-t 就是给镜像起名字 data_tools:latest


5️⃣ docker-compose.yml:端口、挂载、时区一次配齐

ruby 复制代码
version: "3.9"
services:
  data_tool:
    image: data_tools
    container_name: data_tools
    ports:
      - "port1:port1"           # 把容器 port1 映射到宿主机 port1
    extra_hosts:
      - "host.docker.internal:host-gateway"  # 容器访问宿主机 port2
    volumes:
      - /home/baker/apps/sz_data_tools/config.yaml:/app/config.yaml
      - /etc/localtime:/etc/localtime:ro     # 同步宿主机时间
    environment:
      - TZ=Asia/Shanghai
    restart: always

关键字段白话解释

字段 作用 小白记忆法
ports 让外网访问 宿主机IP:port1 宿主机端口在前,容器端口在后
extra_hosts host.docker.internal 指向宿主机 容器内写 127.0.0.1 会找自己,必须改域名
volumes 文件/目录映射 冒号左边是宿主机路径,右边是容器路径
ro 只读挂载 防止容器误删宿主机文件

6️⃣ 启动与验证:3 条命令让服务跑起来

  1. 一键启动

    docker-compose up -d

  2. 查看日志

    docker logs -f data_tools

  3. 浏览器或 Postman 测试

    • 访问 http://<宿主机IP>:port1
    • 容器内部访问宿主机 http://host.docker.internal:port2

7️⃣ 常见坑 & 解决方案

症状 原因 解决
字体乱码 没装/没刷新中文字体 确认 SimHei.ttf 已拷贝并执行 fc-cache -fv
容器连不上 port2 把 127.0.0.1 当成宿主机 把配置改成 host.docker.internal
时区差 8 小时 没挂载 /etc/localtime - /etc/localtime:/etc/localtime:ro
每次改代码都要全量构建 没利用缓存分层 COPY . . 放在 RUN pip install 后面

8️⃣ 进阶技巧:只更新单个容器

  • 只构建

    docker-compose build data_tool

  • 只重启

css 复制代码
docker-compose up -d --no-deps data_tool

--no-deps 确保不重启依赖它的其它服务。


9️⃣ 总结

离线部署 5 步走:

  1. 准备好「镜像/字体/whl」三件套
  2. 写 Dockerfile:装系统依赖 → 装 Python 依赖 → 拷代码
  3. 写 docker-compose.yml:端口、挂载、时区、extra_hosts 一条龙
  4. docker build + docker-compose up -d
  5. 出问题先看日志,再对照「常见坑」表

下次领导再提需求,你就能 10 分钟搞定!


如果本文帮到了你,点个赞再走吧!有任何疑问欢迎留言,一起把 Docker 变简单。

相关推荐
csxin9 分钟前
Spring Boot 中如何设置 serializer 的 TimeZone
java·后端
荔枝爱编程30 分钟前
如何在 Docker 容器中使用 Arthas 监控 Java 应用
java·后端·docker
高松燈34 分钟前
kafka入门和核心概念介绍
后端
喵手37 分钟前
Java中Stream与集合框架的差异:如何通过Stream提升效率!
java·后端·java ee
喵手1 小时前
你知道,如何使用Java的多线程机制优化高并发应用吗?
java·后端·java ee
青梅主码1 小时前
坐标差 1 公分,返工一整天?试试这个转换窍门
后端
cxyxiaokui0011 小时前
别让你的Java对象在内存里躺平!序列化带它看世界
后端·面试
白露与泡影1 小时前
SpringBoot前后端token自动续期方案
spring boot·后端·状态模式
青梅主码1 小时前
重磅!《人工智能和大型语言模型的研究前景:应用、挑战和未来方向》:代理型 AI 和大语言模型是否可以整合?
后端
hui函数2 小时前
Flask-WTF表单验证全攻略
后端·python·flask·web·表单验证