- 约1151字
- 技术
- 2026年3月23日
每次帮团队新人解决 Docker 问题,我都会想起自己刚入门时的狼狈——镜像拉了几个小时下不来,容器启动后连不上网络,修改代码后重新构建要等半天。今天把这5年踩过的坑整理出来,希望你不再重蹈覆辙。
坑一:镜像体积失控
新人最容易犯的错误就是“镜像叠叠乐”。我见过最夸张的一个项目,最终镜像居然有 12GB——光 Python 环境就占了 8GB。
为什么会这样? 多半是把本地开发环境整个搬进去了。node_modules、venv、.git,全部打包进镜像。
怎么解决? 记住一个原则:只放运行时必须的东西。
# ❌ 错误示范:把整个项目目录都搬进去
COPY . /app
RUN pip install -r requirements.txt
# ✅ 正确做法:先复制依赖文件,安装完再复制代码
COPY requirements.txt /app/
RUN pip install -r requirements.txt
COPY . /app
另一个有效手段是用多阶段构建,把编译环境和运行环境分开。最终镜像只保留编译后的二进制文件,体积能减少 70% 以上。
坑二:构建卡死在 RUN install
你有没有遇到过这种情况:Dockerfile 里的 RUN pip install 跑了半小时还没完事,心里默念“是不是卡住了”。
真相是:它确实很慢。 每次构建都要重新下载依赖,没有任何缓存。
优化思路:
- 把依赖文件放在 Dockerfile 前半部分,这样改代码不影响依赖层缓存
- 使用国内镜像源
- 对于超大型依赖,考虑预构建基础镜像
# 使用国内镜像源加速
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
坑三:容器内网络不通
容器启动成功了,Application Error!日志一开,发现是 Connection refused。十有八九是网络配置问题。
常见原因:
容器想访问宿主机服务,用了
localhost:port——容器里的 localhost 指容器自己,不是宿主机需要用
host.docker.internal(Docker Desktop)或宿主机实际 IP端口映射了但协议不对,比如服务是 TCP 你映射成了 UDP
一个排查口诀: 先看端口映射 docker ps -a,再看日志 docker logs <container>,最后用 docker exec 进容器测试连通性。
# 在容器内测试宿主机连通性
docker exec -it <container> ping host.docker.internal
坑四:数据随着容器一起“死”
新手常犯的另一个错误是把数据存在容器里。容器一删,数据全丢,欲哭无泪。
根本原因: 容器的文件系统是分层的,容器删除后,底层数据可能无法恢复。
正确做法:用卷(Volume)
# docker-compose.yml 示例
services:
mysql:
image: mysql:8
volumes:
- mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
volumes:
mysql_data:
这样做的好处是数据独立于容器生命周期,容器重启或删除,数据还在。
坑五:忽视安全配置
很多人觉得“反正是内部项目,用不着安全配置”。结果某天镜像被扫描出漏洞,傻眼了。
最基本的几项:
不要用 root 用户运行容器
RUN addgroup -g 1000 appgroup && adduser -u 1000 -G appgroup -s /bin/sh -D appuser USER appuser只读文件系统可以防止恶意修改
read_only: true定期更新基础镜像,别用三年前的 Python 3.7
说了这么多,其实 Docker 上手并不难。难的是避开这些坑,建立正确的使用习惯。我的建议是:先跑通最小流程,再逐步加入优化。镜像大了就分层构建,网络不通就先看端口,数据重要就加卷——别想着一口吃成胖子。
你踩过最大的 Docker 坑是什么?评论区说说,下次我来写解决方案。