stop docker.service之后容器还能正常提供服务吗?

本文探讨了Docker容器在`live-restore`参数启用时,即使停止或重启docker服务,如何保持服务不间断。通过实例和配置,解释了如何利用这项特性来确保容器内的服务在操作中仍能继续运行。

探讨话题

执行以下命令后,运行的docker容器还能正常提供服务吗?或者换种说法,容器内对应的服务进程还存在吗?
~]# systemctl stop docker.service

此问题是我一个同事抛出来的,当时我没经过太多思考,也直接进行了回答:“不能说停掉,是你本身就没docker守护进程了,有多少个容器你也看不到了,再往后推理,容器也提供不了对应的服务。”,当时我是这样回答的,接着我又抛出了这个话题,在深圳的一位朋友(高级云原生工程师:包包),他回复默认是所有docker容器都会受影响的,但是记得好像有一种是不受影响的,最后也找到了Docker官方提供的链接 https://docs.docker.com/config/containers/live-restore/

最后的仰慕

实战剖析

1、不配参数
docker配置文件概览
[root@VM-0-30-centos ~]# cat /etc/docker/daemon.json 
{
  "graph": "/data/ti-platform/docker",
  "storage-driver": "overlay2",
  "insecure-registries": ["registry.access.redhat.com","quay.io"],
  "registry-mirrors": ["https://q2gr04ke.mirror.aliyuncs.com"],
  "bip": "172.0.30.1/24",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver":"json-file",
  "log-opts": {
	"max-size": "256M", 
	"max-file": "3"
	}
}

查看当前运行的容器
在这里插入图片描述
查看docker.service状态
在这里插入图片描述
执行重启docker动作,发现所有容器状态已经变为Exited,这时会引来一个问题,假如我们刚好需要重启docker,不可能一重启其他容器就都退出了,还要手动进行启动,这个就成了一个很反感的问题,也会使服务异常。
在这里插入图片描述
于是查看Docker官方https://docs.docker.com/config/containers/live-restore/ 有提供参数,无论是停止docker、还是重启,都不会影响我容器里边的服务,也就是服务不会产生中断,接下来看操作演示。

2、带参数
docker配置文件概览
[root@VM-0-30-centos ~]# cat /etc/docker/daemon.json 
{
  "graph": "/data/ti-platform/docker",
  "storage-driver": "overlay2",
  "insecure-registries": ["registry.access.redhat.com","quay.io"],
  "registry-mirrors": ["https://q2gr04ke.mirror.aliyuncs.com"],
  "bip": "172.0.30.1/24",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver":"json-file",
  "log-opts": {
	"max-size": "256M", 
	"max-file": "3"
	},
  "live-restore": true	#官方提供的特殊参数
}

重启生效
[root@VM-0-30-centos ~]# systemctl daemon-reload 
[root@VM-0-30-centos ~]# systemctl restart docker

在这里插入图片描述
验证stop docker.service,可以看出docker服务已处于不可运行状态
在这里插入图片描述
通过公网IP访问Nginx服务,结论:访问正常
在这里插入图片描述
检查本地docker进程也是不存在的,符合预期。
在这里插入图片描述
接下来分析一下背后实现的逻辑

首先,停止docker服务后还能继续提供服务,它背后的逻辑是在停止前会拍摄类似于一个快照的东西,并且它当前快照是处于激活状态的, 其实更专业一点应该叫瞬态存根。可以看出以下有.scope结尾的文件,其实它就是以服务的角色存在。
在这里插入图片描述
查看这个服务的状态,那么是处于active状态,并且也可以看出是nginx容器的
在这里插入图片描述
其他会自动保存一个文件,也就是本文前边所提到的瞬态存根
在这里插入图片描述
在这里插入图片描述

研究了一下 如果你运行有多个容器,停掉之后它就会有对应多个瞬态存根,而且都是激活状态,所以停止docker.service后,服务是不会受影响的,还是可以保持不中断的状态。

附官方配置

/etc/docker/daemon.json

