You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Systemd管理Docker容器服务执行stop后进入failed状态求助

问题:Docker容器Systemd服务停止时触发失败状态

我有一个用于启停自研代理服务器的Systemd服务文件,内容如下:

[Unit]
Description=Golang proxy server in Docker
After=network.target docker.service
Requires=docker.service

[Service]
Type=simple
WorkingDirectory=/home/ooolledj/socks5-proxy
ExecStart=/usr/bin/docker container rm goproxy --force ; /usr/bin/docker run --name goproxy -p 12345:12345 goproxy:local
ExecStop=/usr/bin/docker container stop -t 1 goproxy
Restart=on-failure
TimeoutStartSec=10

[Install]
WantedBy=multi-user.target

服务启动运行正常,但执行systemctl stop goproxy命令时,容器虽已成功停止,服务却进入"failed"状态。重启服务可恢复正常运行,推测原因是容器进程PID终止后,systemd将其判定为异常退出,报错信息为goproxy.service: Main process exited, code=exited, status=2/INVALIDARGUMENT,对应的状态信息如下:

root@my-test-host:/home/ooolledj/socks5-proxy# systemctl status goproxy
● goproxy.service - Golang proxy server in Docker
     Loaded: loaded (/etc/systemd/system/goproxy.service; disabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Thu 2023-08-17 18:05:09 MSK; 881ms ago
    Process: 49618 ExecStartPre=/usr/bin/docker container rm goproxy --force (code=exited, status=0/SUCCESS)
    Process: 49624 ExecStart=/usr/bin/docker run --name goproxy -p 12345:12345 goproxy:local (code=exited, status=2)
    Process: 49717 ExecStop=/usr/bin/docker container stop -t 3 goproxy (code=exited, status=0/SUCCESS)
   Main PID: 49624 (code=exited, status=2)
        CPU: 135ms

Aug 17 18:04:58 my-test-host systemd[1]: Starting Golang proxy server in Docker: https://github.com/OOOlledj/socks5-proxy...
Aug 17 18:04:58 my-test-host docker[49618]: goproxy
Aug 17 18:04:58 my-test-host systemd[1]: Started Golang proxy server in Docker: https://github.com/OOOlledj/socks5-proxy.
Aug 17 18:05:09 my-test-host systemd[1]: Stopping Golang proxy server in Docker: https://github.com/OOOlledj/socks5-proxy...
Aug 17 18:05:09 my-test-host docker[49717]: goproxy
Aug 17 18:05:09 my-test-host systemd[1]: goproxy.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
Aug 17 18:05:09 my-test-host systemd[1]: goproxy.service: Failed with result 'exit-code'.
Aug 17 18:05:09 my-test-host systemd[1]: Stopped Golang proxy server in Docker: https://github.com/OOOlledj/socks5-proxy.

希望服务停止时能进入"exited"正常状态而非"failed",以下是可行解决方案:


解决方案

方案1:标记退出码2为正常状态(推荐)

当执行systemctl stop时,docker run进程会因容器被外部终止返回退出码2,systemd默认将非0退出码视为失败。在服务文件的[Service]段添加配置,告诉systemd该退出码属于正常情况:

SuccessExitStatus=2

同时将原ExecStart中的容器删除命令移到ExecStartPre,更符合systemd启动流程,修改后的完整服务文件:

[Unit]
Description=Golang proxy server in Docker
After=network.target docker.service
Requires=docker.service

[Service]
Type=simple
WorkingDirectory=/home/ooolledj/socks5-proxy
ExecStartPre=/usr/bin/docker container rm goproxy --force
ExecStart=/usr/bin/docker run --name goproxy -p 12345:12345 goproxy:local
ExecStop=/usr/bin/docker container stop -t 1 goproxy
Restart=on-failure
TimeoutStartSec=10
SuccessExitStatus=2

[Install]
WantedBy=multi-user.target

方案2:改用后台运行模式跟踪容器状态

如果希望容器后台运行,可修改ExecStart使用docker run -d,并通过docker wait跟踪容器生命周期,同时将服务类型改为Type=forking:

[Unit]
Description=Golang proxy server in Docker
After=network.target docker.service
Requires=docker.service

[Service]
Type=forking
WorkingDirectory=/home/ooolledj/socks5-proxy
ExecStartPre=/usr/bin/docker container rm goproxy --force
ExecStart=/usr/bin/docker run -d --name goproxy -p 12345:12345 goproxy:local && /usr/bin/docker wait goproxy
ExecStop=/usr/bin/docker container stop -t 1 goproxy
Restart=on-failure
TimeoutStartSec=10

[Install]
WantedBy=multi-user.target

docker wait会阻塞到容器停止,返回容器的退出码,确保systemd正确识别容器的终止状态。

方案3:使用一次性服务模式

若服务仅负责启动容器,无需持续运行主进程,可改用Type=oneshot并开启RemainAfterExit=true,让服务在启动后保持active状态,直到手动停止:

[Unit]
Description=Golang proxy server in Docker
After=network.target docker.service
Requires=docker.service

[Service]
Type=oneshot
WorkingDirectory=/home/ooolledj/socks5-proxy
ExecStartPre=/usr/bin/docker container rm goproxy --force
ExecStart=/usr/bin/docker run -d --name goproxy -p 12345:12345 goproxy:local
ExecStop=/usr/bin/docker container stop -t 1 goproxy && /usr/bin/docker container rm goproxy --force
Restart=on-failure
TimeoutStartSec=10
RemainAfterExit=true

[Install]
WantedBy=multi-user.target

内容的提问来源于stack exchange,提问作者ooolledj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:08:12