Docker 容器老是挂?香港服务器自动重启策略这样配更稳

很多网站、API、后台系统、采集程序、消息队列和轻量业务,现在都会部署在 Docker 容器里。Docker 的好处很明显:环境统一、迁移方便、部署速度快。但在真实生产环境中,容器并不是“启动一次就永远稳定”。程序异常退出、内存占用过高、依赖服务中断、磁盘写满、配置错误,都可能导致容器突然挂掉。
对于部署在香港服务器上的业务来说,这类问题更容易被用户感知。因为香港节点通常面向大陆、东南亚、海外用户访问,一旦容器停止,前台网站、接口服务或管理后台可能立刻出现 502、连接超时、接口无响应等问题。
本文以 A5IDC 一款常见香港业务服务器作为案例:E-2334 处理器、32GB 内存、960GB NVMe SSD、25M CN2 优化带宽 + 100M BGP 网络。这个配置比较适合中小型官网、跨境业务后台、API 服务、轻量 SaaS、Docker 多容器部署等场景。下面我们就围绕这类香港服务器环境,讲清楚 Docker 容器挂掉后如何配置自动重启策略,以及哪些细节不能只依赖“restart: always”一行解决。
一、Docker 容器为什么会挂掉?
在香港服务器上跑 Docker,容器挂掉通常不是线路问题,而是容器内部或宿主机资源层面的问题。常见原因包括:
应用进程异常退出,比如 PHP、Node.js、Java、Go 服务发生未捕获错误,主进程直接退出。
容器内存超限,比如程序短时间占用大量内存,被系统 OOM 机制杀掉。
依赖服务不可用,比如 Web 容器依赖 MySQL、Redis、MQ,后者没有启动成功,导致主服务启动失败。
端口冲突或配置错误,比如容器启动时发现 80、443、3306 等端口已被占用。
磁盘空间写满,比如日志、缓存、上传文件不断增长,导致容器无法正常写入。
镜像或环境变量更新后出错,比如升级程序后缺少参数、目录权限不正确、数据库连接配置错误。
所以,Docker 自动重启策略不是用来“掩盖问题”的,而是用来降低偶发故障带来的业务中断时间。真正稳定的方案,应该是“自动拉起 + 日志排查 + 资源限制 + 健康检查”组合使用。
二、Docker 自带的四种重启策略
Docker 原生支持 restart 策略,常见有四种:
no:默认策略,容器退出后不自动重启。
on-failure:只有容器异常退出时才自动重启,可以限制重启次数。
always:只要容器停止,Docker 就会尽量自动重启。
unless-stopped:除非人为停止,否则容器会自动重启,服务器重启后也会自动拉起。
对于香港服务器上的网站、API、后台服务,比较推荐使用 unless-stopped。它比 always 更适合日常运维,因为如果你手动停掉某个容器进行维护,它不会在 Docker 服务重启后又被强行拉起来。
三、单容器启动时如何配置自动重启?
如果你是直接用 docker run 启动容器,可以这样写:
docker run -d \
--name a5idc-web \
--restart unless-stopped \
-p 80:80 \
-p 443:443 \
nginx:latest
这里最关键的是:
--restart unless-stopped
它表示:只要不是管理员主动停止容器,容器异常退出后会自动重启。比如 Nginx 进程异常退出、服务器重启、Docker 服务重启,容器都会被重新拉起。
如果是任务型容器,比如一次性脚本、数据处理任务,不建议用 always 或 unless-stopped,否则任务执行完退出后又会被反复重启。此类容器可以使用:
--restart on-failure:3
意思是容器异常失败时最多重启 3 次,避免无限循环。
四、Docker Compose 中的推荐写法
生产环境中,更多用户会使用 Docker Compose 管理多个容器。例如一个香港服务器上同时运行 Nginx、PHP、MySQL、Redis,可以这样配置:
services:
web:
image: nginx:latest
container_name: a5idc-web
restart: unless-stopped
ports:
- "80:80"
- "443:443"
depends_on:
- php
php:
image: php:8.2-fpm
container_name: a5idc-php
restart: unless-stopped
volumes:
- ./www:/var/www/html
redis:
image: redis:7
container_name: a5idc-redis
restart: unless-stopped
mysql:
image: mysql:8.0
container_name: a5idc-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: your_password
volumes:
- ./mysql:/var/lib/mysql
这个配置适合官网、业务后台、API 服务等常见场景。以前面提到的 E-2334 / 32GB / 960GB NVMe 香港服务器为例,32GB 内存可以比较从容地承载 Web、数据库、缓存、队列等多个轻量容器,NVMe 硬盘也能减少数据库和日志写入时的 I/O 压力。
不过需要注意,depends_on 只代表启动顺序,不代表依赖服务已经完全可用。比如 MySQL 容器启动了,但数据库还没初始化完成,PHP 应用仍然可能连接失败。因此,核心业务还需要配合健康检查或应用层重试机制。
五、容器挂掉后如何快速判断原因?
配置自动重启后,不代表问题已经解决。你还需要知道容器为什么挂掉,否则同一个错误可能反复发生。
查看容器状态:
docker ps -a
如果看到容器状态反复变成 Restarting,说明它可能启动后马上崩溃。
查看容器退出原因:
docker inspect a5idc-web --format='{{.State.ExitCode}}'
查看是否被 OOM 杀掉:
docker inspect a5idc-web --format='{{.State.OOMKilled}}'
如果返回 true,说明容器大概率是内存占用过高,被系统杀掉了。
查看日志:
docker logs --tail=100 a5idc-web
持续追踪日志:
docker logs -f a5idc-web
对于香港服务器上的线上业务来说,建议不要只看“容器是否启动”,还要关注“容器是否正常提供服务”。有些容器虽然状态是 Up,但应用内部已经报错,外部访问仍然可能 502。
六、健康检查不能等同于自动重启
很多人会误以为 Docker 配置了 healthcheck 后,容器不健康就会自动重启。实际上,在普通 Docker 或 Docker Compose 场景中,healthcheck 主要用于标记容器健康状态,并不会默认自动重启 unhealthy 容器。
例如:
services:
web:
image: nginx:latest
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/"]
interval: 30s
timeout: 5s
retries: 3
这个配置可以让 Docker 判断容器是否健康,但如果容器进程还活着,只是服务不可访问,Docker 不一定会自动重启它。
如果你希望容器不健康时自动处理,可以考虑三种方式:
第一,在应用内部做好异常退出机制。当核心依赖不可用或服务异常时,让主进程明确退出,由 Docker restart 策略重新拉起。
第二,使用外部监控脚本定期检查 unhealthy 状态,并执行重启。
第三,业务规模较大时,使用更完整的编排方案,比如 Docker Swarm、Kubernetes 或专业监控告警系统。
对于中小型香港服务器业务,第二种方式比较实用。
示例脚本:
#!/bin/bash
container_name="a5idc-web"
status=$(docker inspect --format='{{.State.Health.Status}}' $container_name 2>/dev/null)
if [ "$status" = "unhealthy" ]; then
echo "$(date) $container_name is unhealthy, restarting..." >> /var/log/docker-watchdog.log
docker restart $container_name
fi
然后用 crontab 每分钟执行一次:
* * * * * /bin/bash /root/docker-watchdog.sh
这种方式不复杂,但能解决“容器没退出、服务却不可用”的问题。
七、自动重启策略也要配合资源限制
如果容器是因为内存爆掉而退出,只配置自动重启会变成“挂掉、重启、再挂掉”的循环。更合理的方式是给容器设置资源边界。
例如:
docker run -d \
--name a5idc-api \
--restart unless-stopped \
--memory=2g \
--memory-swap=2g \
-p 8080:8080 \
your-api-image
Docker Compose 写法:
services:
api:
image: your-api-image
restart: unless-stopped
mem_limit: 2g
这样做的意义是避免单个容器拖垮整台服务器。尤其是在同一台香港服务器上同时运行 Web、数据库、缓存、队列时,资源隔离非常重要。
以前面的 32GB 内存配置为例,可以根据业务类型大致规划:
Web / Nginx:512MB 到 1GB
PHP / Node.js / Java API:1GB 到 4GB
Redis:512MB 到 2GB
MySQL:4GB 到 12GB,视数据库规模调整
日志与监控容器:512MB 到 1GB
不要把所有内存都分配给容器,宿主机系统、Docker daemon、磁盘缓存也需要保留空间。
八、服务器重启后,Docker 自身也要能自动启动
有些用户配置了容器 restart 策略,但服务器重启后容器没有起来,原因可能是 Docker 服务本身没有设置开机启动。
检查 Docker 状态:
systemctl status docker
设置 Docker 开机自启:
systemctl enable docker
systemctl start docker
如果 Docker 服务没有运行,容器的 restart 策略自然也不会生效。因此完整链路应该是:
服务器开机 → Docker 服务启动 → 容器根据 restart 策略自动拉起 → 应用服务恢复访问。
九、香港服务器部署 Docker 的实用建议
如果你的业务主要面向大陆、东南亚或海外用户,香港服务器的网络质量和系统稳定性都很关键。Docker 自动重启只是其中一环,建议同时做好以下几点:
不要把数据库、缓存、应用日志全部放在容器临时层,重要数据必须挂载到宿主机目录或独立数据盘。
定期清理无用镜像、旧容器和日志,避免磁盘写满:
docker system df
docker image prune
容器日志建议限制大小,例如:
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "3"
关键业务不要只依赖单容器,至少要配合反向代理、健康检查、监控告警。
应用程序自身要有重试机制,比如数据库连接失败时等待重试,而不是直接崩溃。
定期检查:
docker ps
docker stats
df -h
free -m
这些命令虽然基础,但能提前发现大量隐患。
十、推荐的生产环境策略
如果是官网、API、业务后台这类长期运行服务,推荐:
restart: unless-stopped
如果是脚本任务、一次性任务、定时处理任务,推荐:
restart: on-failure:3
如果是数据库、缓存、队列服务,也可以使用:
restart: unless-stopped
但一定要配合数据持久化和备份。
如果容器经常自动重启,不要只觉得“反正服务会恢复”。这通常说明应用、资源、配置或依赖存在问题。自动重启策略的价值,是把偶发故障的影响降到最低,而不是替代真正的故障排查。
总结
香港服务器上部署 Docker 容器,自动重启策略是生产环境中非常基础但很重要的一步。对于网站、API、后台、缓存、数据库等长期运行服务,unless-stopped 通常是更稳妥的选择;对于任务型容器,on-failure 更合适。
但容器自动重启并不是万能方案。真正稳定的 Docker 部署,应该同时包含 restart 策略、健康检查、日志分析、资源限制、数据持久化、Docker 开机自启和监控告警。
以 A5IDC 香港 E-2334 / 32GB / 960GB NVMe / CN2 + BGP 网络服务器为例,这类配置足够支撑中小型业务的多容器部署。只要在系统层面做好资源规划,在 Docker 层面做好自动恢复,在应用层面做好异常处理,就能让香港服务器上的容器服务在面对偶发异常时更快恢复,减少业务中断时间,也让后续运维排查更有方向。