{
  "allow-nondistributable-artifacts": [],
  "api-cors-header": "",
  "authorization-plugins": [],
  "bip": "",
  "bridge": "",
  "cgroup-parent": "",
  "cluster-advertise": "",
  "cluster-store": "",
  "cluster-store-opts": {},
  "containerd": "/run/containerd/containerd.sock",
  "containerd-namespace": "docker",
  "containerd-plugin-namespace": "docker-plugins",
  "data-root": "",
  "debug": true,
  "default-address-pools": [
    {
      "base": "172.30.0.0/16",
      "size": 24
    },
    {
      "base": "172.31.0.0/16",
      "size": 24
    }
  ],
  "default-cgroupns-mode": "private",
  "default-gateway": "",
  "default-gateway-v6": "",
  "default-runtime": "runc",
  "default-shm-size": "64M",
  "default-ulimits": {
    "nofile": {
      "Hard": 64000,
      "Name": "nofile",
      "Soft": 64000
    }
  },
  "dns": [],
  "dns-opts": [],
  "dns-search": [],
  "exec-opts": [],
  "exec-root": "",
  "experimental": false,
  "features": {},
  "fixed-cidr": "",
  "fixed-cidr-v6": "",
  "group": "",
  "hosts": [],
  "icc": false,
  "init": false,
  "init-path": "/usr/libexec/docker-init",
  "insecure-registries": [],
  "ip": "0.0.0.0",
  "ip-forward": false,
  "ip-masq": false,
  "iptables": false,
  "ip6tables": false,
  "ipv6": false,
  "labels": [],
  "live-restore": true,
  "log-driver": "json-file",
  "log-level": "",
  "log-opts": {
    "cache-disabled": "false",
    "cache-max-file": "5",
    "cache-max-size": "20m",
    "cache-compress": "true",
    "env": "os,customer",
    "labels": "somelabel",
    "max-file": "5",
    "max-size": "10m"
  },
  "max-concurrent-downloads": 3,
  "max-concurrent-uploads": 5,
  "max-download-attempts": 5,
  "mtu": 0,
  "no-new-privileges": false,
  "node-generic-resources": [
    "NVIDIA-GPU=UUID1",
    "NVIDIA-GPU=UUID2"
  ],
  "oom-score-adjust": -500,
  "pidfile": "",
  "raw-logs": false,
  "registry-mirrors": [],
  "runtimes": {
    "cc-runtime": {
      "path": "/usr/bin/cc-runtime"
    },
    "custom": {
      "path": "/usr/local/bin/my-runc-replacement",
      "runtimeArgs": [
        "--debug"
      ]
    }
  },
  "seccomp-profile": "",
  "selinux-enabled": false,
  "shutdown-timeout": 15,
  "storage-driver": "",
  "storage-opts": [],
  "swarm-default-advertise-addr": "",
  "tls": true,
  "tlscacert": "",
  "tlscert": "",
  "tlskey": "",
  "tlsverify": true,
  "userland-proxy": false,
  "userland-proxy-path": "/usr/libexec/docker-proxy",
  "userns-remap": ""
}

参考资料:https://my.oschina.net/xsh1208/blog/1837768

