Docker 新手最容易踩的 5 个坑:从镜像膨胀到容器一重启数据就没了
第一次用 Docker 时,我最大的感受是爽:一条命令拉起 MySQL,再一条命令跑起应用,本地和服务器终于不用反复装环境了。可真正把容器用到日常开发和小项目部署后才发现,爽只是开头,重启一次容器、换一次机器,数据、时区、权限、日志这些问题会一个接一个冒出来。下面这 5 个坑,都是新手很容易踩、又完全可以提前避开的。
坑 1:镜像里塞太多东西,越打越大。很多人第一版 Dockerfile 是把完整操作系统、编译工具、源码、缓存全打进一个镜像,结果动不动 900MB,拉取慢、部署慢、漏洞扫描还一堆。正确做法是三件事:第一,选小基础镜像,能用 slim 就不用完整版,工具类可用 alpine;第二,加 .dockerignore,把 .git、依赖缓存、日志、本地文件排除在构建上下文之外;第三,用多阶段构建,构建阶段负责编译,最终阶段只复制运行产物和运行依赖。我把一个小服务按这三步改完后,镜像从约 900MB 降到了 180MB 左右,思路就是:构建时需要的东西,不要带到运行时。比如构建阶段用完整镜像编译,运行阶段用 python:3.12-slim 或 node:20-alpine,只拷贝产物,体积立刻下来。
坑 2:数据不挂卷,容器一删数据就没了。容器自己的可写层不是用来存数据的。执行 docker rm、重新拉镜像、换一台机器,容器层没了,数据库文件和用户上传的文件也就跟着没了。所以只要是需要保留的数据,都要挂卷:数据库、上传目录用 named volume,例如 -v app-data:/var/lib/mysql;本地调试需要直接改文件时才用 bind mount 把宿主机目录挂进去。还要记得备份,卷不是备份,可以用一条 tar 命令把卷内容打包到当前目录,定期执行,重要数据再同步到别处。
坑 3:全程用 root 跑应用。默认 root 跑应用最省事,出问题也最直接:应用一旦被攻破,拿到的就是容器里的最高权限;挂载目录的文件属主还会被改成 root,宿主机上清理都麻烦。做法是在 Dockerfile 里新建普通用户并用 USER 指令降权,只给应用真正需要写的目录开权限;能只读就把文件系统设为只读,临时目录单独挂载。权限给最小,麻烦留给自己,别留给攻击者。
坑 4:不设资源和日志上限,一个容器吃满整台机器。新手常忽略两件事:内存不设上限,一个内存泄漏就能把宿主机拖死;日志不做轮转,容器日志能悄悄涨到几十 GB,把磁盘写满后所有服务一起出问题。启动时就加上限制,例如 --memory=512m,并给日志配置 max-size 和 max-file 做轮转。开发环境图省事不限,到了小服务器上,这个坑几乎一定会还回来。
坑 5:没写 healthcheck,也没配重启策略。容器进程还在,不等于服务是好的。接口已经卡死、数据库连接断了,容器状态照样显示 running。这时要配合两件事:用 HEALTHCHECK 或 compose 里的 healthcheck 定期探活一个轻量健康接口;再配 restart: unless-stopped 这类重启策略,让进程意外退出时能自动拉起。注意重启策略不是万能药,配置错误导致的崩溃会被反复重启,所以日志和告警也要跟上。
结尾小清单:发布前对一遍,镜像是否用了小基础镜像和多阶段构建?数据是否都挂了卷并有备份?应用是否已降权运行?内存和日志是否设了上限?健康检查和重启策略是否都配了?最后留一个最小 compose 模板供参考:服务里写 build、volumes 挂命名卷、restart 设 unless-stopped、mem_limit 设上限、healthcheck 探活 /health 接口,volumes 段声明命名卷。把这五件事做在前面,比容器半夜挂掉再爬起来查,省心得多。
- 点赞
- 收藏
- 关注作者
评论(0)