容器启动即退出的根本原因是PID 1进程结束,因其生命周期与容器完全绑定;常见场景包括Nginx默认后台运行、CMD执行短命命令、启动脚本未阻塞等。
容器启动就退出:别让 CMD 成为“秒退开关”
敲完 docker run nginx,容器一闪而过,docker ps 看不到它——这不是命令错了,而是没理解容器生命周期的本质。容器不是“运行一个服务”,而是“运行一个前台进程”。一旦这个进程结束,容器立刻退出。
常见诱因包括:
- Nginx 默认以 daemon 模式运行(后台),导致主进程 fork 后父进程退出,容器随之终止;正确做法是加 -g "daemon off;" 强制前台运行
- 镜像中 CMD 是 sh -c "sleep 10" 这类短命命令,执行完即退出
- 应用启动脚本缺少 exec "$@" 或未阻塞,进程提前收尾
验证方式:用 docker logs
run 和 start 混用:名字冲突不是报错,是逻辑警告
docker run --name my-app nginx 报 Conflict. The container name "/my-app" is already in use,说明你正试图重复创建同名容器——哪怕旧容器处于 Exited 状态。
记住两个动作的边界:
- docker run = 创建 + 启动新容器(命名、网络、卷等资源重新分配)
- docker start = 复用已有容器配置,仅恢复其运行状态
若需修改启动参数(如新端口映射),不能靠 start,必须先 docker rm my-app(注意加 -f 强制删除运行中容器),再用新参数 run。
端口与权限陷阱:映射失效和拒绝访问常被误判
浏览器打不开 localhost:8080,别急着重装 Docker。先分三步排查:
- 确认宿主机端口未被占用:netstat -tuln | grep :8080 或 lsof -i :8080
- 检查容器内服务是否真在监听 0.0.0.0:8080(而非 127.0.0.1:8080),可用 docker exec -it
ss -tln 验证 - 非 root 用户无法绑定 1–1023 端口,若用 USER 指令降权,务必改用高位端口(如 8080)并确保应用配置同步更新
环境与数据风险:硬编码和无持久化=生产定时炸弹
以下写法在开发阶段看似省事,上线就是事故:
- Dockerfile 中写死 RUN echo "password=123456" > /app/.env —— 密码随镜像分发,不可撤销
- 直接 -v ./config:/app/config 绑定本地目录,却忽略 Windows/macOS 与 Linux 路径差异及文件权限(如容器内 UID 1001 写不了宿主机 UID 501 的目录)
- 运行数据库容器不挂载卷,重启后所有数据清零
安全替代方案:
- 敏感配置统一通过 .env 文件 + docker-compose.yml 的 env_file: 或 environment: 注入
- 优先使用命名卷(docker volume create db-data),再 -v db-data:/var/lib/postgresql/data
- 确需绑定目录时,显式指定用户 UID:-v $(pwd)/data:/data:Z(Linux SELinux)或 --user 1001:1001