<think> 我们正在解决“启动docker.service失败,控制进程退出并返回错误代码”的问题。根据引用[2],一个常见原因是docker配置文件(如daemon.json)存在语法错误,特别是使用了不允许的注释符号(如#)。此外,引用[3]提到需要检查系统内核版本是否满足要求(高于3.10)。引用[4]则显示错误信息中包含'docker.service: Failed with result 'exit-code'',这通常需要查看详细日志。 解决步骤: 1. 检查系统内核版本:使用`uname -r`确保内核版本高于3.10。 2. 检查docker配置文件:daemon.json中不能有注释(除非使用.conf格式),如果存在注释,要么删除注释,要么将文件改为daemon.conf格式(并确保使用允许注释的格式)。 3. 查看详细错误日志:使用`systemctl status docker.service`和`journalctl -xe`查看具体错误信息。 4. 如果配置文件有误,修正后重新加载并重启docker服务。 然而,用户之前的问题是关于docker.socket的启动限制(service-start-limit-hit),但现在的问题是docker.service启动失败(控制进程退出并返回错误代码)。这两个问题可能是相关的,也可能是独立的。当前用户明确要解决的是docker.service启动失败的问题。 因此,我们按照以下步骤解决: 步骤1:检查系统内核版本 步骤2:检查并修正docker配置文件(daemon.json或daemon.conf) 步骤3:查看日志,定位错误 步骤4:根据日志中的具体错误信息采取相应措施 另外,注意引用[1]中提到防火墙问题也可能导致类似错误。所以,如果上述步骤不能解决,还要考虑端口冲突或防火墙设置。 下面是具体的操作指南: </think> ### 🔧 解决 Docker 启动失败问题:控制进程退出并返回错误代码 当 Docker 服务启动失败并提示 `Job for docker.service failed because the control process exited with error code` 时,通常由以下原因导致。请按顺序执行以下步骤: --- ### ️ 解决步骤(分步操作) #### 1️⃣ **检查内核版本兼容性** ```bash uname -r # 检查内核版本 ``` - **要求**:内核版本必须 ≥ 3.10(Docker 最低要求)[^3] - **解决方案**: - 若版本过低:`sudo apt update && sudo apt upgrade -y` 升级系统 - 若为云服务器:在控制台升级内核 #### 2️⃣ **验证配置文件语法** ```bash sudo docker config validate # 检查配置文件语法 ``` - **关键问题**: - `daemon.json` **不允许使用注释**(如 `# 注释内容`)[^2] - 格式错误会导致服务启动失败 - **修复方案**: ```bash sudo mv /etc/docker/daemon.json /etc/docker/daemon.bak # 备份错误配置 sudo echo '{}' > /etc/docker/daemon.json # 创建最小化空配置 ``` #### 3️⃣ **查看详细错误日志** ```bash journalctl -u docker.service -xe --no-pager | tail -n 30 # 查看最后30行错误日志 ``` **常见错误及解决方案**: | 错误类型 | 特征 | 修复方法 | |---------|------|----------| | 端口冲突 | `Address already in use` | `sudo ss -tulnp \| grep 2375` 结束占用进程 | | 文件权限 | `Permission denied` | `sudo chmod 666 /var/run/docker.sock` | | 存储驱动 | `storage-driver not supported` | 在 `daemon.json` 添加 `"storage-driver": "overlay2"` | #### 4️⃣ **修复依赖服务** ```bash sudo systemctl status containerd # 检查容器运行时状态 ``` - 若 containerd 未运行: ```bash sudo apt install containerd -y sudo systemctl enable --now containerd ``` #### 5️⃣ **完全重置 Docker 环境** ```bash sudo systemctl stop docker sudo rm -rf /var/lib/docker/* # 清除旧数据 sudo dockerd --debug # 调试模式启动(观察输出) ``` #### 6️⃣ **防火墙配置** ```bash sudo ufw allow 2375/tcp # 开放 Docker API 端口 sudo ufw reload ``` --- ### 📊 故障诊断公式 $$ \text{解决方案} = \begin{cases} \text{升级内核} & \text{if } \text{kernel} < 3.10 \\ \text{修复配置} & \text{if } \exists \text{语法错误} \\ \text{释放端口} & \text{if } \text{port conflict} \\ \text{重装依赖} & \text{if } \text{containerd missing} \end{cases} $$ --- ### 💡 技术原理说明 Docker 服务启动失败的本质是**控制进程非零退出**。systemd 通过 `ExitCode` 捕获错误,常见原因包括: 1. **配置语法错误**:JSON 文件对注释和格式高度敏感 2. **依赖缺失**:containerd 未运行导致启动链断裂 3. **资源冲突**:端口/套接字被占用(如 `2375/tcp`) 4. **权限问题**:`/var/run/docker.sock` 权限不足 --- ### ❓ 相关问题
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程朗加措

谢谢老板的支持和鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值