写给懒猫微服玩家的容器小书 Docker篇(三):《容器部落生活》

忘机山人

发布于380天前
博客图片修整中,看不了可以先搜索公众号“忘机山人”看。
# 《容器部落生活》讲的是 容器生命周期管理,包括容器的启动、停止、查看、交互、日志、后台运行、重启策略等操作

> 一直想写一本容器小书,真好懒猫基本都做了容器化,所以把这部分分享出来。不同的是,懒猫微服中使用pg-docker来替代docker命令,使用dockge来执行docker-compose。以下讲解以标准docker为主,这样子既学会了docker知识,也能够在懒猫微服上启动Docker服务。



镜像旅馆的旅途告一段落,小李的下一站是**容器部落**。

老周牵着他走过一条闪烁着数字光芒的通道,一排排运行中的应用像帐篷一样排列着。有人在调试日志,有人在重启服务,还有人用 `bash` 正在某个容器里“打补丁”。

老周说:

> “镜像只是静态的模板,**容器才是它们的生命**。容器是镜像运行出来的真实世界。”

------

## 🧠 技术基础:容器 vs 镜像

| 项目 | 镜像(Image) | 容器(Container)    |
| ---- | ------------- | -------------------- |
| 类比 | 模板、配方    | 实际的运行实例       |
| 特性 | 只读          | 可读写               |
| 作用 | 用来创建容器  | 实际运行中的程序环境 |
| 状态 | 不运行        | 可运行、停止、销毁   |

------

## 🛫 第一节:容器的启动方式

小李想运行他的 Flask 应用镜像。

老周告诉他:

> “运行镜像的命令是 `docker run`,容器就像是用镜像盖起来的一顶帐篷。”

### 1. 最常见方式(临时 + 前台):

```bash
docker run my-flask-app
```

但程序一执行完就退出了。小李困惑。

老周解释:

> “容器会在主进程结束后自动退出,比如 `CMD ["python", "main.py"]` 一旦结束,容器就结束了。”

------

### 2. 保持后台运行(常用)

```bash
docker run -d --name flask-app -p 5000:5000 my-flask-app
```

解释:

- `-d`:detached 模式,后台运行
- `--name`:给容器取个名字,方便管理
- `-p 宿主端口:容器端口`:端口映射,把容器内部 5000 暴露到外部

> 小李可以在浏览器里访问 `http://localhost:5000`,服务在跑!

------

### 3. 设置环境变量

```bash
docker run -d -e ENV=production my-flask-app
```

在容器内可通过 `os.environ['ENV']` 访问。

------

### 4. 设置自动重启策略(生产强烈建议)

```bash
docker run -d --restart=always my-flask-app
```

可选策略:

| 策略名           | 说明               |
| ---------------- | ------------------ |
| `no`             | 不自动重启(默认) |
| `on-failure`     | 出错时重启         |
| `always`         | 永远重启           |
| `unless-stopped` | 除非人为停止       |

------

## 🧭 第二节:查看容器状态

老周说:“运行中的容器就像是火堆,你得学会看它们是否还在烧。”

### 查看运行中容器:

```bash
docker ps
```

如果想看所有容器(包括已退出的):

```bash
docker ps -a
```

输出示例:

```
CONTAINER ID   IMAGE           STATUS         NAMES
f123abc456     my-flask-app    Up 3 minutes   flask-app
```

------

## 🔄 第三节:容器的停止与重启

### 停止容器:

```bash
docker stop flask-app
```

### 启动容器:

```bash
docker start flask-app
```

### 重启容器:

```bash
docker restart flask-app
```

> ⚠️ 容器停止后并不会删除,除非显式用 `docker rm`

------

## 🧰 第四节:进入容器内“远程调试”

有一次小李发现容器里缺了个配置文件,他想进去看看。

### 使用 exec 进入运行中的容器:

```bash
docker exec -it flask-app /bin/bash
```

- `-i`:保持输入
- `-t`:分配终端
- `/bin/bash`:使用 bash shell(Alpine 镜像可能要用 `/bin/sh`)

> 现在他能像 SSH 进服务器一样,在容器里操作文件、日志、环境变量。

------

## 📜 第五节:查看容器日志

某天应用崩溃了,小李要调日志。

老周提醒他:“容器日志直接走标准输出和错误输出。”

```bash
docker logs flask-app
```

可以加参数看最近内容:

```bash
docker logs --tail 100 flask-app
```

实时滚动输出(调试很有用):

```bash
docker logs -f flask-app
```

------

## 🧽 第六节:删除容器

小李尝试重建容器时,系统提示名字重复。

老周告诉他要先删除原来的:

```bash
docker rm flask-app
```

如果容器还在运行,先 `stop` 再 `rm`,或直接强制:

```bash
docker rm -f flask-app
```

------

## 🔄 第七节:容器生命周期一览表

| 操作            | 命令                             |
| --------------- | -------------------------------- |
| 创建 + 运行容器 | `docker run`                     |
| 后台运行        | `docker run -d`                  |
| 设置名字        | `docker run --name name`         |
| 设置端口映射    | `-p 外:内`                       |
| 查看容器        | `docker ps [-a]`                 |
| 停止容器        | `docker stop name`               |
| 启动容器        | `docker start name`              |
| 重启容器        | `docker restart name`            |
| 删除容器        | `docker rm [-f] name`            |
| 查看日志        | `docker logs [-f] name`          |
| 进入容器        | `docker exec -it name /bin/bash` |

