Docker 容器化实战踩坑:我被这些细节坑了3次后终于搞懂了

📅 发布时间:2026/7/7 21:18:05 👁️ 浏览次数:
Docker 容器化实战踩坑:我被这些细节坑了3次后终于搞懂了
Docker 容器化实战踩坑我被这些细节坑了3次后终于搞懂了说实话我一开始是拒绝用 Docker 的。直到上次部署生产环境三台服务器环境不一致导致服务集体翻车我才终于下决心把项目容器化。折腾了一个星期踩了无数坑今天把这些血泪教训分享出来希望能帮到你们。坑一Dockerfile 构建失败依赖包安装超时问题描述第一次写 Dockerfile运行docker build时卡在pip install步骤整整等了 20 分钟然后报错退出。原因分析国内服务器访问 PyPI 官方源太慢timeout 设置又太短导致安装依赖直接失败。解决方案配置国内镜像源同时增加 timeout 时间# 写法一设置 pip 镜像源 RUN pip install --no-cache-dir -r requirements.txt \ -i https://pypi.tuna.tsinghua.edu.cn/simple # 写法二全局配置 pip 镜像 RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple \ pip install --no-cache-dir -r requirements.txt注意事项--no-cache-dir必须加否则镜像层会很大建议在 requirements.txt 同目录下新建 pip.conf 文件[global] index-url https://pypi.tuna.tsinghua.edu.cn/simple timeout 120然后 COPY 到镜像中复用坑二容器启动成功但立即退出exit code 0问题描述docker run后容器立刻退出日志显示程序正常执行完毕。原因分析Docker 容器的主进程退出后容器会自动停止。如果你启动的是 Python 脚本或定时任务执行完就退出了。解决方案方案一使用 tail -f 或 sleep 保持容器运行# 适用于需要后台运行的服务的镜像 CMD [python, app.py] # 替换为 CMD [tail, -f, /dev/null] # 或者 CMD [python, app.py] sleep infinity方案二使用 supervisor 管理多进程# 安装 supervisor RUN apt-get update apt-get install -y supervisor # 配置 supervisor.conf RUN mkdir -p /var/log/supervisor COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf # 启动命令 CMD [/usr/bin/supervisord, -n, -c, /etc/supervisor/conf.d/supervisord.conf]supervisord.conf 示例[supervisord] nodaemontrue [program:app] commandpython app.py stdout_logfile/var/log/supervisor/app.log stderr_logfile/var/log/supervisor/app.err autostarttrue autorestarttrue坑三容器内无法访问宿主机数据库问题描述Spring Boot 容器连接localhost:3306报连接失败但宿主机数据库明明在运行。原因分析Docker 有自己的网络 namespace容器内的 localhost 指向容器自己不是宿主机。解决方案方案一使用 host.docker.internal推荐开发环境# docker-compose.ymlservices:app:build:.extra_hosts:-host.docker.internal:host-gatewayenvironment:-SPRING_DATASOURCE_URLjdbc:mysql://host.docker.internal:3306/mydb方案二使用宿主机网络模式dockerrun--networkhostmyapp方案三使用 docker-compose 的服务名生产推荐services:app:build:.depends_on:-mysqlenvironment:-SPRING_DATASOURCE_URLjdbc:mysql://mysql:3306/mydbmysql:image:mysql:8.0environment:MYSQL_ROOT_PASSWORD:root123坑四数据卷挂载后文件找不到问题描述使用-v /host/path:/container/path挂载目录后容器内目录是空的或者报错 “permission denied”。原因分析两个原因宿主机目录不存在Docker 会自动创建但创建的是空目录容器内用户没有权限写入宿主机目录尤其是 root 拥有的目录解决方案方案一创建并授权宿主机目录# 创建目录mkdir-p/data/app# 修改所有者sudochown-R$(id-u):$(id-g# 运行容器)/data/appdockerrun-v/data/app:/app/data myapp方案二Dockerfile 中创建非 root 用户# 创建用户并授权 RUN groupadd -r appuser useradd -r -g appuser appuser RUN mkdir -p /app/data chown -R appuser:appuser /app # 切换用户 USER appuser # 容器启动命令 CMD [python, app.py]方案三使用 named volume推荐# docker-compose.ymlservices:app:build:.volumes:-app_data:/app/datavolumes:app_data:坑五容器内存无限膨胀最终 OOM问题描述运行几小时后容器内存持续增长最终被 OOM Killer 杀死。原因分析容器没有设置内存限制Java/Python 等语言会不断申请内存宿主机有多少它就吃多少。解决方案方案一设置内存限制dockerrun-m512m myapp# 或dockerrun--memory512m --memory-swap1g myapp方案二docker-compose 中配置services:app:build:.mem_limit:512mmem_reservation:256menvironment:-JAVA_OPTS-Xmx256m-Xms256m方案三Java 应用必须设置 JVM 堆内存ENV JAVA_OPTS-Xms256m -Xmx512m -XX:UseG1GC CMD [sh, -c, java $JAVA_OPTS -jar app.jar]对于 Spring Boot 项目可以直接使用内置的JAVA_OPTS# docker-compose.ymlservices:app:build:.environment:-JAVA_TOOL_OPTIONS-Xms256m-Xmx512m写在最后折腾了 Docker 这一周虽然踩坑无数但确实香。现在项目的部署从手动操作变成了docker-compose up -d五分钟搞定所有服务。给新手几点建议先在本地用 docker-compose 模拟完整环境别直接上生产镜像尽量做小能用 alpine 就用 alpine敏感信息用环境变量或 secrets别写死在 Dockerfile一定要设置内存和 CPU 限制别让容器放飞自我Docker 的坑还有很多比如网络策略、镜像安全扫描、滚动更新等等后面再慢慢聊。有问题欢迎评论区交流。