当前位置: 首页 > news >正文

如何优雅的终止 Docker 容器

init 系统有以下几个特点:

  • 它是系统的第一个进程,负责产生其他所有用户进程。

  • init 以守护进程方式存在,是所有其他进程的祖先。

  • 它主要负责:

    • 启动守护进程

    • 回收孤儿进程

    • 将操作系统信号转发给子进程

1. Docker 容器停止过程

对于容器来说,init 系统不是必须的,当你通过命令 docker stop mycontainer 来停止容器时,docker CLI 会将 TERM 信号发送给 mycontainer 的 PID 为 1 的进程。

  • 如果 PID 1 是 init 进程 - 那么 PID 1 会将 TERM 信号转发给子进程,然后子进程开始关闭,最后容器终止。

  • 如果没有 init 进程 - 那么容器中的应用进程(Dockerfile 中的 ENTRYPOINT 或 CMD 指定的应用)就是 PID 1,应用进程直接负责响应 TERM 信号。这时又分为两种情况:

    • 应用不处理 SIGTERM - 如果应用没有监听 SIGTERM 信号,或者应用中没有实现处理 SIGTERM 信号的逻辑,应用就不会停止,容器也不会终止。

    • 容器停止时间很长 - 运行命令 docker stop mycontainer 之后,Docker 会等待 10s,如果 10s 后容器还没有终止,Docker 就会绕过容器应用直接向内核发送 SIGKILL,内核会强行杀死应用,从而终止容器。

2. 容器进程收不到 SIGTERM 信号?

如果容器中的进程没有收到 SIGTERM 信号,很有可能是因为应用进程不是 PID 1,PID 1 是 shell,而应用进程只是 shell 的子进程。而 shell 不具备 init 系统的功能,也就不会将操作系统的信号转发到子进程上,这也是容器中的应用没有收到 SIGTERM 信号的常见原因。

问题的根源就来自 Dockerfile,例如:

FROM alpine:3.7
COPY popcorn.sh .
RUN chmod +x popcorn.sh
ENTRYPOINT ./popcorn.sh

ENTRYPOINT 指令使用的是 shell 模式[3],这样 Docker 就会把应用放到 shell 中运行,因此 shell 是 PID 1。

解决方案有以下几种:

方案 1:使用 exec 模式的 ENTRYPOINT 指令

与其使用 shell 模式,不如使用 exec 模式[4],例如:

FROM alpine:3.7
COPY popcorn.sh .
RUN chmod +x popcorn.sh
ENTRYPOINT ["./popcorn.sh"]

这样 PID 1 就是 ./popcorn.sh,它将负责响应所有发送到容器的信号,至于 ./popcorn.sh 是否真的能捕捉到系统信号,那是另一回事。

举个例子,假设使用上面的 Dockerfile 来构建镜像,popcorn.sh 脚本每过一秒打印一次日期:

#!/bin/shwhile true
dodatesleep 1
done

构建镜像并创建容器:

🐳 → docker build -t truek8s/popcorn .
🐳 → docker run -it --name corny --rm truek8s/popcorn

打开另外一个终端执行停止容器的命令,并计时:

🐳 → time docker stop corny

因为 popcorn.sh 并没有实现捕获和处理 SIGTERM 信号的逻辑,所以需要 10s 左右才能停止容器。要想解决这个问题,就要往脚本中添加信号处理代码,让它捕获到 SIGTERM 信号时就终止进程:

#!/bin/sh# catch the TERM signal and then exit
trap "exit" TERMwhile true
dodatesleep 1
done

注意:下面这条指令与 shell 模式的 ENTRYPOINT 指令是等效的:

ENTRYPOINT ["/bin/sh", "./popcorn.sh"]

方案 2:直接使用 exec 命令

如果你就想使用 shell 模式的 ENTRYPOINT 指令,也不是不可以,只需将启动命令追加到 exec 后面即可,例如:

FROM alpine:3.7
COPY popcorn.sh .
RUN chmod +x popcorn.sh
ENTRYPOINT exec ./popcorn.sh

这样 exec 就会将 shell 进程替换为 ./popcorn.sh 进程,PID 1 仍然是 ./popcorn.sh

