Files
docker_practice/05_container/5.3_stop.md
2026-02-09 11:34:35 -08:00

302 lines
7.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 终止容器
本节将介绍如何终止一个运行中的容器以及几种不同的终止方式及其区别
### 终止方式概述
终止容器有三种方式
| 方式 | 命令 | 说明 |
|------|------|------|
| **优雅停止** | `docker stop` | 先发 SIGTERM超时后发 SIGKILL |
| **强制停止** | `docker kill` | 直接发 SIGKILL |
| **自动终止** | - | 容器主进程退出时自动停止 |
---
### docker stop推荐
#### 基本用法
运行以下命令
```bash
$ docker stop 容器名或ID
```
#### 工作原理
具体内容如下
```
docker stop mycontainer
┌─────────────────────────────────────────────────────────────────┐
│ 1. 发送 SIGTERM 信号给容器主进程PID 1
│ ↓ │
│ 2. 等待容器优雅退出(默认 10 秒) │
│ ↓ │
│ 3. 如果超时仍未退出,发送 SIGKILL 强制终止 │
└─────────────────────────────────────────────────────────────────┘
```
#### 自定义超时时间
运行以下命令
```bash
## 等待 30 秒后强制终止
$ docker stop -t 30 mycontainer
## 立即发送 SIGKILL相当于 docker kill
$ docker stop -t 0 mycontainer
```
#### 停止多个容器
运行以下命令
```bash
## 停止多个指定容器
$ docker stop container1 container2 container3
## 停止所有运行中的容器
$ docker stop $(docker ps -q)
```
---
### docker kill
#### 基本用法
运行以下命令
```bash
$ docker kill 容器名或ID
```
#### stop 的区别
| 命令 | 信号 | 使用场景 |
|------|------|---------|
| `docker stop` | SIGTERM SIGKILL | 正常停止让应用优雅退出 |
| `docker kill` | SIGKILL | 应用无响应强制终止 |
#### 发送自定义信号
运行以下命令
```bash
## 发送 SIGHUP让进程重新加载配置
$ docker kill -s HUP mycontainer
## 发送 SIGTERM
$ docker kill -s TERM mycontainer
```
---
### 容器自动终止
容器的生命周期与主进程绑定主进程退出时容器自动停止
```bash
## 主进程是交互式 bash
$ docker run -it ubuntu bash
root@abc123:/# exit # 退出 bash → 容器停止
## 主进程执行完毕
$ docker run ubuntu echo "Hello" # echo 执行完 → 容器停止
```
---
### 查看已停止的容器
运行以下命令
```bash
$ docker ps -a
CONTAINER ID IMAGE COMMAND STATUS NAMES
ba267838cc1b ubuntu "/bin/bash" Exited (0) 2 minutes ago myubuntu
c5d3a5e8f7b2 nginx "nginx" Up 5 minutes mynginx
```
**STATUS 字段说明**
| 状态 | 说明 |
|------|------|
| `Up X minutes` | 运行中 |
| `Exited (0)` | 正常退出退出码 0 |
| `Exited (1)` | 异常退出非零退出码 |
| `Exited (137)` | SIGKILL 终止128 + 9 |
| `Exited (143)` | SIGTERM 终止128 + 15 |
---
### 重新启动容器
#### 启动已停止的容器
运行以下命令
```bash
$ docker start 容器名或ID
## 启动并附加终端
$ docker start -ai 容器名
```
#### 重启运行中的容器
运行以下命令
```bash
## 先停止再启动
$ docker restart 容器名
## 自定义停止超时
$ docker restart -t 30 容器名
```
---
### 生命周期状态图
具体内容如下
```
docker create
┌──────────┐
┌────────│ Created │────────┐
│ └──────────┘ │
│ │ │
│ │ docker start│
│ ▼ │
│ ┌──────────┐ │
│ ┌────│ Running │────┐ │
│ │ └──────────┘ │ │
│ │ │ │ │
│ │ docker │ docker │ │
│ │ pause │ stop │ │
│ ▼ │ │ │
│ ┌──────┐ │ │ │
│ │Paused│ │ │ │
│ └──────┘ │ │ │
│ │ │ │ │
│ │ docker │ │ │
│ │ unpause │ │ │
│ ▼ ▼ │ │
│ └──────►┌──────────┐◄┘ │
│ │ Stopped │ │
│ └──────────┘ │
│ │ │
│ │ docker rm │
│ ▼ │
│ ┌──────────┐ │
└──────────►│ Deleted │◄────┘
└──────────┘
```
---
### 批量操作
#### 停止所有容器
运行以下命令
```bash
$ docker stop $(docker ps -q)
```
#### 删除所有已停止的容器
运行以下命令
```bash
$ docker container prune
```
#### 停止并删除所有容器
运行以下命令
```bash
$ docker stop $(docker ps -q) && docker container prune -f
```
---
### 常见问题
#### Q: 容器停止很慢
原因应用没有正确处理 SIGTERM 信号需要等待超时后强制终止
解决方案
1. 在应用中正确处理 SIGTERM
2. 使用 `docker stop -t 0` 立即终止
3. 检查 Dockerfile 中的 `STOPSIGNAL` 配置
#### Q: 如何让容器优雅退出
确保容器主进程正确处理信号
```dockerfile
## Dockerfile 示例
FROM node:22
...
## 使用 exec 形式确保信号能传递给 node 进程
CMD ["node", "server.js"]
```
#### Q: 容器无法停止
运行以下命令
```bash
## 强制终止
$ docker kill 容器名
## 如果仍无法停止,检查系统资源
$ docker inspect 容器名
```
---
### 本章小结
| 操作 | 命令 | 说明 |
|------|------|------|
| 优雅停止 | `docker stop` | SIGTERM超时后 SIGKILL |
| 强制停止 | `docker kill` | 直接 SIGKILL |
| 重新启动 | `docker start` | 启动已停止的容器 |
| 重启 | `docker restart` | 停止后立即启动 |
| 停止全部 | `docker stop $(docker ps -q)` | 停止所有运行中容器 |
### 延伸阅读
- [启动容器](5.1_run.md)容器启动详解
- [删除容器](4.3_rm.md)清理容器
- [容器日志](logs.md)排查停止原因