------

## 🧪 小李的实战练习任务

老周布置了一个练习:

> “请你写一个脚本,构建镜像,运行容器,设置环境变量和端口,再用日志确认 Flask 成功启动。”

小李完成如下步骤:

```bash
docker build -t flask-test .
docker run -d --name flask-run -p 8080:5000 -e MODE=debug flask-test
docker logs -f flask-run
docker exec -it flask-run /bin/bash
```

------

## 🧬 衍生补充:容器的状态码解释

容器退出时,可以用 `docker ps -a` 查看 `STATUS` 栏:

- `Exited (0)`:正常退出
- `Exited (1)`:出错退出
- `Up`:正在运行

调试时很有用。

------

## 🎬 尾声:容器部落里的秩序

小李现在已经能够用容器完成:

- 应用部署
- 环境隔离
- 日志查看
- 重启容错
- 在线修复问题

他看着容器部落中灯火通明的帐篷,知道自己终于从一个“只会打包镜像”的新人,成长为能驾驭容器生命周期的工程师。

老周拍拍他肩膀说:

> “你已经能掌控容器的生死了,下一步——掌控它们的数据。”







好嘞,我们来拓展**第三章《容器部落生活》**,新增三大实战内容:

> 🚀 Nginx 容器部署
>  🔗 多个容器配合运行(应用 + 数据库)
>  🩺 容器的服务探针(健康检查)

这部分会继续以**故事+实战命令+讲解**的方式展开,帮助你更贴近真实工作中的容器部署流程。

------

## 🧱 实战一:Nginx 容器部署小站点

小李想搭个静态站点测试,老周给他出了一个练习:

> “用 Nginx 容器部署一个 HTML 网站,只通过 Docker 完成。”

### 1. 准备文件结构:

```
nginx-site/
├── index.html
└── Dockerfile
```

`index.html` 示例:

```html


Hello from Nginx
Hello Docker + Nginx!

```

### 2. Dockerfile 内容(基于官方 Nginx):

```dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
```

> ✅ 把自己的网页文件覆盖掉默认首页。

### 3. 构建 + 运行:

```bash
docker build -t nginx-site .
docker run -d --name my-nginx -p 8080:80 nginx-site
```

打开浏览器访问 `http://localhost:8080`,小李看到页面显示成功,笑得像个孩子。

------

## 🔗 实战二:应用容器 + 数据库容器组合运行

接着老周出了第二个任务:

> “把你的 Flask 应用和一个 MySQL 数据库用两个容器跑起来,实现数据连接。”

### 方法一:手动网络 + 多容器连接

#### 1. 创建网络(容器间通信):

```bash
docker network create flask-net
```

#### 2. 启动 MySQL 容器:

```bash
docker run -d --name my-mysql \
  --network flask-net \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -e MYSQL_DATABASE=mydb \
  mysql:5.7
```

#### 3. 启动 Flask 应用容器(连接到 MySQL):

假设 Flask 连接数据库时使用:

```python
host = 'my-mysql'  # 容器名就是主机名
```

启动命令:

```bash
docker run -d --name flask-app \
  --network flask-net \
  -e DB_HOST=my-mysql \
  -p 5000:5000 \
  my-flask-app
```

> 🔗 容器间在同一个网络中,通过名字直接通信,像局域网一样!

------

### 方法二:使用 `docker-compose`(下一章会详细讲)

------

## 🩺 实战三:为容器添加“健康探针”

老周问小李:“如果你的服务挂了,但容器还在运行,你怎么知道?”

> 小李摇头:这不就是“僵尸容器”吗?

老周笑了:

> “那就给它**加一个健康探针(HEALTHCHECK)**,定期检测服务状态。”

### 为 Flask 容器加健康检查:

修改 `Dockerfile`:

```dockerfile
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:5000/health || exit 1
```

在 Flask 代码中添加一个健康检查路由:

```python
@app.route('/health')
def health():
    return "OK", 200
```

构建镜像,运行容器后,通过命令查看健康状态:

```bash
docker inspect flask-app | grep -i health
```

输出示例:

```
"Health": {
  "Status": "healthy",
  ...
}
```

如果 `/health` 接口返回失败状态码,容器会标记为 `"unhealthy"`,可配合自动重启策略联动修复。

------

## 🧭 实战拓展总结表

| 场景         | 命令 / 技术                                       |
| ------------ | ------------------------------------------------- |
| 部署静态站点 | Nginx + COPY index.html                           |
| 容器间通信   | `docker network create` + `--network` 参数        |
| 多容器组合   | 应用容器连接数据库容器                            |
| 服务探针     | Dockerfile 添加 `HEALTHCHECK`,应用实现 `/health` |
| 探针状态查看 | `docker inspect 容器名                            |

------

## 🎬 尾声 · 容器集群的微光

小李站在容器部落的山丘上,看着成百上千个容器像城市灯火一样运转。

Nginx 做前端代理,Flask 作为后端逻辑,MySQL 管理数据,每个服务都是一块积木,有秩序、有协作。

老周淡淡说:

> “这只是单机的容器调度,真正的战场——在云上。”

小李的眼里闪起光芒:“那我下次要学的就是——Compose,K8s,还有 CI/CD,对吧?”

老周点头:“没错,下一站——数据卷与共享、Compose 编排,再之后……你就要去打云原生的战了。”

评论

0

暂无评论

说点什么呢~
收藏
1
0
0