方案 3:使用 init 系统

如果容器中的应用默认无法处理 SIGTERM 信号,又不能修改代码,这时候方案 1 和 2 都行不通了,只能在容器中添加一个 init 系统。init 系统有很多种,这里推荐使用 tini,它是专用于容器的轻量级 init 系统,使用方法也很简单:

  1. 安装 tini

  2. 将 tini 设为容器的默认应用

  3. 将 popcorn.sh 作为 tini 的参数


具体的 Dockerfile 如下:

FROM alpine:3.7
COPY popcorn.sh .
RUN chmod +x popcorn.sh
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--", "./popcorn.sh"]

现在 tini 就是 PID 1,它会将收到的系统信号转发给子进程 popcorn.sh

如果你想直接通过 docker 命令来运行容器,可以直接通过参数 --init 来使用 tini,不需要在镜像中安装 tini。如果是 Kubernetes 就不行了,还得老老实实安装 tini。

3. 使用 tini 后应用还需要处理 SIGTERM 吗?

最后一个问题:如果移除 popcorn.sh 中对 SIGTERM 信号的处理逻辑,容器会在我们执行停止命令后立即终止吗?

答案是肯定的。在 Linux 系统中,PID 1 和其他进程不太一样,准确地说应该是 init 进程和其他进程不一样,它不会执行与接收到的信号相关的默认动作,必须在代码中明确实现捕获处理 SIGTERM 信号的逻辑,方案 1 和 2 干的就是这个事。

普通进程就简单多了,只要它收到系统信号,就会执行与该信号相关的默认动作,不需要在代码中显示实现逻辑,因此可以优雅终止。

相关文章:

如何优雅的终止 Docker 容器

init 系统有以下几个特点: 它是系统的第一个进程,负责产生其他所有用户进程。 init 以守护进程方式存在,是所有其他进程的祖先。 它主要负责: 启动守护进程 回收孤儿进程 将操作系统信号转发给子进程 1. Docker 容器停止过程…...

SXSSFWorkbook-MinIo-大数据-流式导出

文章目录 前言业务现状架构思路技术细节生成摘要IDSXSSFWorkbookMinIomybatis 流查询PipedInputStream 保存到minio 总结 前言 由于业务涉及到数据比较大,用户对导出功能使用频繁,每次导出数据两10万以上。 为了减少数据库压力,及应用服务器…...

使用PyQt5创建图片查看器应用程序

使用PyQt5创建图片查看器应用程序 作者:安静到无声 个人主页 在本教程中,我们将使用PyQt5库创建一个简单的图片查看器应用程序。这个应用程序可以显示一系列图片,并允许用户通过按钮切换、跳转到不同的图片。 1. 准备工作 首先&#xff0…...

怎样制作一个展会场馆预约小程序

随着互联网的发展,展会行业也逐渐向数字化转型。展会场馆预约小程序作为展会线下向线上的延伸,能够让参展商和观众随时随地进行预约,大大提升了客户的体验。那么,如何制作一个展会场馆预约小程序呢?下面就以乔拓云平台…...

呼叫中心系统信息发送功能的应用

通常情况下功能比较齐全的呼叫中心系统都会有短信功能,那么短信功能在呼叫中心职场中有哪些应用呢? 呼叫中心系统中短信功能主要分为三部分:短信发送、待发送短信、短信发件箱,先来简单了解一下这三个功能在工作中如何使用。 短信…...

Android笔记(三)多Activity活动的切换中的简化处理

多Activity实现的跳转简单实现 Activity定义移动的界面。在本例中,介绍多个活动之间的切换的简化通用的实现。在本例中,定义三个活动MainActivity、FirstActivity和SecondActivity.要求能从MainActivity分别切换到FirstActivity和SecondActivity&#x…...

vue打包压缩

参考 https://www.cnblogs.com/lafitewu/p/8309305.html 注意:方法1和方法2不能同时用 取消打包的map config/index.js的productionSourceMap设置为false 抽取js 将部分常用又比较大的组件直接抽取为一个单独的js 打开webpack.base.conf.js,在module.exports.entry中添加想…...

