写在前面:为什么要读这篇博文?
你可能遇到过这些场景:
- 公司内网不通 Docker Hub,拉不到镜像;
- 项目要跑在 port1 端口,同时还得访问宿主机 port2 的服务;
- 字体、时区、依赖统统要离线搞定;
- 领导一句「用 Docker 部署」,你却连 Dockerfile 都没写过。
别怕!本文用一个真实项目「data_tools」做主线,手把手带你走完「本地打包 → 离线镜像 → 端口映射 → 数据持久 → 一键启动」全流程。读完你就能独立把自己的 Python 项目装进容器并上线运行。
目录
- 思路总览:一张图看懂整个流程
- 环境准备:你需要提前下载好的 3 个文件
- Dockerfile 拆解:逐行解释,小白也能改
- 构建镜像:离线也能玩
docker build
- docker-compose.yml:端口、挂载、时区一次配齐
- 启动与验证:3 条命令让服务跑起来
- 常见坑 & 解决方案:字体 404、端口不通、时区不对
- 进阶技巧:如何只更新单个容器而不动其它服务
- 总结 & 思维导图
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
- 导入离线镜像(若有)
css
docker load -i python310.tar
看到 Loaded image: python:3.10-slim
即可。
- 开始构建
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 条命令让服务跑起来
-
一键启动
docker-compose up -d
-
查看日志
docker logs -f data_tools
-
浏览器或 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 步走:
- 准备好「镜像/字体/whl」三件套
- 写 Dockerfile:装系统依赖 → 装 Python 依赖 → 拷代码
- 写 docker-compose.yml:端口、挂载、时区、extra_hosts 一条龙
docker build
+docker-compose up -d
- 出问题先看日志,再对照「常见坑」表
下次领导再提需求,你就能 10 分钟搞定!
如果本文帮到了你,点个赞再走吧!有任何疑问欢迎留言,一起把 Docker 变简单。