Files
docker_practice/07_dockerfile/7.8_volume.md
Baohua Yang 175aaae48a style(docs): standardize heading formats and numbering
- Enforce Level 1-3 structural numbering based on SUMMARY.md hierarchy
- Remove structural numbering from Level 4+ headings
- Eliminate single child headings by converting to bold text
- Auto-inject summary text for headings with multiple children missing intro text
- Exclude Appendix chapters from structural numbering
- Avoid modifying code block contents
- Add script to detect non-standard English usage in headers
2026-02-21 22:40:33 -08:00

308 lines
5.4 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

## 7.8 VOLUME 定义匿名卷
本节涵盖了相关内容与详细描述主要探讨以下几个方面
### 7.8.1 基本语法
如下代码块所示展示了相关示例
```docker
VOLUME ["/路径1", "/路径2"]
VOLUME /路径
```
`VOLUME` 指令创建挂载点并标记为外部挂载的卷
---
### 7.8.2 为什么使用 VOLUME
> **核心原则**容器存储层应该保持无状态任何运行时数据都应该存储在卷中
```mermaid
flowchart LR
subgraph NoVolume ["没有 VOLUME"]
direction TB
subgraph Container1 ["容器存储层"]
direction TB
Files["数据库文件 (问题)<br/>日志文件<br/>上传文件"]
end
Result1["容器删除 = 数据丢失"]
Container1 ~~~ Result1
end
subgraph UseVolume ["使用 VOLUME"]
direction TB
Container2["容器存储层<br/>(只读/无状态)"]
subgraph Volume ["数据卷"]
Data["持久化数据 (安全)"]
end
Container2 --> Volume
Result2["容器删除,数据保留"]
Volume ~~~ Result2
end
```
---
### 7.8.3 基本用法
本节涵盖了相关内容与详细描述主要探讨以下几个方面
#### 定义单个卷
如下代码块所示展示了相关示例
```docker
FROM mysql:8.0
VOLUME /var/lib/mysql
```
#### 定义多个卷
如下代码块所示展示了相关示例
```docker
FROM myapp
VOLUME ["/data", "/logs", "/config"]
```
---
### 7.8.4 VOLUME 的行为
本节涵盖了相关内容与详细描述主要探讨以下几个方面
#### 1自动创建匿名卷
如果运行时未指定挂载Docker 会自动创建匿名卷
```bash
$ docker run mysql:8.0
$ docker volume ls
DRIVER VOLUME NAME
local a1b2c3d4e5f6... # 自动创建的匿名卷
```
#### 2可被命名卷覆盖
运行以下命令
```bash
## 使用命名卷替代匿名卷
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
```
#### 3可被 Bind Mount 覆盖
运行以下命令
```bash
## 使用宿主机目录替代
$ docker run -v /my/data:/var/lib/mysql mysql:8.0
```
---
### 7.8.5 VOLUME 在构建时的特殊行为
> **重要**VOLUME 之后对该目录的修改会被丢弃
```docker
FROM ubuntu
VOLUME /data
## ❌ 这个文件不会出现在镜像中!
RUN echo "hello" > /data/test.txt
```
**原因**VOLUME 指令之后Docker 将该目录视为外部挂载点不再记录对它的修改
#### 概述
总体概述了以下内容
#### 正确做法
如下代码块所示展示了相关示例
```docker
FROM ubuntu
## ✅ 先写入文件
RUN mkdir -p /data && echo "hello" > /data/test.txt
## 再声明 VOLUME
VOLUME /data
```
---
### 7.8.6 常见使用场景
本节涵盖了相关内容与详细描述主要探讨以下几个方面
#### 数据库持久化
如下代码块所示展示了相关示例
```docker
FROM postgres:15
VOLUME /var/lib/postgresql/data
```
#### 日志目录
如下代码块所示展示了相关示例
```docker
FROM nginx
VOLUME /var/log/nginx
```
#### 上传文件目录
如下代码块所示展示了相关示例
```docker
FROM myapp
VOLUME /app/uploads
```
---
### 7.8.7 查看 VOLUME 定义
运行以下命令
```bash
## 查看镜像定义的 VOLUME
$ docker inspect mysql:8.0 --format '{{json .Config.Volumes}}' | jq
{
"/var/lib/mysql": {}
}
## 查看容器挂载的卷
$ docker inspect mycontainer --format '{{json .Mounts}}' | jq
```
---
### 7.8.8 VOLUME vs docker run -v
相关信息如下表
| 特性 | Dockerfile VOLUME | docker run -v |
|------|-------------------|---------------|
| **定义时机** | 镜像构建时 | 容器运行时 |
| **默认行为** | 创建匿名卷 | 可指定命名卷或路径 |
| **灵活性** | (固定路径)| (可任意指定)|
| **适用场景** | 定义必须持久化的路径 | 灵活的数据管理 |
---
### 7.8.9 Compose
Compose 中配置如下
```yaml
services:
db:
image: postgres:15
volumes:
# 命名卷(推荐)
- postgres_data:/var/lib/postgresql/data
# Bind Mount
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
postgres_data: # 声明命名卷
```
---
### 7.8.10 安全注意事项
本节涵盖了相关内容与详细描述主要探讨以下几个方面
#### 概述
总体概述了以下内容
#### 匿名卷可能导致数据丢失
运行以下命令
```bash
## 使用 --rm 运行的容器,匿名卷会在容器删除时一起删除
$ docker run --rm mysql:8.0
## 容器停止后,数据丢失!
...
```
**解决**始终使用命名卷
```bash
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
```
---
### 7.8.11 最佳实践
本节涵盖了相关内容与详细描述主要探讨以下几个方面
#### 1定义必须持久化的路径
如下代码块所示展示了相关示例
```docker
## 数据库必须使用卷
FROM postgres:15
VOLUME /var/lib/postgresql/data
```
#### 2不要在 VOLUME 后修改目录
如下代码块所示展示了相关示例
```docker
## ❌ 避免
VOLUME /app/data
RUN cp init-data.json /app/data/
## ✅ 正确
RUN mkdir -p /app/data && cp init-data.json /app/data/
VOLUME /app/data
```
#### 3文档中说明 VOLUME 用途
如下代码块所示展示了相关示例
```docker
## 持久化用户上传的文件
VOLUME /app/uploads
## 持久化数据库数据
VOLUME /var/lib/mysql
```
---