Mysql5.7大限将至升级Mysql 8.0过程记录(未完)

一、前言 时间很快,到2023年10月底,MySQL 5.7就到了它的EOL(End of Life),届时将不会提供任何补丁,无法应对潜在的安全风险;是时候和 MySQL 5.7 说再见了!!!&…...

多架构环境下docker-compose部署rocketmq单机模式—— 筑梦之路

接上篇linux上构建任意版本的rocketmq多架构x86 arm镜像——筑梦之路-CSDN博客,本文适用于x86、arm等多架构环境。 话不多说,直接上代码。 准备broker配置文件 #broker配置文件示例 cat data/broker/conf/broker.conf brokerClusterName DefaultClus…...

[Unity][VR]Passthrough2-创建一个基本的Passthrough应用

上一期我们对PassthroughXR项目做好了基本的项目设置,今天我们就开始构建一个基本的Passthrough应用。 我们还是从基本场景开始。先把默认的main camera删除。因为后续我们会引入OVR Rig对象,这个对象自带Camera用来实现VR视角。 在Project面板我们搜索OVR camera rig。看见…...

【Unity3D赛车游戏制作】设置面板搭建——UGUI复合控件

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:Uni…...

如何让 Source Insight 识别 AUTOSAR 宏定义 FUNC

有很多从事汽车电子行业的软件工程师在使用Source Insight阅览Classic AUTOSAR协议栈源码的时候, 发现函数名无法解析,基本上都变成了FUNC。 先说原因: AUTOSAR的协议栈为了实现多平台和编译器兼容,大量使用宏定义来代替关键字。…...

sts搭建springboot

sts搭建springboot 需要的软件 Apache-maven-3.3.9.rar 链接:百度网盘 请输入提取码 提取码:1xgj Spring-tool-suite-4-4.20.0.RELEASE-e4.29.0-win32.win32.x86_64.self-extracting.jar 链接:百度网盘 请输入提取码 提取码:p…...

解决react使用css module无法重写bootstrap样式的问题

react使用css module虽然能够解决样式污染,但是同时也失去了写css样式的灵活性,特别是:在.module.css文件中当子元素是非变量的静态class类(比如bootstrap), 此时使用css选择器对该子元素的样式不会起作用的 比如下面…...

自动驾驶软件和人工智能

自动驾驶汽车的核心在于其软件系统,而其中的机器学习和深度学习技术是使车辆能够感知、理解、决策和行动的关键。本文将深入探讨这些技术在自动驾驶中的应用,包括感知、定位、路径规划以及道路标志和交通信号的识别。 1. 机器学习和深度学习在自动驾驶中…...

堆叠、集群技术

1.堆叠、集群技术的概述 堆叠、集群简介 堆叠(iStack),将多台支持堆叠特性的交换机通过堆叠线缆连接在一起,从逻辑上虚拟成一台交换设备,作为一个整体参与数据转发。 集群(Cluster Switch System&#xf…...

SpringCould微服务保护01——Sentinel组件下载并使用

1.初识Sentinel 1.1.雪崩问题及解决方案 1.1.1.雪崩问题 微服务中,服务间调用关系错综复杂,一个微服务往往依赖于多个其它微服务。 如图,如果服务提供者I发生了故障,当前的应用的部分业务因为依赖于服务I,因此也会被…...

可扩展性对物联网管理系统有哪些影响?

可扩展性对于物联网管理系统的设计和开发非常重要,它直接影响着系统的性能、可靠性和能耗等方面,是评估一个系统优劣的重要因素之一。可扩展性对物联网管理系统的影响主要体现在以下几个方面: 设备兼容性:物联网管理系统的可扩展性…...

洗地机哪个品牌最耐用质量好?2023年最好用的洗地机

随着科技的发展,人们的生活越来越便利,就拿打扫卫生来说,现在越来越多人抛弃扫把、地拖,转而选择让清洁更加轻松的清洁家电,而洗地机就是这样一种让打扫卫生变得简单轻松的家电。近年来洗地机销量剧增,是目…...

计算机视觉(Computer Vision, CV)是什么?

什么是计算机视觉 近年来,计算机视觉 (Computer Vision,简称CV) 不断普及,已成为人工智能 (AI) 增长最快的领域之一。计算机视觉致力于使计算机能够识别和理解图像和视频中的物体和人。 计算机视觉应用程序使用来自传感设备、人工智能、机器…...

【【萌新的SOC学习之自定义IP核 AXI4接口】】

萌新的SOC学习之自定义IP核 AXI4接口 自定义IP核-AXI4接口 AXI接口时序 对于一个读数据信号 AXI突发读 不要忘记 最后还有拉高RLAST 表示信号的中止 实验任务 : 通过自定义一个AXI4接口的IP核 ,通过AXI_HP接口对PS端 DDR3 进行读写测试 。 S_AXI…...

设计模式-创建型模式

文章目录 一、单例模式1.饿汉式(1) 静态变量(2) 静态代码块(3) 枚举方式 2.懒汉式(1) 双检锁(2) 静态内部类 3.破坏单例模式(1) 序列化(2) 反射 4.解决单例模式被破坏(1) 序列化、反序列化破坏单例模式的解决方法(2) 反射破坏单例解决 二、工厂方法模式1.简单工厂模式2.工厂方法…...

golang中的RSA算法,加密解密,签名校验,导出公钥密钥,导入公钥密钥

RSA算法广泛应用与数据加密(比如 SSL 传输层加密),数字签名(比如支付宝的支付签名)。 1、加密解密 // encrypts the given message with RSA-OAEP func f1() {// random 用来生成随机的素数rsaPriviteKey, err : rsa…...

修炼k8s+flink+hdfs+dlink(四:k8s(二)组件)

一:控制平面组件。 控制平面组件会为集群做出全局决策,比如资源的调度。 以及检测和响应集群事件,例如当不满足部署的 replicas 字段时, 要启动新的 pod)。 1. kube-apiserver。 该组件负责公开了 Kubernetes API&a…...

Android约束布局ConstraintLayout流式Flow

Android约束布局ConstraintLayout流式Flow <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.…...

Android JNI代码语法解释

文章目录 JNI中的JNIEXPORT、JNIIMPORT和JNICALLJVM如何查找native方法①按照JNI规范的命名规则②调用JNI提供的RegsterNatives函数&#xff0c;将本地函数注册到JVM中示例代码 JNI数据类型JNI字符串的处理①获取字符串②释放字符串③创建字符串④其他字符串处理API JNI中的JNI…...

小程序和前台开发软件定制的相关信息|APP网站搭建

小程序和前台开发软件定制的相关信息 在如今数字化时代&#xff0c;软件、小程序和前台开发软件定制已经成为了企业必备的工具之一。那么&#xff0c;这些工具到底有什么作用呢&#xff1f;接下来&#xff0c;我将为大家详细介绍。 首先&#xff0c;让我们来了解一下软件。软件…...

JVM监控及诊断工具-GUI篇

文章目录 JVM监控及诊断工具-GUI篇工具概述JConsoleVisual VM再谈内存泄漏Java中内存泄漏的8种情况Arthas&#xff08;阿尔萨斯&#xff09;康师傅使用阿尔萨斯的例子help指令 JVM监控及诊断工具-GUI篇 工具概述 使用上一章命令行工具或组合能获取目标Java应用性能相关的基础…...

【C++STL基础入门】list基本使用

文章目录 前言一、list简介1.1 list是什么1.2 list的头文件 二、list2.1 定义对象2.2 list构造函数2.3 list的属性函数 总结 前言 STL&#xff08;Standard Template Library&#xff09;是C标准库的一个重要组成部分&#xff0c;提供了一套丰富的数据结构和算法&#xff0c;可…...

WSL+vscode配置miniob环境

1.配置WSL Windows Subsystem for Linux入门&#xff1a;安装配置图形界面中文环境vscode wu-kan 2.获取源码 找个位置Git Bash然后拉取代码 git clone https://github.com/oceanbase/miniob.git 3.安装相关依赖 https://gitee.com/liangcha-xyy/source/blob/master/how…...