test01
@@ -1,939 +0,0 @@
|
||||
# 01.Docker介绍与安装
|
||||
|
||||
## 01.Docker介绍与安装
|
||||
|
||||
### 1. Docker是什么?
|
||||
|
||||
Docker是一个在2013年开源的应用程序,并且是一个基于go语言编写的PAAS服务。
|
||||
|
||||
Docker最早采用LXC技术,之后改为自己研发并开源的runc技术运行容器。
|
||||
|
||||
Docker相比虚拟机的交付速度更快,资源消耗更低,Docker采用客户端、服务端架构,使用远程api来管理和创建Docker容器。
|
||||
|
||||
Docker的三大理念是build(构建)、ship(运输)、run(运行)。
|
||||
|
||||
Docker通过namespace、cgroup等技术来提供容器的资源隔离与安全保障。
|
||||
|
||||
### 2. Docker与虚拟机之间的对比
|
||||
|
||||

|
||||
|
||||
| **虚拟化** | **容器** |
|
||||
| ------------------------------------------------ | ------------------------------------------------------- |
|
||||
| 隔离性强,有独立的GUEST OS | 共享内核和OS,隔离性弱! |
|
||||
| 虚拟化性能差(>15%) | 计算/存储无损耗,无Guest OS内存开销(~200M) |
|
||||
| 虚拟机镜像庞大(十几G~几十G), 且实例化时不能共享 | Docker容器镜象200~300M,且公共基础镜象实例化时可以共享 |
|
||||
| 虚拟机镜象缺乏统一标准 | Docker提供了容器应用镜象事实标准,OCI推动进一 步标准化 |
|
||||
| 虚拟机创建慢(>2分钟) | 秒级创建(<10s)相当于建立索引 |
|
||||
| 虚拟机启动慢(>30s) 读文件逐个加载 | 秒级(<1s,不含应用本身启动) |
|
||||
| 资源虚拟化粒度低,单机10~100虚拟机 | 单机支持1000+容器密度很高,适合大规模的部署 |
|
||||
|
||||
- 资源利用率更高:一台物理机可以运行数百个容器,但一般只能运行数十个虚拟机
|
||||
- 开销更小:不需要启动单独的虚拟机占用硬件资源
|
||||
- 启动速度更快:可以在数秒内完成启动
|
||||
|
||||
### 3. Docker的组成
|
||||
|
||||
官网:https://docs.docker.com/get-started/overview/
|
||||
|
||||
Docker主机 host:一个物理机或者虚拟机,用于运行docker服务进程和容器
|
||||
|
||||
Docker服务端 Server:Docker守护进程,运行docker容器
|
||||
|
||||
Docker客户端 client:客户端使用docker命令或其他工具调用docker api
|
||||
|
||||
Docker仓库 registry:保存镜像的仓库,类似于git或svn这样的版本控制器
|
||||
|
||||
Docker镜像 images:镜像可以理解为创建实例使用的模板
|
||||
|
||||
Docker容器 container:容器是从镜像生成对外提供服务的一个或一组服务
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### 4. Docker服务端软件选择
|
||||
|
||||
Docker CE(Community Edition,社区版)和 Docker EE(Enterprise Edition,企业版)是 Docker 产品的两个主要版本,它们之间的主要区别在于目标用户、功能集、支持和维护等方面:
|
||||
|
||||
1. **目标用户**:
|
||||
- **Docker CE**:面向个人开发者、小团队以及技术爱好者,主要用于开发和测试环境。
|
||||
- **Docker EE**:面向大型企业和组织,提供企业级的功能和支持。
|
||||
2. **功能集**:
|
||||
- **Docker CE**:提供基本的容器化功能,包括构建、运行和共享容器。
|
||||
- **Docker EE**:除了包含 CE 版本的所有功能外,还提供了额外的企业级特性,如增强的安全、管理、可扩展性和集成性。
|
||||
3. **支持和维护**:
|
||||
- **Docker CE**:社区支持,适合自我解决问题的开发者。
|
||||
- **Docker EE**:提供商业支持和专业服务,适合需要稳定运行环境的企业。
|
||||
4. **安全性**:
|
||||
- **Docker CE**:安全性相对较低,适合非生产环境。
|
||||
- **Docker EE**:提供更高级的安全特性,如镜像扫描、安全策略和合规性报告。
|
||||
5. **管理**:
|
||||
- **Docker CE**:通常不需要复杂的管理工具。
|
||||
- **Docker EE**:提供 Docker Universal Control Plane (UCP) 和 Docker Trusted Registry (DTR) 等管理工具,帮助企业更有效地管理容器环境。
|
||||
6. **成本**:
|
||||
- **Docker CE**:免费。
|
||||
- **Docker EE**:需要购买许可证。
|
||||
7. **更新和生命周期**:
|
||||
- **Docker CE**:更新频繁,可能包含实验性功能,生命周期较短。
|
||||
- **Docker EE**:更新周期更稳定,更注重稳定性和兼容性,生命周期较长。
|
||||
|
||||
### 5. Docker安装
|
||||
|
||||
- 安装docker-ce
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# yum install -y yum-utils
|
||||
[root@localhost ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
|
||||
[root@localhost ~]# sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
|
||||
[root@localhost ~]# yum install docker-ce -y
|
||||
```
|
||||
|
||||
- 启动docker
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# systemctl enable --now docker
|
||||
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
|
||||
[root@localhost ~]# systemctl status docker
|
||||
● docker.service - Docker Application Container Engine
|
||||
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: disabled)
|
||||
Active: active (running) since Sun 2025-03-23 23:36:27 CST; 10s ago
|
||||
TriggeredBy: ● docker.socket
|
||||
Docs: https://docs.docker.com
|
||||
Main PID: 29081 (dockerd)
|
||||
Tasks: 10
|
||||
Memory: 25.7M
|
||||
CPU: 141ms
|
||||
CGroup: /system.slice/docker.service
|
||||
└─29081 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
|
||||
```
|
||||
|
||||
#### 5.1 镜像加速配置
|
||||
|
||||
由于Docker Image仓库在国外,目前,从23年底开始,国内陆续访问不到了,所以要通过一些镜像加速器才能获取到镜像
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker pull nginx
|
||||
Error response from daemon: Get "https://registry-1.docker.io/v2/": context deadline exceeded
|
||||
|
||||
# 无法从docker官方镜像仓库,docker.io获取镜像
|
||||
```
|
||||
|
||||
**使用国内镜像加速器**(不稳定,会经常变化)
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# mkdir -p /etc/docker
|
||||
[root@localhost ~]# vim /etc/docker/daemon.json
|
||||
{
|
||||
"registry-mirrors": [
|
||||
"https://docker.m.daocloud.io"
|
||||
]
|
||||
}
|
||||
|
||||
# 重启容器服务
|
||||
[root@localhost ~]# systemctl daemon-reload
|
||||
[root@localhost ~]# systemctl restart docker
|
||||
|
||||
# 可选加速地址(不一定有用,随时会跑路):
|
||||
1、https://docker.m.daocloud.io
|
||||
2、https://docker.1panelproxy.com
|
||||
3、https://atomhub.openatom.cn
|
||||
4、https://docker.1panel.live
|
||||
5、https://dockerhub.jobcher.com
|
||||
6、https://hub.rat.dev
|
||||
7、https://docker.registry.cyou
|
||||
8、https://docker.awsl9527.cn
|
||||
9、https://do.nark.eu.org/
|
||||
10、https://docker.ckyl.me
|
||||
11、https://hub.uuuadc.top
|
||||
12、https://docker.chenby.cn
|
||||
13、https://docker.ckyl.me
|
||||
|
||||
|
||||
# 实在不行的话,可以在拉去的时候手动加上镜像加速器,因为有时候写到daemon.json中也有可能访问不到
|
||||
[root@localhost ~]# docker pull nginx
|
||||
[root@localhost ~]# docker pull docker.m.daocloud.io/nginx
|
||||
[root@localhost ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
nginx latest 53a18edff809 6 weeks ago 192MB
|
||||
```
|
||||
|
||||
#### 5.2 快速开始
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker pull nginx
|
||||
[root@localhost ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
nginx latest d1a364dc548d 5 days ago 133MB
|
||||
[root@localhost ~]# docker run -d -p 80:80 nginx
|
||||
e617ca1db9a5d242e6b4145b9cd3dff9f7955c6ab1bf160f13fb6bec081a29e4
|
||||
[root@localhost ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
e617ca1db9a5 nginx "/docker-entrypoint.…" 6 seconds ago Up 5 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp intelligent_turing
|
||||
[root@localhost ~]# docker exec -it e617ca1db9a5 bash
|
||||
root@e617ca1db9a5:/# cd /usr/share/nginx/html/
|
||||
root@e617ca1db9a5:/usr/share/nginx/html# ls
|
||||
50x.html index.html
|
||||
root@e617ca1db9a5:/usr/share/nginx/html# echo 'docker nginx test' > index.html
|
||||
[root@localhost ~]# curl 192.168.88.10
|
||||
docker nginx test
|
||||
|
||||
[root@admin ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED NAMES
|
||||
e0a818c40b7e nginx "/docker-entrypoint.…" About an hour ago 0.0.0.0:9000->9000/tcp, :::9000->9000/tcp determined_sanderson
|
||||
9b066ef4bcd2 nginx "/docker-entrypoint.…" About an hour ago 90->80/tcp, :::90->80/tcp vigorous_hypatia
|
||||
[root@admin ~]# docker stop e0a818c40b7e
|
||||
e0a818c40b7e
|
||||
[root@localhost ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
```
|
||||
|
||||
- **`-i`(`--interactive`)**:
|
||||
- **功能**:保持标准输入(stdin)打开,即使没有附加终端。
|
||||
- **作用**:允许用户与容器内的命令进行交互。
|
||||
- **`-t`(`--tty`)**:
|
||||
- **功能**:分配一个伪终端(TTY)。
|
||||
- **作用**:为用户创建一个类似本地终端的交互环境,支持颜色显示、光标操作等终端特性。
|
||||
|
||||
##### 5.2.1 Docker快速搭建RPG小游戏
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker pull registry.cn-guangzhou.aliyuncs.com/welldene/games:rpg_game
|
||||
[root@localhost ~]# docker run -d -p 8000:8000 -p 8787:8787 --name rpg -e HOST_IP=192.168.88.10 registry.cn-guangzhou.aliyuncs.com/welldene/games:rpg_game
|
||||
9c4bc95c98836a1df0453c282196083e4cb0b5d06e507d5d4567a4c018c13272
|
||||
[root@localhost ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
35a6b44d5645 registry.cn-guangzhou.aliyuncs.com/welldene/games:rpg_game "bash run.sh" 3 seconds ago Up 2 seconds 0.0.0.0:8000->8000/tcp, [::]:8000->8000/tcp, 0.0.0.0:8787->8787/tcp, [::]:8787->8787/tcp rpg
|
||||
```
|
||||
|
||||
**浏览器访问: http://IP:8787**
|
||||
|
||||

|
||||
|
||||
##### 5.2.2 Docker参数说明
|
||||
|
||||
```bash
|
||||
-d, --detach: 以守护进程方式运行容器
|
||||
-p, --publish: 映射容器端口到宿主机端口
|
||||
格式: `-p [hostPort]:[containerPort]`
|
||||
|
||||
-P(大写):随机端口映射
|
||||
|
||||
-v, --volume: 挂载数据卷
|
||||
格式: `-v [hostPath]:[containerPath]`
|
||||
|
||||
-e, --env: 设置环境变量
|
||||
--name: 为容器指定名称
|
||||
--network: 指定容器所属网络
|
||||
--restart: 容器退出时的重启策略
|
||||
可选值: `no`, `on-failure`, `unless-stopped`, `always`
|
||||
|
||||
-i, --interactive: 保持标准输入打开
|
||||
-t, --tty: 分配一个伪终端
|
||||
-u, --user: 指定运行容器的用户
|
||||
--entrypoint: 覆盖容器的默认入口点
|
||||
--rm: 容器退出后自动删除
|
||||
--hostname: 设置容器主机名
|
||||
--add-host: 添加自定义主机名到 IP 的映射
|
||||
--link: 添加到另一个容器的链接
|
||||
--expose: 暴露容器端口
|
||||
--volume-driver: 指定数据卷驱动程序
|
||||
--cpu-shares: 设置 CPU 权重
|
||||
--memory: 设置容器内存限制
|
||||
```
|
||||
|
||||
### 6. Docker核心技术
|
||||
|
||||
#### 6.1 Linux namespace技术
|
||||
|
||||
如果一个宿主机运行了N个容器,多个容器带来的以下问题怎么解决:
|
||||
|
||||
1. 怎么样保证每个容器都有不同的文件系统并且能互不影响?
|
||||
2. 一个docker主进程内的各个容器都是其子进程,那么如何实现同一个主进程下不同类型的子进程?各个子进程间通信能相互访问吗?
|
||||
3. 每个容器怎么解决IP以及端口分配的问题?
|
||||
4. 多个容器的主机名能一样吗?
|
||||
5. 每个容器都要不要有root用户?怎么解决账户重名问题呢?
|
||||
|
||||
以上问题怎么解决
|
||||
|
||||
Docker 的 Namespace 技术是实现容器隔离的核心机制之一。它通过 Linux Namespace 提供的隔离功能,为每个容器创建独立的资源视图,从而实现容器之间的隔离
|
||||
|
||||
**namespace**是Linux系统的底层概念,在内核层实现,即有一些不同类型的命名空间都部署在核内,**各个docker容器运行在同一个docker主进程并且共用同一个宿主机系统内核**,各个docker容器运行在宿主机的用户空间,每个容器都要有类似于虚拟机一样的相**互隔离的运行空间**,但是容器技术是在一个进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响,如文件系统、网络空间、进程空间等,目前主要通过以下技术实现容器运行空间的相互隔离:
|
||||
|
||||
| 隔离类型 | 功能 | 系统调用参数 | 内核 |
|
||||
| -------------------------------------------- | ---------------------------------- | ------------- | ------ |
|
||||
| MNT Namespace(mount) | 提供磁盘挂载点和文件系统的隔离能力 | CLONE_NEWNS | 2.4.19 |
|
||||
| IPC Namespace(Inter-Process Communication) | 提供进程间通信的隔离能力 | CLONE_NEWIPC | 2.6.19 |
|
||||
| UTS Namespace(UNIX Timesharing System) | 提供主机名隔离能力 | CLONE_NEWUTS | 2.6.19 |
|
||||
| PID Namespace(Process Identification) | 提供进程隔离能力 | CLONE_NEWPID | 2.6.24 |
|
||||
| Net Namespace(network) | 提供网络隔离能力 | CLONE_NEWNET | 2.6.29 |
|
||||
| User Namespace(user) | 提供用户隔离能力 | CLONE_NEWUSER | 3.8 |
|
||||
|
||||
##### 6.1.1 MNT Namespace
|
||||
|
||||
每个容器都要有独立的根文件系统有独立的用户空间,以实现容器里面启动服务并且使用容器的运行环境。
|
||||
|
||||
- 启动三个容器
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -d --name nginx-1 -p 80:80 nginx
|
||||
0e72f06bba417073d1d4b2cb53e62c45b75edc699b737e46a157a3249f3a803e
|
||||
[root@localhost ~]# docker run -d --name nginx-2 -p 81:80 nginx
|
||||
c8ce6a0630b66e260eef16d8ecf48049eed7b893b87459888b634bf0e9e40f23
|
||||
[root@localhost ~]# docker run -d --name nginx-3 -p 82:80 nginx
|
||||
1cddbd412b5997f8935815c2f588431e100b752595ceaa92b95758ca45179096
|
||||
[root@localhost ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
b42378a51c40 nginx "/docker-entrypoint.…" 2 seconds ago Up 1 second 0.0.0.0:82->80/tcp, [::]:82->80/tcp nginx-3
|
||||
d30f033c2f29 nginx "/docker-entrypoint.…" 5 seconds ago Up 5 seconds 0.0.0.0:81->80/tcp, [::]:81->80/tcp nginx-2
|
||||
d34a012dcebc nginx "/docker-entrypoint.…" 10 seconds ago Up 10 seconds 0.0.0.0:80->80/tcp, [::]:80->80/tcp nginx-1
|
||||
```
|
||||
|
||||
- 连接进入某一个容器中,并创建一个文件
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker exec -it nginx-1 bash
|
||||
root@d34a012dcebc:/# echo 'hello world test!' > /opt/test_nginx-1
|
||||
root@d34a012dcebc:/# exit
|
||||
```
|
||||
|
||||
- 宿主机是使用了chroot技术把容器锁定到一个指定的运行目录里
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# find / -name test_nginx-1
|
||||
/var/lib/docker/overlay2/075b51fb5d33011d4b449fde8c14199c1e30f86224862f68a6116b1cb1dacfdf/diff/opt/test_nginx-1
|
||||
/var/lib/docker/overlay2/075b51fb5d33011d4b449fde8c14199c1e30f86224862f68a6116b1cb1dacfdf/merged/opt/test_nginx-1
|
||||
```
|
||||
|
||||
在 Docker 中,文件系统是通过分层存储机制实现的,这与 Docker 的镜像和容器的架构有关。看到的两个文件路径反映了 Docker 的存储驱动(如 Overlay2)的工作原理。
|
||||
|
||||
###### 6.1.1.1 Docker 的存储架构
|
||||
|
||||
1. **镜像层(Read-Only)**:
|
||||
- Docker 镜像是由多个只读层组成的。每一层代表了镜像的某个状态或修改。
|
||||
- 这些层是不可变的,一旦创建,不会被修改。
|
||||
2. **容器层(Read-Write)**:
|
||||
- 当你运行一个容器时,Docker 会在镜像层之上添加一个可写层。
|
||||
- 容器的所有写操作(如创建文件、修改文件等)都会在这个可写层中进行,而不会影响下面的镜像层。
|
||||
|
||||
###### 6.1.1.2 Overlay2 存储驱动
|
||||
|
||||
Docker 默认使用 Overlay2 存储驱动(在支持的系统上)。Overlay2 的工作机制如下:
|
||||
|
||||
- **`merged` 目录**:
|
||||
- 这是容器的根文件系统,是镜像层和容器层的联合视图。
|
||||
- 当你在容器中访问文件时,看到的是 `merged` 目录中的内容。
|
||||
- 例如,你在容器中创建的文件 `/opt/test_nginx-1`,在宿主机上可以通过 `/var/lib/docker/overlay2/<id>/merged/opt/test_nginx-1` 访问。
|
||||
- **`diff` 目录**:
|
||||
- 这是容器的可写层,记录了容器对文件系统的修改。
|
||||
- 当你在容器中创建或修改文件时,实际的文件数据会存储在 `diff` 目录中。
|
||||
- 例如,你在容器中创建的文件 `/opt/test_nginx-1`,其实际数据存储在 `/var/lib/docker/overlay2/<id>/diff/opt/test_nginx-1`。
|
||||
|
||||
- 当你在容器中创建文件 `/opt/test_nginx-1` 时:
|
||||
- 文件的实际数据被写入到 `diff` 目录中。
|
||||
- 在 `merged` 目录中,通过联合文件系统(OverlayFS)的机制,将 `diff` 目录中的文件映射到 `merged` 目录中,让你在容器中看到完整的文件系统视图。
|
||||
|
||||
##### 6.1.2 IPC Namespace
|
||||
|
||||
一个容器内的进程间通信,允许一个容器内的不同进程数据互相访问,但是不能跨容器访问其他容器的数据
|
||||
|
||||
UTS Namespace包含了运行内核的名称、版本、底层体系结构类型等信息用于系统表示,其中包含了hostname和域名,它使得一个容器拥有属于自己hostname标识,这个主机名标识独立于宿主机系统和其上的其他容器。
|
||||
|
||||
##### 6.1.3 PID Namespace
|
||||
|
||||
Linux系统中,有一个pid为1的进程(init/systemd)是其他所有进程的父进程,那么在每个容器内也要有一个父进程来管理其下属的进程,那么多个容器的进程通PID namespace进程隔离
|
||||
|
||||
- 安装软件包
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker exec -it 065f06e5caa4 bash
|
||||
root@0e72f06bba41:/# apt update
|
||||
# ifconfig
|
||||
root@0e72f06bba41:/# apt install -y net-tools
|
||||
root@0e72f06bba41:/# apt install -y procps
|
||||
root@0e72f06bba41:/# ps -ef
|
||||
UID PID PPID C STIME TTY TIME CMD
|
||||
root 10 0 03:20 ? 00:00:00 nginx: master process nginx -g d
|
||||
nginx 32 1 0 03:20 ? 00:00:00 nginx: worker process
|
||||
nginx 33 1 0 03:20 ? 00:00:00 nginx: worker process
|
||||
nginx 34 1 0 03:20 ? 00:00:00 nginx: worker process
|
||||
nginx 35 1 0 03:20 ? 00:00:00 nginx: worker process
|
||||
nginx 36 1 0 03:20 ? 00:00:00 nginx: worker process
|
||||
nginx 37 1 0 03:20 ? 00:00:00 nginx: worker process
|
||||
nginx 38 1 0 03:20 ? 00:00:00 nginx: worker process
|
||||
nginx 39 1 0 03:20 ? 00:00:00 nginx: worker process
|
||||
root 59 0 0 03:35 pts/0 00:00:00 bash
|
||||
root 503 59 0 03:42 pts/0 00:00:00 ps -ef
|
||||
```
|
||||
|
||||
**那么宿主机的PID与容器内的PID是什么关系?**
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# yum install psmisc
|
||||
[root@localhost ~]# pstree -p
|
||||
[root@localhost ~]# pstree -p
|
||||
systemd(1)─┬─NetworkManager(769)─┬─{NetworkManager}(772)
|
||||
│ └─{NetworkManager}(775)
|
||||
├─agetty(817)
|
||||
├─atd(799)
|
||||
├─auditd(693)─┬─sedispatch(695)
|
||||
│ ├─{auditd}(694)
|
||||
│ └─{auditd}(696)
|
||||
├─bluetoothd(742)
|
||||
├─chronyd(753)
|
||||
├─containerd(28884)─┬─{containerd}(28886)
|
||||
│ ├─{containerd}(28887)
|
||||
│ ├─{containerd}(28888)
|
||||
│ ├─{containerd}(28889)
|
||||
│ ├─{containerd}(28890)
|
||||
│ ├─{containerd}(28891)
|
||||
│ ├─{containerd}(28892)
|
||||
│ └─{containerd}(28894)
|
||||
├─containerd-shim(30330)─┬─bash(30801)
|
||||
│ ├─nginx(30353)─┬─nginx(30426)
|
||||
│ │ ├─nginx(30427)
|
||||
│ │ ├─nginx(30428)
|
||||
│ │ └─nginx(30429)
|
||||
│ ├─{containerd-shim}(30332)
|
||||
│ ├─{containerd-shim}(30333)
|
||||
│ ├─{containerd-shim}(30334)
|
||||
│ ├─{containerd-shim}(30335)
|
||||
│ ├─{containerd-shim}(30336)
|
||||
│ ├─{containerd-shim}(30337)
|
||||
│ ├─{containerd-shim}(30338)
|
||||
│ ├─{containerd-shim}(30339)
|
||||
│ ├─{containerd-shim}(30340)
|
||||
│ ├─{containerd-shim}(30703)
|
||||
│ └─{containerd-shim}(30909)
|
||||
├─containerd-shim(30447)─┬─nginx(30469)─┬─nginx(30546)
|
||||
│ │ ├─nginx(30547)
|
||||
│ │ ├─nginx(30548)
|
||||
│ │ └─nginx(30549)
|
||||
│ ├─{containerd-shim}(30448)
|
||||
│ ├─{containerd-shim}(30449)
|
||||
│ ├─{containerd-shim}(30450)
|
||||
│ ├─{containerd-shim}(30451)
|
||||
│ ├─{containerd-shim}(30452)
|
||||
│ ├─{containerd-shim}(30453)
|
||||
│ ├─{containerd-shim}(30454)
|
||||
│ ├─{containerd-shim}(30455)
|
||||
│ ├─{containerd-shim}(30456)
|
||||
│ └─{containerd-shim}(30705)
|
||||
├─containerd-shim(30566)─┬─nginx(30587)─┬─nginx(30662)
|
||||
│ │ ├─nginx(30663)
|
||||
│ │ ├─nginx(30664)
|
||||
│ │ └─nginx(30665)
|
||||
│ ├─{containerd-shim}(30567)
|
||||
│ ├─{containerd-shim}(30568)
|
||||
│ ├─{containerd-shim}(30569)
|
||||
│ ├─{containerd-shim}(30570)
|
||||
│ ├─{containerd-shim}(30571)
|
||||
│ ├─{containerd-shim}(30572)
|
||||
│ ├─{containerd-shim}(30573)
|
||||
│ ├─{containerd-shim}(30574)
|
||||
│ ├─{containerd-shim}(30593)
|
||||
│ ├─{containerd-shim}(30706)
|
||||
│ └─{containerd-shim}(30780)
|
||||
├─crond(801)
|
||||
├─dbus-broker-lau(719)───dbus-broker(723)
|
||||
├─dockerd(29156)─┬─docker-proxy(30381)─┬─{docker-proxy}(30382)
|
||||
│ │ ├─{docker-proxy}(30383)
|
||||
│ │ ├─{docker-proxy}(30384)
|
||||
│ │ ├─{docker-proxy}(30385)
|
||||
│ │ ├─{docker-proxy}(30386)
|
||||
│ │ └─{docker-proxy}(30388)
|
||||
│ ├─docker-proxy(30387)─┬─{docker-proxy}(30389)
|
||||
│ │ ├─{docker-proxy}(30390)
|
||||
│ │ ├─{docker-proxy}(30391)
|
||||
│ │ ├─{docker-proxy}(30392)
|
||||
│ │ ├─{docker-proxy}(30393)
|
||||
│ │ ├─{docker-proxy}(30394)
|
||||
│ │ ├─{docker-proxy}(30395)
|
||||
│ │ └─{docker-proxy}(30396)
|
||||
│ ├─docker-proxy(30497)─┬─{docker-proxy}(30498)
|
||||
│ │ ├─{docker-proxy}(30499)
|
||||
│ │ ├─{docker-proxy}(30500)
|
||||
│ │ ├─{docker-proxy}(30501)
|
||||
│ │ ├─{docker-proxy}(30502)
|
||||
│ │ ├─{docker-proxy}(30503)
|
||||
│ │ ├─{docker-proxy}(30504)
|
||||
│ │ └─{docker-proxy}(30505)
|
||||
│ ├─docker-proxy(30506)─┬─{docker-proxy}(30507)
|
||||
│ │ ├─{docker-proxy}(30508)
|
||||
│ │ ├─{docker-proxy}(30509)
|
||||
│ │ ├─{docker-proxy}(30510)
|
||||
│ │ ├─{docker-proxy}(30511)
|
||||
│ │ ├─{docker-proxy}(30512)
|
||||
│ │ └─{docker-proxy}(30513)
|
||||
│ ├─docker-proxy(30616)─┬─{docker-proxy}(30617)
|
||||
│ │ ├─{docker-proxy}(30618)
|
||||
│ │ ├─{docker-proxy}(30619)
|
||||
│ │ ├─{docker-proxy}(30620)
|
||||
│ │ ├─{docker-proxy}(30621)
|
||||
│ │ ├─{docker-proxy}(30622)
|
||||
│ │ ├─{docker-proxy}(30624)
|
||||
│ │ └─{docker-proxy}(30625)
|
||||
│ ├─docker-proxy(30623)─┬─{docker-proxy}(30626)
|
||||
│ │ ├─{docker-proxy}(30627)
|
||||
│ │ ├─{docker-proxy}(30628)
|
||||
│ │ ├─{docker-proxy}(30629)
|
||||
│ │ ├─{docker-proxy}(30630)
|
||||
│ │ ├─{docker-proxy}(30631)
|
||||
│ │ └─{docker-proxy}(30632)
|
||||
│ ├─{dockerd}(29157)
|
||||
│ ├─{dockerd}(29159)
|
||||
│ ├─{dockerd}(29161)
|
||||
│ ├─{dockerd}(29163)
|
||||
│ ├─{dockerd}(29407)
|
||||
│ ├─{dockerd}(29420)
|
||||
│ ├─{dockerd}(29430)
|
||||
│ ├─{dockerd}(29537)
|
||||
│ ├─{dockerd}(29711)
|
||||
│ ├─{dockerd}(29712)
|
||||
│ ├─{dockerd}(29823)
|
||||
│ ├─{dockerd}(29844)
|
||||
│ ├─{dockerd}(29845)
|
||||
│ ├─{dockerd}(30633)
|
||||
│ └─{dockerd}(30683)
|
||||
├─irqbalance(729)───{irqbalance}(738)
|
||||
├─lsmd(730)
|
||||
├─mcelog(734)
|
||||
├─polkitd(944)─┬─{polkitd}(975)
|
||||
│ ├─{polkitd}(976)
|
||||
│ ├─{polkitd}(979)
|
||||
│ ├─{polkitd}(980)
|
||||
│ ├─{polkitd}(981)
|
||||
│ ├─{polkitd}(982)
|
||||
│ └─{polkitd}(1004)
|
||||
├─rsyslogd(1063)─┬─{rsyslogd}(1095)
|
||||
│ └─{rsyslogd}(1096)
|
||||
├─sshd(786)─┬─sshd(1527)───sshd(1541)───bash(1542)───docker(30781)─┬─{docker}(30782)
|
||||
│ │ ├─{docker}(30783)
|
||||
│ │ ├─{docker}(30784)
|
||||
│ │ ├─{docker}(30785)
|
||||
│ │ ├─{docker}(30786)
|
||||
│ │ ├─{docker}(30787)
|
||||
│ │ ├─{docker}(30788)
|
||||
│ │ └─{docker}(30807)
|
||||
│ └─sshd(30928)───sshd(30932)───bash(30933)───pstree(31158)
|
||||
├─systemd(1532)───(sd-pam)(1534)
|
||||
├─systemd-journal(635)
|
||||
├─systemd-logind(739)
|
||||
├─systemd-udevd(648)
|
||||
└─tuned(791)─┬─{tuned}(1106)
|
||||
├─{tuned}(1137)
|
||||
└─{tuned}(1138)
|
||||
|
||||
[root@localhost ~]# ps aux | grep b42378a51c40
|
||||
root 30566 0.0 0.9 1237984 16524 ? Sl 18:42 0:00 /usr/bin/containerd-shim-runc-v2 -namespace moby -id b42378a51c402d7ffa408d331a61ebdefe1b920eb723cd343ebc8e5781bec03d -address /run/containerd/containerd.sock
|
||||
root 31171 0.0 0.1 3880 2048 pts/1 S+ 18:54 0:00 grep --color=auto b42378a51c40
|
||||
```
|
||||
|
||||
**在宿主机上查看容器的进程**
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker top nginx-1
|
||||
UID PID PPID C STIME TTY TIME CMD
|
||||
root 30353 30330 0 18:42 ? 00:00:00 nginx: master process nginx -g daemon off;
|
||||
101 30426 30353 0 18:42 ? 00:00:00 nginx: worker process
|
||||
101 30427 30353 0 18:42 ? 00:00:00 nginx: worker process
|
||||
101 30428 30353 0 18:42 ? 00:00:00 nginx: worker process
|
||||
101 30429 30353 0 18:42 ? 00:00:00 nginx: worker process
|
||||
root 30801 30330 0 18:46 pts/0 00:00:00 bash
|
||||
```
|
||||
|
||||
首先,可以看到容器内的进程在宿主机上的 PID。容器内的进程只能看到自己命名空间中的进程,而无法看到宿主机或其他容器的进程
|
||||
|
||||
所以说明docker采用PID Namespace技术将容器内部的进程与宿主机的进程进行了隔离
|
||||
|
||||
并且,容器内部的进程和宿主机上的进程还存在一定的对应或者映射关系
|
||||
|
||||
1. **独立的 PID 命名空间**:
|
||||
- 每个 Docker 容器都有自己独立的 PID 命名空间。
|
||||
- 容器内的进程 PID 从 1 开始编号,与宿主机上的 PID 是相互独立的。
|
||||
2. **PID 映射**:
|
||||
- 容器内的进程 PID 与宿主机上的进程 PID 之间是有映射关系的。
|
||||
3. **PID 可见性**:
|
||||
- 容器内的进程只能看到容器内部的 PID。
|
||||
- 宿主机上的进程可以看到容器内部的 PID,但容器内的进程无法看到宿主机上的 PID。
|
||||
4. **PID 隔离**:
|
||||
- 容器内的进程无法访问或影响宿主机上的其他进程。
|
||||
- 宿主机上的进程可以访问和管理容器内的进程。
|
||||
|
||||
##### 6.1.4 Net Namespace
|
||||
|
||||
每一个容器都类似于虚拟机一样有自己的网卡、监听端口、TCP/IP协议栈等,Docker使用network namespace启动一个vethX接口,这样容器将拥有它自己的桥接IP地址,通常是docker0,而docker0实质就是linux的虚拟网桥。
|
||||
|
||||
查看容器内部的IP网络信息,发现有一个eth0的网卡
|
||||
|
||||
```bash
|
||||
root@d34a012dcebc:/# ifconfig
|
||||
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
|
||||
ether ce:f2:f5:63:47:16 txqueuelen 0 (Ethernet)
|
||||
RX packets 4713 bytes 10994487 (10.4 MiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 3888 bytes 212050 (207.0 KiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
|
||||
inet 127.0.0.1 netmask 255.0.0.0
|
||||
inet6 ::1 prefixlen 128 scopeid 0x10<host>
|
||||
loop txqueuelen 1000 (Local Loopback)
|
||||
RX packets 0 bytes 0 (0.0 B)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 0 bytes 0 (0.0 B)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
```
|
||||
|
||||
而我们的宿主机上的网卡中,多了个docker0的虚拟网桥,这样以来,通过Net Namespace将容器的网络与宿主机的网络进行隔离,并且通过虚拟网桥docker0与容器进行网络通信
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# ifconfig
|
||||
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
|
||||
inet6 fe80::38a5:cdff:fe6b:7dbc prefixlen 64 scopeid 0x20<link>
|
||||
ether 3a:a5:cd:6b:7d:bc txqueuelen 0 (Ethernet)
|
||||
RX packets 5820 bytes 11520579 (10.9 MiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 9483 bytes 11508761 (10.9 MiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 192.168.88.10 netmask 255.255.255.0 broadcast 192.168.88.255
|
||||
inet6 fe80::20c:29ff:fe26:8384 prefixlen 64 scopeid 0x20<link>
|
||||
ether 00:0c:29:26:83:84 txqueuelen 1000 (Ethernet)
|
||||
RX packets 235433 bytes 340010957 (324.2 MiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 54812 bytes 14709198 (14.0 MiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
|
||||
inet 127.0.0.1 netmask 255.0.0.0
|
||||
inet6 ::1 prefixlen 128 scopeid 0x10<host>
|
||||
loop txqueuelen 1000 (Local Loopback)
|
||||
RX packets 0 bytes 0 (0.0 B)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 0 bytes 0 (0.0 B)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
veth51c3173: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet6 fe80::d8fa:18ff:fe0f:d176 prefixlen 64 scopeid 0x20<link>
|
||||
ether da:fa:18:0f:d1:76 txqueuelen 0 (Ethernet)
|
||||
RX packets 3888 bytes 212050 (207.0 KiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 4714 bytes 10994557 (10.4 MiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
veth813b530: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet6 fe80::e498:2eff:fe08:2c5b prefixlen 64 scopeid 0x20<link>
|
||||
ether e6:98:2e:08:2c:5b txqueuelen 0 (Ethernet)
|
||||
RX packets 3 bytes 126 (126.0 B)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 15 bytes 1118 (1.0 KiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
vethc11c399: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet6 fe80::a482:dfff:fe74:dec7 prefixlen 64 scopeid 0x20<link>
|
||||
ether a6:82:df:74:de:c7 txqueuelen 0 (Ethernet)
|
||||
RX packets 3 bytes 126 (126.0 B)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 18 bytes 1244 (1.2 KiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
```
|
||||
|
||||
- **`docker0` 网桥**:
|
||||
- 它是 Docker 默认创建的一个虚拟网桥,用于管理容器的网络通信。
|
||||
- 它为连接到它的容器提供了一个内部网络环境,允许容器之间通过这个网桥进行通信。
|
||||
- **`veth3ad3c5b` 接口**:
|
||||
- 这是一个虚拟以太网接口,用于连接容器和宿主机的网络。
|
||||
- 它的一端连接到 `docker0` 网桥,另一端连接到容器的网络命名空间。
|
||||
- 当容器启动时,Docker 会自动创建这样的 veth pair,并将一端连接到 `docker0`,另一端连接到容器的网络命名空间。
|
||||
|
||||
逻辑图
|
||||
|
||||

|
||||
|
||||
##### 6.1.5 User Namespace
|
||||
|
||||
各个容器内可能会出现重名的用户和用户组名称,或重复的用户UID或者GID,那么怎么隔离各个容器内的用户空间呢?
|
||||
|
||||
User Namespace允许在宿主机的各个容器空间内创建相同的用户名以及相同的uid和gid,只是此用户的有效范围仅仅是当前的容器内,不能访问另外一个容器内的文件系统,即相互隔离、互不影响、永不相见
|
||||
|
||||
#### 6.2 Linux control groups
|
||||
|
||||
在一个容器内部,如果不对其做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配限制,比如cpu、内存等,Linux Cgroups的全称是Linux control Groups,它最重要的作用就是限制一个进程组能够使用的资源上线,包括cpu、内存、磁盘、网络等等。
|
||||
|
||||
- 验证系统内核层已经默认开启cgroup功能
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# cat /boot/config-5.14.0-427.13.1.el9_4.x86_64 | grep cgroup -i
|
||||
CONFIG_CGROUPS=y
|
||||
# CONFIG_CGROUP_FAVOR_DYNMODS is not set
|
||||
CONFIG_BLK_CGROUP=y
|
||||
CONFIG_CGROUP_WRITEBACK=y
|
||||
CONFIG_CGROUP_SCHED=y
|
||||
CONFIG_CGROUP_PIDS=y
|
||||
CONFIG_CGROUP_RDMA=y
|
||||
CONFIG_CGROUP_FREEZER=y
|
||||
CONFIG_CGROUP_HUGETLB=y
|
||||
CONFIG_CGROUP_DEVICE=y
|
||||
CONFIG_CGROUP_CPUACCT=y
|
||||
CONFIG_CGROUP_PERF=y
|
||||
CONFIG_CGROUP_BPF=y
|
||||
CONFIG_CGROUP_MISC=y
|
||||
# CONFIG_CGROUP_DEBUG is not set
|
||||
CONFIG_SOCK_CGROUP_DATA=y
|
||||
CONFIG_BLK_CGROUP_RWSTAT=y
|
||||
CONFIG_BLK_CGROUP_IOLATENCY=y
|
||||
CONFIG_BLK_CGROUP_FC_APPID=y
|
||||
# CONFIG_BLK_CGROUP_IOCOST is not set
|
||||
# CONFIG_BLK_CGROUP_IOPRIO is not set
|
||||
# CONFIG_BFQ_CGROUP_DEBUG is not set
|
||||
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
|
||||
CONFIG_NET_CLS_CGROUP=y
|
||||
CONFIG_CGROUP_NET_PRIO=y
|
||||
CONFIG_CGROUP_NET_CLASSID=y
|
||||
# CONFIG_DEBUG_CGROUP_REF is not set
|
||||
```
|
||||
|
||||
- 关于内存的模块
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# cat /boot/config-3.10.0-957.el7.x86_64 | grep mem -i | grep cg -i
|
||||
CONFIG_MEMCG=y
|
||||
CONFIG_MEMCG_SWAP=y
|
||||
CONFIG_MEMCG_SWAP_ENABLED=y
|
||||
CONFIG_MEMCG_KMEM=y
|
||||
```
|
||||
|
||||
扩展阅读:
|
||||
|
||||
https://blog.csdn.net/qyf158236/article/details/110475457
|
||||
|
||||
##### 6.2.1 Docker 中的 cgroups 资源限制
|
||||
|
||||
###### 6.2.1.1 **CPU 资源限制**
|
||||
|
||||
Docker 提供了多种方式来限制容器的 CPU 使用:
|
||||
|
||||
- **`--cpus`**:限制容器可以使用的 CPU 核心数量。例如,`--cpus="1.5"` 表示容器最多可以使用 1.5 个 CPU。
|
||||
- **`--cpu-shares`**:设置容器的 CPU 使用权重。默认值为 1024,值越高,分配的 CPU 时间片越多。
|
||||
- **`--cpu-period` 和 `--cpu-quota`**:更细粒度地控制 CPU 时间片。`--cpu-period` 设置 CPU 时间片的周期(单位为微秒),`--cpu-quota` 设置每个周期内容器可以使用的 CPU 时间。
|
||||
|
||||
###### 6.2.1.2 **内存资源限制**
|
||||
|
||||
Docker 可以通过以下参数限制容器的内存使用:
|
||||
|
||||
- **`-m` 或 `--memory`**:限制容器的物理内存使用量。例如,`-m 512m` 表示限制容器使用 512MB 的物理内存。
|
||||
- **`--memory-swap`**:限制容器的总内存使用量(物理内存 + 交换空间)。例如,`--memory-swap=1g` 表示容器可以使用 1GB 的总内存。
|
||||
|
||||
###### 6.2.1.3 **磁盘 I/O 资源限制**
|
||||
|
||||
Docker 可以限制容器的磁盘 I/O 使用:
|
||||
|
||||
- **`--blkio-weight`**:设置容器的块设备 I/O 权重,范围为 10 到 1000。
|
||||
- **`--device-read-bps` 和 `--device-write-bps`**:限制特定设备的读写速率。例如,`--device-read-bps /dev/sda:1mb` 表示限制容器对 `/dev/sda` 的读取速率为 1MB/s。
|
||||
|
||||
##### 6.2.2 查看和管理 cgroups 资源限制
|
||||
|
||||
- **查看 cgroups 配置**:可以通过访问 `/sys/fs/cgroup` 目录来查看容器的 cgroups 配置。例如,`/sys/fs/cgroup/cpu/docker/<container_id>` 目录下包含了容器的 CPU 资源限制文件。
|
||||
- **动态调整资源限制**:在容器运行时,可以通过修改 cgroups 文件的内容来动态调整资源限制。
|
||||
|
||||
##### 6.2.3 使用压缩工具测试
|
||||
|
||||
```plain
|
||||
[root@bogon ~]# docker pull lorel/docker-stress-ng
|
||||
Using default tag: latest
|
||||
latest: Pulling from lorel/docker-stress-ng
|
||||
c52e3ed763ff: Pull complete
|
||||
a3ed95caeb02: Pull complete
|
||||
7f831269c70e: Pull complete
|
||||
Digest: sha256:c8776b750869e274b340f8e8eb9a7d8fb2472edd5b25ff5b7d55728bca681322
|
||||
Status: Downloaded newer image for lorel/docker-stress-ng:latest
|
||||
```
|
||||
|
||||
###### 6.2.3.1 测试CPU
|
||||
|
||||
不限制cpu使用
|
||||
|
||||
```bash
|
||||
[root@bogon ~]# docker container run --name stress -it --rm lorel/docker-stress-ng:latest --cpu 4
|
||||
stress-ng: info: [1] defaulting to a 86400 second run per stressor
|
||||
stress-ng: info: [1] dispatching hogs: 8 cpu
|
||||
[root@bogon ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
92b0b8d916c1 stress 101.54% 15.81MiB / 983.3MiB 1.61% 648B / 0B 0B / 0B 9
|
||||
[root@bogon ~]# top
|
||||
top - 19:15:49 up 2 days, 2:38, 2 users, load average: 7.02, 3.00, 1.15
|
||||
Tasks: 131 total, 10 running, 121 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu(s): 99.7 us, 0.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
KiB Mem : 1006892 total, 100680 free, 320704 used, 585508 buff/cache
|
||||
KiB Swap: 2097148 total, 2096628 free, 520 used. 422732 avail Mem
|
||||
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
|
||||
40035 root 20 0 6908 4180 252 R 12.6 0.4 0:12.79 stress-ng-cpu
|
||||
40037 root 20 0 6908 4180 252 R 12.6 0.4 0:12.78 stress-ng-cpu
|
||||
40038 root 20 0 6908 2136 252 R 12.6 0.2 0:12.78 stress-ng-cpu
|
||||
40040 root 20 0 6908 2136 252 R 12.6 0.2 0:12.78 stress-ng-cpu
|
||||
40036 root 20 0 6908 2136 252 R 12.3 0.2 0:12.77 stress-ng-cpu
|
||||
40039 root 20 0 6908 2136 252 R 12.3 0.2 0:12.78 stress-ng-cpu
|
||||
40041 root 20 0 6908 4180 252 R 12.3 0.4 0:12.77 stress-ng-cpu
|
||||
40042 root 20 0 6908 2136 252 R 12.3 0.2 0:12.77 stress-ng-cpu
|
||||
1 root 20 0 128484 7208 4196 S 0.0 0.7 0:10.12 systemd
|
||||
```
|
||||
|
||||
可以看到,cpu使用已经满了
|
||||
|
||||
重新启动容器加入CPU限制参数
|
||||
|
||||
```bash
|
||||
[root@bogon ~]# docker container run --name stress --cpus=0.5 -it --rm lorel/docker-stress-ng:latest --cpu 8
|
||||
stress-ng: info: [1] defaulting to a 86400 second run per stressor
|
||||
stress-ng: info: [1] dispatching hogs: 8 cpu
|
||||
[root@bogon ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
845220ef9982 stress 51.57% 20.05MiB / 983.3MiB 2.04% 648B / 0B 0B / 0B 9
|
||||
```
|
||||
|
||||
### 7. 容器规范
|
||||
|
||||
#### 7.1 容器技术及其标准化组织 OCI
|
||||
|
||||
容器技术是一种轻量级的虚拟化技术,用于隔离应用程序及其依赖项,使其能够在不同的环境中一致地运行。除了 Docker 之外,还有其他多种容器运行时和工具,例如 CoreOS 的 rkt、阿里的 Pouch 和红帽的 Podman。为了确保容器生态系统的标准性和可持续发展,Linux 基金会、Docker、微软、红帽、谷歌和 IBM 等公司在 2015 年 6 月共同成立了 **Open Container Initiative (OCI)** 组织。
|
||||
|
||||
##### 7.1.1 **OCI 的目标**
|
||||
|
||||
OCI 的主要目标是制定开放的容器规范,以确保不同容器技术之间的可移植性和互操作性。目前,OCI 已经发布了两个核心规范:
|
||||
|
||||
1. **Runtime Spec**:定义了容器运行时的规范,包括容器的生命周期管理、资源隔离和安全等。
|
||||
2. **Image Format Spec**:定义了容器镜像的格式和元数据,确保镜像可以在不同的容器运行时之间共享和运行。
|
||||
|
||||
通过遵循这些规范,不同的容器运行时和工具可以实现互操作性,从而推动容器技术的标准化和健康发展。
|
||||
|
||||
##### 7.1.2 主流容器运行时
|
||||
|
||||
容器运行时是真正运行容器的地方,它需要与操作系统的内核紧密合作,为容器提供隔离的运行环境。以下是目前主流的三种容器运行时:
|
||||
|
||||
###### 7.1.2.1 **LXC (Linux Containers)**
|
||||
|
||||
- **简介**:LXC 是 Linux 上早期的容器运行时,它利用 Linux 内核的 Namespace 和 Cgroups 技术来实现进程隔离和资源管理。
|
||||
- **特点**:
|
||||
- 提供了完整的 Linux 系统环境,支持多种 Linux 发行版。
|
||||
- 早期 Docker 也曾使用 LXC 作为其默认的运行时。
|
||||
- **适用场景**:适用于需要完整 Linux 系统环境的容器化应用。
|
||||
|
||||
###### 7.1.2.2 **Runc**
|
||||
|
||||
- **简介**:Runc 是目前 Docker 默认的容器运行时,它是一个轻量级的命令行工具,用于运行和管理容器。
|
||||
- **特点**:
|
||||
- 完全遵循 OCI 的 Runtime Spec 规范,确保与 OCI 标准的兼容性。
|
||||
- 由于其轻量级和高性能的特点,Runc 已经成为许多容器运行时的底层实现。
|
||||
- **适用场景**:适用于需要高性能和轻量级容器运行环境的场景。
|
||||
|
||||
###### 7.1.2.3 **Rkt (Rocket)**
|
||||
|
||||
- **简介**:Rkt 是由 CoreOS 开发的容器运行时,旨在提供一个安全、可靠且符合 OCI 规范的容器运行环境。
|
||||
- **特点**:
|
||||
- 与 Docker 不同,Rkt 本身是一个独立的容器运行时,不依赖 Docker 的守护进程。
|
||||
- 提供了更好的安全性和隔离性,例如通过 AppArmor 和 SELinux 等安全机制。
|
||||
- **适用场景**:适用于对安全性要求较高的容器化应用。
|
||||
|
||||
容器技术的发展离不开标准化的推动。OCI 通过制定 Runtime Spec 和 Image Format Spec,为容器运行时和工具提供了统一的标准,确保了不同容器技术之间的互操作性和可移植性。目前主流的容器运行时(如 LXC、Runc 和 Rkt)都遵循这些规范,从而推动了容器技术的广泛应用和发展。
|
||||
|
||||
### 8. docker info信息
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker info
|
||||
Client:
|
||||
Context: default
|
||||
Debug Mode: false
|
||||
Plugins:
|
||||
app: Docker App (Docker Inc., v0.9.1-beta3)
|
||||
buildx: Build with BuildKit (Docker Inc., v0.5.1-docker)
|
||||
scan: Docker Scan (Docker Inc.)
|
||||
|
||||
Server:
|
||||
Containers: 2 # 当前主机运行容器总数
|
||||
Running: 1 # 有几个容器是正在运行的
|
||||
Paused: 0 # 有几个容器是暂停的
|
||||
Stopped: 1 # 有几个容器是停止的
|
||||
Images: 1 # 当前服务器的镜像数
|
||||
Server Version: 20.10.6 # 服务端版本
|
||||
Storage Driver: overlay2 # 正在使用的存储引擎
|
||||
Backing Filesystem: xfs # 后端文件系统,即服务器的磁盘文件系统
|
||||
Supports d_type: true # 是否支持d_type
|
||||
Native Overlay Diff: true # 是否支持差异数据存储
|
||||
userxattr: false
|
||||
Logging Driver: json-file # 日志文件类型
|
||||
Cgroup Driver: cgroupfs # cgroups类型
|
||||
Cgroup Version: 1
|
||||
Plugins: # 插件
|
||||
Volume: local # 卷
|
||||
Network: bridge host ipvlan macvlan null overlay
|
||||
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
|
||||
Swarm: inactive # 是否支持swarm
|
||||
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
|
||||
Default Runtime: runc # 默认的runtime
|
||||
Init Binary: docker-init # 初始化容器的守护进程
|
||||
containerd version: d71fcd7d8303cbf684402823e425e9dd2e99285d
|
||||
runc version: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
|
||||
init version: de40ad0
|
||||
Security Options: # 安全选项
|
||||
seccomp
|
||||
Profile: default
|
||||
Kernel Version: 3.10.0-693.el7.x86_64 # 宿主机内核版本
|
||||
Operating System: CentOS Linux 7 (Core) # 宿主机操作系统
|
||||
OSType: linux # 宿主机操作系统类型
|
||||
Architecture: x86_64 # 宿主机架构
|
||||
CPUs: 1 # 宿主机cpu数量
|
||||
Total Memory: 1.781GiB # 宿主机总内存
|
||||
Name: docker-server # 宿主机主机名
|
||||
ID: ARN5:ESPO:FEZ4:KDZ6:RWGG:WQ3X:SIXN:3FVG:ATXH:JAXA:ENGH:RAVE
|
||||
Docker Root Dir: /var/lib/docker # 宿主机数据保存目录
|
||||
Debug Mode: false
|
||||
Registry: https://index.docker.io/v1/ # 镜像仓库
|
||||
Labels:
|
||||
Experimental: false # 是否是测试版
|
||||
Insecure Registries:
|
||||
127.0.0.0/8
|
||||
Live Restore Enabled: false # 是否开启活动容器(重启不关闭容器)
|
||||
```
|
||||
|
||||
### 9. docker 存储引擎
|
||||
|
||||
Docker 的存储引擎是 Docker 平台中用于管理容器和镜像数据的核心组件。它负责容器的文件系统、网络配置、权限管理等,以及其他与容器运行相关的任务。以下是对 Docker 存储引擎的详细介绍:
|
||||
|
||||
#### 9.1 **核心概念及工作原理**
|
||||
|
||||
Docker 存储引擎的核心思想是“层”的概念。镜像是由多个只读层组成的,而容器则在镜像的基础上添加了一个可读写的层。这种分层架构使得镜像的复用和部署变得非常方便,同时减少了容器的体积。
|
||||
|
||||
Docker 使用联合文件系统(Union File System)来管理容器的文件系统。联合文件系统允许将多个目录(或文件系统)合并为一个统一的文件系统视图。Docker 的存储引擎通过这种机制,将镜像层和容器层合并在一起,使得容器能够看到一个完整的文件系统。
|
||||
|
||||
Docker 支持多种存储引擎,每种存储引擎都有其特点和适用场景。以下是一些常见的存储引擎:
|
||||
|
||||
**AUFS(Another Union File System)**
|
||||
|
||||
- **特点**:AUFS 是一种文件级的存储驱动,允许多个目录共享相同的文件系统层次结构。它通过联合挂载技术将多个目录挂载到一个单一的文件系统上。
|
||||
- **适用场景**:AUFS 曾是 Docker 早期版本的默认存储驱动,但在较新的 Docker 版本中已被 Overlay2 替代。
|
||||
|
||||
**OverlayFS**
|
||||
|
||||
- **特点**:OverlayFS 是一种更现代的联合文件系统,从 Linux 内核 3.18 开始支持。它将文件系统简化为两层:一个只读的下层(lowerdir)和一个可读写的上层(upperdir),统一后的视图称为合并层(merged)。
|
||||
- **优势**:OverlayFS 支持页缓存共享,多个容器如果读取相同层的同一个文件,可以共享页缓存,从而提高内存利用率。此外,OverlayFS 在性能和稳定性方面表现更好,是目前 Docker 的默认存储驱动。
|
||||
|
||||
#### 9.2 Docker 的 Overlay2 存储驱动介绍
|
||||
|
||||
1. **什么是 Overlay2?**
|
||||
|
||||
Overlay2 是 Docker 中的一种存储驱动,用于管理容器和镜像的文件系统。它是 OverlayFS 的改进版本,解决了早期 Overlay 驱动可能遇到的 inode 耗尽问题。Overlay2 使用联合文件系统(Union File System)技术,将多个文件系统层合并为一个统一的文件系统视图,从而实现高效的容器文件系统管理。
|
||||
|
||||
2. **Overlay2 的工作原理**
|
||||
|
||||
Overlay2 通过以下三个主要目录来管理文件系统:
|
||||
|
||||
- **`LowerDir`**:只读层,包含基础镜像的文件系统。可以有多个只读层,每层都是独立的。
|
||||
- **`UpperDir`**:读写层,用于存储容器运行时的文件系统变更(即 diff 层)。
|
||||
- **`MergedDir`**:联合挂载后的视图,容器看到的完整文件系统。它将 `LowerDir` 和 `UpperDir` 合并为一个统一的文件系统视图。
|
||||
- **`WorkDir`**:工作目录,用于联合挂载的内部操作,挂载后内容被清空。
|
||||
|
||||
当启动一个容器时,Overlay2 会将镜像层(`LowerDir`)和容器层(`UpperDir`)联合挂载到 `MergedDir`,容器通过这个目录看到完整的文件系统。
|
Before Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 172 KiB |
@@ -1,293 +0,0 @@
|
||||
# 02.Docker镜像管理
|
||||
|
||||
## 02.Docker镜像管理
|
||||
|
||||
### 1. 搜索镜像
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker search centos
|
||||
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
|
||||
centos The official build of CentOS. 6584 [OK]
|
||||
ansible/centos7-ansible Ansible on Centos7 134 [OK]
|
||||
consol/centos-xfce-vnc Centos container with "headless" VNC session… 129 [OK]
|
||||
jdeathe/centos-ssh OpenSSH / Supervisor / EPEL/IUS/SCL Repos - … 118 [OK]
|
||||
centos/systemd systemd enabled base container. 99 [OK]
|
||||
imagine10255/centos6-lnmp-php56 centos6-lnmp-php56 58 [OK]
|
||||
tutum/centos Simple CentOS docker image with SSH access 48
|
||||
kinogmt/centos-ssh CentOS with SSH 29 [OK]
|
||||
pivotaldata/centos-gpdb-dev CentOS image for GPDB development. Tag names… 13
|
||||
guyton/centos6 From official centos6 container with full up… 10 [OK]
|
||||
centos/tools Docker image that has systems administration… 7 [OK]
|
||||
drecom/centos-ruby centos ruby 6 [OK]
|
||||
pivotaldata/centos Base centos, freshened up a little with a Do… 5
|
||||
pivotaldata/centos-gcc-toolchain CentOS with a toolchain, but unaffiliated wi… 3
|
||||
darksheer/centos Base Centos Image -- Updated hourly 3 [OK]
|
||||
mamohr/centos-java Oracle Java 8 Docker image based on Centos 7 3 [OK]
|
||||
pivotaldata/centos-mingw Using the mingw toolchain to cross-compile t… 3
|
||||
miko2u/centos6 CentOS6 日本語環境 2 [OK]
|
||||
indigo/centos-maven Vanilla CentOS 7 with Oracle Java Developmen… 2 [OK]
|
||||
amd64/centos The official build of CentOS. 2
|
||||
dokken/centos-7 CentOS 7 image for kitchen-dokken 2
|
||||
pivotaldata/centos6.8-dev CentosOS 6.8 image for GPDB development 1
|
||||
blacklabelops/centos CentOS Base Image! Built and Updates Daily! 1 [OK]
|
||||
smartentry/centos centos with smartentry 0 [OK]
|
||||
```
|
||||
|
||||
可以看到返回了很多包含关键字的镜像,其中包括镜像名字、描述、点赞数(表示该镜像的受欢迎程度)、是否官方创建、是否自动创建。默认输出结果按照星级评价进行排序。
|
||||
|
||||

|
||||
|
||||
### 2. 下载镜像
|
||||
|
||||
可以使用docker pull命令直接下载镜像,语法为:
|
||||
|
||||
```bash
|
||||
docker pull NAME:TAG
|
||||
```
|
||||
|
||||
其中,NAME是镜像名称,TAG是镜像的标签(往往用来是表示版本信息),通常情况下,描述一个镜像需要包括名称+标签,如果不指定标签,标签的值默认为latest。
|
||||
|
||||
- 下载nginx、centos、hello-world镜像
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker pull nginx
|
||||
[root@docker-server ~]# docker pull centos
|
||||
[root@docker-server ~]# docker pull hello-world
|
||||
```
|
||||
|
||||
### 3. 查看镜像信息
|
||||
|
||||
#### 3.1 docker images
|
||||
|
||||
- 列出本地所有镜像
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
nginx latest d1a364dc548d 2 weeks ago 133MB
|
||||
hello-world latest d1165f221234 3 months ago 13.3kB
|
||||
centos latest 300e315adb2f 6 months ago 209MB
|
||||
```
|
||||
|
||||
在列出的信息中可以看到几个字段:
|
||||
|
||||
- REPOSITORY:镜像仓库名称
|
||||
- TAG:镜像的标签信息
|
||||
- 镜像ID:唯一用来标识镜像,如果两个镜像的ID相同,说明他们实际上指向了同一个镜像,只是具有不同标签名称而已
|
||||
- CREATED:创建时间,说明镜像的最后更新时间
|
||||
- SIZE:镜像大小,优秀的镜像往往体积都较小
|
||||
|
||||
#### 3.2 docker tag
|
||||
|
||||
为了方便在后续工作中使用特定镜像,可以使用docker tag命令来为本地镜像任意添加新的标签
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker tag nginx:latest mynginx:latest
|
||||
[root@localhost ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
mynginx latest 53a18edff809 6 weeks ago 192MB
|
||||
nginx latest 53a18edff809 6 weeks ago 192MB
|
||||
hello-world latest 74cc54e27dc4 2 months ago 10.1kB
|
||||
registry.cn-guangzhou.aliyuncs.com/welldene/games rpg_game 6a963645d135 22 months ago 310MB
|
||||
```
|
||||
|
||||
#### 3.3 docker inspect
|
||||
|
||||
可以使用docker inspect命令获取该镜像的详细信息
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker inspect nginx:latest
|
||||
[
|
||||
{
|
||||
"Id": "sha256:53a18edff8091d5faff1e42b4d885bc5f0f897873b0b8f0ace236cd5930819b0",
|
||||
"RepoTags": [
|
||||
"mynginx:latest",
|
||||
"nginx:latest"
|
||||
],
|
||||
"RepoDigests": [
|
||||
"nginx@sha256:124b44bfc9ccd1f3cedf4b592d4d1e8bddb78b51ec2ed5056c52d3692baebc19"
|
||||
],
|
||||
"Parent": "",
|
||||
"Comment": "buildkit.dockerfile.v0",
|
||||
"Created": "2025-02-05T21:27:16Z",
|
||||
"DockerVersion": "",
|
||||
"Author": "",
|
||||
"Config": {
|
||||
"Hostname": "",
|
||||
"Domainname": "",
|
||||
"User": "",
|
||||
"AttachStdin": false,
|
||||
"AttachStdout": false,
|
||||
"AttachStderr": false,
|
||||
"ExposedPorts": {
|
||||
"80/tcp": {}
|
||||
},
|
||||
"Tty": false,
|
||||
"OpenStdin": false,
|
||||
"StdinOnce": false,
|
||||
"Env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"NGINX_VERSION=1.27.4",
|
||||
"NJS_VERSION=0.8.9",
|
||||
"NJS_RELEASE=1~bookworm",
|
||||
"PKG_RELEASE=1~bookworm",
|
||||
"DYNPKG_RELEASE=1~bookworm"
|
||||
],
|
||||
"Cmd": [
|
||||
"nginx",
|
||||
"-g",
|
||||
"daemon off;"
|
||||
],
|
||||
"Image": "",
|
||||
"Volumes": null,
|
||||
"WorkingDir": "",
|
||||
"Entrypoint": [
|
||||
"/docker-entrypoint.sh"
|
||||
],
|
||||
"OnBuild": null,
|
||||
"Labels": {
|
||||
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
|
||||
},
|
||||
"StopSignal": "SIGQUIT"
|
||||
},
|
||||
"Architecture": "amd64",
|
||||
"Os": "linux",
|
||||
"Size": 192004242,
|
||||
"GraphDriver": {
|
||||
"Data": {
|
||||
"LowerDir": "/var/lib/docker/overlay2/5698387a01cba2eedc0058d1ceec91493ae1c0a55352cc3d3ff2de257add6461/diff:/var/lib/docker/overlay2/3c85557f47aee3bc95423d00407b301ba73ee79e689a4acaa63b22aea3f64a29/diff:/var/lib/docker/overlay2/0dcd12c3dfdc4ca7e74cc05e6ec1ea701bff84acbdbe8c0ece63a1a5cbac85c4/diff:/var/lib/docker/overlay2/3105b0866bd0cba95bb28d3df6e7948853129aaadf4bdb6f162de3d61bb176cc/diff:/var/lib/docker/overlay2/f0864c0d8aa319dbf9e0f63d00b817bd9723badce3eef3879cc3114523ed6831/diff:/var/lib/docker/overlay2/44374136ef63aea5fd69dc1dc7d3c6238b4eca766845f15a869eb1479bd12387/diff",
|
||||
"MergedDir": "/var/lib/docker/overlay2/d658b597a569f714a0dab28da1ddf3b7b15001f1b1889dfc72f1ea8ed56d2cad/merged",
|
||||
"UpperDir": "/var/lib/docker/overlay2/d658b597a569f714a0dab28da1ddf3b7b15001f1b1889dfc72f1ea8ed56d2cad/diff",
|
||||
"WorkDir": "/var/lib/docker/overlay2/d658b597a569f714a0dab28da1ddf3b7b15001f1b1889dfc72f1ea8ed56d2cad/work"
|
||||
},
|
||||
"Name": "overlay2"
|
||||
},
|
||||
"RootFS": {
|
||||
"Type": "layers",
|
||||
"Layers": [
|
||||
"sha256:1287fbecdfcce6ee8cf2436e5b9e9d86a4648db2d91080377d499737f1b307f3",
|
||||
"sha256:135f786ad04647c6e58d9a2d4f6f87bd677ef6144ab24c81a6f5be7acc63fbc9",
|
||||
"sha256:ad2f08e39a9de1e12157c800bd31ba86f8cc222eedec11e8e072c3ba608d26fb",
|
||||
"sha256:d98dcc720ae098efb91563f0a9abe03de50b403f7aa6c6f0e1dfb8297aedb61f",
|
||||
"sha256:aa82c57cd9fe730130e35d42c6b26a4a9d3c858f61c23f63d53b703abf30adf8",
|
||||
"sha256:d26dc06ef910f67b1b2bcbcc6318e2e08881011abc7ad40fd859f38641ab105c",
|
||||
"sha256:03d9365bc5dc9ec8b2f032927d3d3ae10b840252c86cf245a63b713d50eaa2fd"
|
||||
]
|
||||
},
|
||||
"Metadata": {
|
||||
"LastTagTime": "2025-03-24T19:26:37.193805768+08:00"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### 3.4 docker history
|
||||
|
||||
镜像由多层组成,可以使用history子命令,该命令将列出各层创建信息
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker history nginx
|
||||
IMAGE CREATED CREATED BY SIZE COMMENT
|
||||
53a18edff809 6 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago STOPSIGNAL SIGQUIT 0B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago COPY 30-tune-worker-processes.sh /docker-ent… 4.62kB buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago COPY 20-envsubst-on-templates.sh /docker-ent… 3.02kB buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago COPY 15-local-resolvers.envsh /docker-entryp… 389B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago COPY 10-listen-on-ipv6-by-default.sh /docker… 2.12kB buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago COPY docker-entrypoint.sh / # buildkit 1.62kB buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago RUN /bin/sh -c set -x && groupadd --syst… 117MB buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago ENV DYNPKG_RELEASE=1~bookworm 0B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago ENV PKG_RELEASE=1~bookworm 0B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago ENV NJS_RELEASE=1~bookworm 0B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago ENV NJS_VERSION=0.8.9 0B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago ENV NGINX_VERSION=1.27.4 0B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago LABEL maintainer=NGINX Docker Maintainers <d… 0B buildkit.dockerfile.v0
|
||||
<missing> 6 weeks ago # debian.sh --arch 'amd64' out/ 'bookworm' '… 74.8MB debuerreotype 0.15
|
||||
```
|
||||
|
||||
### 4. 镜像导入导出
|
||||
|
||||
#### 4.1 导出
|
||||
|
||||
可以将镜像从本地导出为一个压缩文件,然后复制到其他服务器进行导入使用
|
||||
|
||||
- 导出方法一
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker save nginx:latest -o /opt/nginx.tar.gz
|
||||
[root@localhost ~]# ll /opt/nginx.tar.gz
|
||||
-rw-------. 1 root root 196167168 Mar 24 19:28 /opt/nginx.tar.gz
|
||||
```
|
||||
|
||||
- 导出方法二
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker save nginx:latest > /opt/nginx-1.tar.gz
|
||||
[root@localhost ll /opt/nginx-1.tar.gz
|
||||
-rw-r--r--. 1 root root 196167168 Mar 24 19:29 /opt/nginx-1.tar.gz
|
||||
```
|
||||
|
||||
#### 4.2 导入
|
||||
|
||||
先将导出的镜像发到需要导入的docker服务器中
|
||||
|
||||
- 导入方法一
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker load -i /opt/nginx.tar.gz
|
||||
Loaded image: centos:latest
|
||||
```
|
||||
|
||||
- 导出方法二
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker load < /opt/nginx.tar.gz
|
||||
Loaded image: centos:latest
|
||||
```
|
||||
|
||||
### 5. 删除镜像
|
||||
|
||||
- 使用镜像名称+标签
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
nginx latest d1a364dc548d 2 weeks ago 133MB
|
||||
hello-world latest d1165f221234 3 months ago 13.3kB
|
||||
centos latest 300e315adb2f 6 months ago 209MB
|
||||
mycentos latest 300e315adb2f 6 months ago 209MB
|
||||
[root@docker-server ~]# docker rmi nginx:latest
|
||||
Untagged: nginx:latest
|
||||
Untagged: nginx@sha256:6d75c99af15565a301e48297fa2d121e15d80ad526f8369c526324f0f7ccb750
|
||||
Deleted: sha256:d1a364dc548d5357f0da3268c888e1971bbdb957ee3f028fe7194f1d61c6fdee
|
||||
Deleted: sha256:fcc8faba78fe8a1f75025781c8fa1841079b75b54fce8408d039f73a48b7a81b
|
||||
Deleted: sha256:a476b265974ace4c857e3d88b358e848f126297a8249840c72d5f5ea1954a4bf
|
||||
Deleted: sha256:56722ee1ee7e73a5c6f96ea2959fa442fb4db9f044399bcd939bb0a6eb7919dc
|
||||
Deleted: sha256:c657df997c75f6c1a9c5cc683e8e34c6f29e5b4c1dee60b632d3477fd5fdd644
|
||||
Deleted: sha256:e9e1f772d2a8dbbeb6a4a4dcb4f0d07ff1c432bf94fac7a2db2216837bf9ec5b
|
||||
Deleted: sha256:02c055ef67f5904019f43a41ea5f099996d8e7633749b6e606c400526b2c4b33
|
||||
```
|
||||
|
||||
- 使用镜像id
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
hello-world latest d1165f221234 3 months ago 13.3kB
|
||||
centos latest 300e315adb2f 6 months ago 209MB
|
||||
mycentos latest 300e315adb2f 6 months ago 209MB
|
||||
[root@docker-server ~]# docker rmi 300e315adb2f
|
||||
Error response from daemon: conflict: unable to delete 300e315adb2f (must be forced) - image is referenced in multiple repositories
|
||||
[root@docker-server ~]# docker rmi 300e315adb2f -f
|
||||
Untagged: centos:latest
|
||||
Untagged: centos@sha256:5528e8b1b1719d34604c87e11dcd1c0a20bedf46e83b5632cdeac91b8c04efc1
|
||||
Untagged: mycentos:latest
|
||||
Deleted: sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55
|
||||
Deleted: sha256:2653d992f4ef2bfd27f94db643815aa567240c37732cae1405ad1c1309ee9859
|
||||
[root@docker-server ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
hello-world latest d1165f221234 3 months ago 13.3kB
|
||||
|
||||
```
|
Before Width: | Height: | Size: 135 KiB |
@@ -1,400 +0,0 @@
|
||||
# 03.Docker容器管理
|
||||
|
||||
## 03.Docker容器管理
|
||||
|
||||
### 1. docker容器管理
|
||||
|
||||
### 2. 创建容器
|
||||
|
||||
#### 2.1 docker create
|
||||
|
||||
docker create命令新建的容器处于停滞状态,可以使用docker start命令来启动它
|
||||
|
||||
| 选项 | 说明 |
|
||||
| ------------- | ------------------------------------------------------------ |
|
||||
| -d | 是否在后台运行容器,默认为否 |
|
||||
| -i | 保持标准输入打开 |
|
||||
| -P | 通过NAT机制将容器标记暴露的端口自动映射到本地主机的临时端口 |
|
||||
| -p | 指定如何映射到本地主机端口 |
|
||||
| -t | 分配一个终端 |
|
||||
| -v | 挂载主机上的文件卷到容器内 |
|
||||
| --rm | 容器退出后是否自动删除,不能跟-d同时使用 |
|
||||
| -e | 指定容器内的环境变量 |
|
||||
| -h | 指定容器内的主机名 |
|
||||
| --name | 指定容器的别名 |
|
||||
| --cpu-shares | 允许容器使用cpu资源的相对权重,默认一个容器能用满一个核的cpu |
|
||||
| --cpuset-cpus | 限制容器能使用哪些cpu核心 |
|
||||
| -m | 限制容器内使用的内存,单位可以是b、k、m、g |
|
||||
|
||||
```
|
||||
docker create -it --name mycontainer mycentos bash
|
||||
docker start mycontainer
|
||||
```
|
||||
|
||||
#### 2.2 docker run
|
||||
|
||||
除了创建容器后通过start命令来启动也可以通过docker run直接新建并启动容器。
|
||||
|
||||
- 启动一个容器
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker run -it centos:latest bash
|
||||
[root@4abaf8a399fe /]#
|
||||
```
|
||||
|
||||
- 显示正在运行的容器
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4abaf8a399fe centos:latest "bash" 47 seconds ago Up 46 seconds hardcore_perlman
|
||||
```
|
||||
|
||||
- 显示所有容器,包括停止的所有容器
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
[root@docker-server ~]# docker ps -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4abaf8a399fe centos:latest "bash" 2 minutes ago Exited (0) 9 seconds ago hardcore_perlman
|
||||
```
|
||||
|
||||
#### 2.3 端口映射
|
||||
|
||||
- 前台启动随机映射端口
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker pull nginx
|
||||
[root@docker-server ~]# docker run -P nginx
|
||||
# 随机映射端口,其实是从32768开始映射
|
||||
[root@docker-server ~]# ss -tanl
|
||||
State Recv-Q Send-Q Local Address:Port Peer Address:Port
|
||||
LISTEN 0 128 *:22 *:*
|
||||
LISTEN 0 100 127.0.0.1:25 *:*
|
||||
LISTEN 0 128 *:49153 *:*
|
||||
LISTEN 0 128 :::22 :::*
|
||||
LISTEN 0 100 ::1:25 :::*
|
||||
LISTEN 0 128 :::49153 :::*
|
||||
```
|
||||
|
||||

|
||||
|
||||
- 指定端口映射
|
||||
|
||||
```bash
|
||||
# 方式1,本地端口80映射到容器80端口
|
||||
[root@docker-server ~]# docker run -p 80:80 --name nginx-1 nginx:latest
|
||||
# 方式2,本地ip:本地端口:容器端口
|
||||
[root@docker-server ~]# docker run -p 192.168.204.135:80:80 --name nginx-1 nginx:latest
|
||||
# 方式3,本地ip:本地随机端口:容器端口
|
||||
[root@docker-server ~]# docker run -p 192.168.175.10::80 --name nginx-1 nginx:latest
|
||||
# 方式4,本地ip:本地端口:容器端口/协议默认为tcp协议
|
||||
[root@docker-server ~]# docker run -p 192.168.175.10:80:80/tcp --name nginx-1 nginx:latest
|
||||
|
||||
```
|
||||
|
||||
- 查看容器已经映射的端口
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker port nginx-1
|
||||
80/tcp -> 0.0.0.0:80
|
||||
80/tcp -> :::80
|
||||
```
|
||||
|
||||
#### 2.4 后台启动容器
|
||||
|
||||
- 当容器前台启动时,前台进程退出容器也就退出,更多时候需要容器在后台启动
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker run -d -P --name nginx-2 nginx
|
||||
c75333168c0dad9094d94828c33998294f2809ae8c5b60881707d9cc33ea4893
|
||||
```
|
||||
|
||||
- 传递运行命令
|
||||
|
||||
容器需要由一个前台运行的进程才能保持容器的运行,通过传递运行参数是一种方式,另外也可以在构建镜像的时候指定容器启动时运行的前台命令
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker ps -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
[root@docker-server ~]# docker run -d centos
|
||||
9ef312d30f7a396ecb5c93b7b70e70a742f333bbe01e9112d6f22fc52aeb71b8
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
[root@docker-server ~]# docker ps -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
9ef312d30f7a centos "/bin/bash" 12 seconds ago Exited (0) 11 seconds ago upbeat_noether
|
||||
[root@docker-server ~]# docker run -d centos tail -f /etc/hosts
|
||||
7b0700c01f9516f49e70ad92e7256d965e0fe4eb8ccc7b30676a03c1d8046c64
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
7b0700c01f95 centos "tail -f /etc/hosts" 3 seconds ago Up 2 seconds charming_brahmagupta
|
||||
```
|
||||
|
||||
- 单次运行,容器退出后自动删除
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker run --name hello_world_test --rm hello-world
|
||||
|
||||
Hello from Docker!
|
||||
This message shows that your installation appears to be working correctly.
|
||||
|
||||
To generate this message, Docker took the following steps:
|
||||
1. The Docker client contacted the Docker daemon.
|
||||
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
|
||||
(amd64)
|
||||
3. The Docker daemon created a new container from that image which runs the
|
||||
executable that produces the output you are currently reading.
|
||||
4. The Docker daemon streamed that output to the Docker client, which sent it
|
||||
to your terminal.
|
||||
|
||||
To try something more ambitious, you can run an Ubuntu container with:
|
||||
$ docker run -it ubuntu bash
|
||||
|
||||
Share images, automate workflows, and more with a free Docker ID:
|
||||
https://hub.docker.com/
|
||||
|
||||
For more examples and ideas, visit:
|
||||
https://docs.docker.com/get-started/
|
||||
|
||||
[root@docker-server ~]# docker ps -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
[root@docker-server ~]#
|
||||
```
|
||||
|
||||
### 3. 停止容器
|
||||
|
||||
#### 3.1 暂停容器
|
||||
|
||||
- 挂起容器
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4c6344c46c80 nginx "/docker-entrypoint.…" 8 seconds ago Up 8 seconds 80/tcp wizardly_hofstadter
|
||||
[root@docker-server ~]# docker pause wizardly_hofstadter
|
||||
wizardly_hofstadter
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4c6344c46c80 nginx "/docker-entrypoint.…" 17 seconds ago Up 16 seconds (Paused) 80/tcp wizardly_hofstadter
|
||||
```
|
||||
|
||||
- 取消挂起容器
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker unpause wizardly_hofstadter
|
||||
wizardly_hofstadter
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4c6344c46c80 nginx "/docker-entrypoint.…" 33 seconds ago Up 33 seconds 80/tcp wizardly_hofstadter
|
||||
```
|
||||
|
||||
#### 3.2 终止容器
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4c6344c46c80 nginx "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp wizardly_hofstadter
|
||||
|
||||
[root@docker-server ~]# docker stop wizardly_hofstadter
|
||||
wizardly_hofstadter
|
||||
[root@docker-server ~]# docker ps -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4c6344c46c80 nginx "/docker-entrypoint.…" 2 minutes ago Exited (0) 5 seconds ago wizardly_hofstadter
|
||||
|
||||
[root@docker-server ~]# docker start wizardly_hofstadter
|
||||
wizardly_hofstadter
|
||||
[root@docker-server ~]# docker ps -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4c6344c46c80 nginx "/docker-entrypoint.…" 2 minutes ago Up 2 seconds 80/tcp wizardly_hofstadter
|
||||
```
|
||||
|
||||
### 4. 删除容器
|
||||
|
||||
#### 4.1 docker rm
|
||||
|
||||
- 删除正在运行的容器
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
dfd5ba20c3c6 centos:latest "bash" 8 seconds ago Up 6 seconds frosty_elbakyan
|
||||
[root@docker-server ~]# docker rm -f dfd5ba20c3c6
|
||||
dfd5ba20c3c6
|
||||
```
|
||||
|
||||
- 批量删除容器
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker ps -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
8e3cb314c9ad nginx "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 80/tcp pedantic_lovelace
|
||||
4ab46864c8a3 nginx "/docker-entrypoint.…" 5 seconds ago Up 4 seconds 80/tcp beautiful_spence
|
||||
26a154528469 nginx "/docker-entrypoint.…" 5 seconds ago Up 5 seconds 80/tcp serene_booth
|
||||
2ecbf60d817a nginx "/docker-entrypoint.…" 6 seconds ago Up 6 seconds 80/tcp dreamy_bassi
|
||||
d73faf8c2f7d nginx "/docker-entrypoint.…" 8 seconds ago Up 8 seconds 80/tcp beautiful_solomon
|
||||
[root@docker-server ~]# docker ps -a -q
|
||||
8e3cb314c9ad
|
||||
4ab46864c8a3
|
||||
26a154528469
|
||||
2ecbf60d817a
|
||||
d73faf8c2f7d
|
||||
[root@docker-server ~]# docker rm -f `docker ps -a -q`
|
||||
8e3cb314c9ad
|
||||
4ab46864c8a3
|
||||
26a154528469
|
||||
2ecbf60d817a
|
||||
d73faf8c2f7d
|
||||
[root@docker-server ~]# docker ps -a
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
```
|
||||
|
||||
### 5. 进入容器
|
||||
|
||||
#### 5.1 attach
|
||||
|
||||
所有使用此方式进入容器的操作都是同步显示的且exit容器将被关闭,且使用exit退出后容器关闭,不推荐使用
|
||||
|
||||

|
||||
|
||||
当有一个容器执行exit退出后会导致容器退出
|
||||
|
||||
#### 5.2 exec
|
||||
|
||||
执行单次命令与进入容器,退出容器后容器还在运行
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker run -d -it centos
|
||||
129d518869d550e579bcff38608bae38209923dcbfab49c823d5e1473d38214a
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
129d518869d5 centos "/bin/bash" 2 seconds ago Up 1 second jovial_haibt
|
||||
[root@docker-server ~]# docker exec -it jovial_haibt /bin/bash
|
||||
[root@129d518869d5 /]# echo hello
|
||||
hello
|
||||
[root@129d518869d5 /]# exit
|
||||
exit
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
129d518869d5 centos "/bin/bash" 46 seconds ago Up 45 seconds jovial_haibt
|
||||
```
|
||||
|
||||
```
|
||||
在Docker中,docker exec命令用于在正在运行的容器中执行命令。docker exec命令的一般语法如下:
|
||||
|
||||
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
|
||||
其中,参数的含义如下:
|
||||
|
||||
OPTIONS:可选参数,用于指定一些附加选项。常用的选项包括:
|
||||
|
||||
-i, --interactive:保持标准输入(stdin)打开,允许用户与命令交互。
|
||||
-t, --tty:分配一个伪终端(pseudo-TTY),以便于命令的交互和输出格式化。
|
||||
-u, --user:指定执行命令的用户或用户组。
|
||||
-d, --detach:在后台运行命令。
|
||||
-e, --env:设置环境变量。
|
||||
-w, --workdir:指定命令执行的工作目录。
|
||||
等等。
|
||||
CONTAINER:必需参数,指定要执行命令的容器名称或容器ID。
|
||||
|
||||
COMMAND:必需参数,指定要在容器中执行的命令。
|
||||
|
||||
ARG:可选参数,传递给命令的参数
|
||||
```
|
||||
|
||||
#### 5.3 nsenter
|
||||
|
||||
nsenter命令需要通过pid进入到容器内部,不过可以使用docker inspect获取到容器的pid
|
||||
|
||||
- 可以通过docker inspect获取到某个容器的进程id
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker inspect -f ".State.Pid" 129d518869d5 # .State.Pid 两边需要加上两个花括号
|
||||
7949
|
||||
```
|
||||
|
||||
- 通过nsenter进入到容器内部
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# nsenter -t 7949 -m -u -i -n -p
|
||||
[root@129d518869d5 /]#
|
||||
```
|
||||
|
||||
- 使用脚本方式进入
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# cat docker_in.sh
|
||||
#!/bin/bash
|
||||
docker_in(){
|
||||
DOCKER_ID=$1
|
||||
PID=`docker inspect -f ".State.Pid" ${DOCKER_ID}`
|
||||
nsenter -t ${PID} -m -u -i -n -p
|
||||
}
|
||||
|
||||
docker_in $1
|
||||
[root@docker-server ~]# chmod +x docker_in.sh
|
||||
[root@docker-server ~]# ./docker_in.sh 129d518869d5
|
||||
[root@129d518869d5 /]# exit
|
||||
logout
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
129d518869d5 centos "/bin/bash" 14 minutes ago Up 14 minutes jovial_haibt
|
||||
[root@docker-server ~]#
|
||||
```
|
||||
|
||||
### 6. 指定容器DNS
|
||||
|
||||
dns服务,默认采用dns地址
|
||||
|
||||
一是通过将dns地址配置在宿主机上
|
||||
|
||||
二是将参数配置在docker启动脚本里面
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker run -it --rm --dns 8.8.8.8 centos bash
|
||||
[root@a6ce80126e75 /]# cat /etc/resolv.conf
|
||||
nameserver 8.8.8.8
|
||||
[root@a6ce80126e75 /]# ping www.baidu.com -c 1
|
||||
PING www.a.shifen.com (180.101.49.11) 56(84) bytes of data.
|
||||
64 bytes from 180.101.49.11 (180.101.49.11): icmp_seq=1 ttl=127 time=9.35 ms
|
||||
|
||||
--- www.a.shifen.com ping statistics ---
|
||||
1 packets transmitted, 1 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 9.346/9.346/9.346/0.000 ms
|
||||
[root@a6ce80126e75 /]# exit
|
||||
exit
|
||||
```
|
||||
|
||||
### 7. 导入导出容器
|
||||
|
||||
#### 7.1 docker export
|
||||
|
||||
导出容器是指,导出一个已经创建的容器到一个文件,不管此时这个容器是否处于运行状态,**导出一个容器快照**
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker run -d -it centos
|
||||
43f2397b9456d27a3b84dba0d79ae9a1dd8dddf40440d7d73fca71cddea0e10d
|
||||
[root@docker-server ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
43f2397b9456 centos "/bin/bash" 2 seconds ago Up 2 seconds awesome_rubin
|
||||
[root@docker-server ~]# docker export -o /opt/centos.tar 43f
|
||||
[root@docker-server ~]# ll /opt/centos.tar
|
||||
-rw------- 1 root root 216525312 6月 9 13:28 /opt/centos.tar
|
||||
```
|
||||
|
||||
#### 7.2 docker import
|
||||
|
||||
导出的文件可以使用docker import命令导入变成镜像,**导入一个容器快照到本地镜像库**
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker import /opt/centos.tar mycentos:v1
|
||||
sha256:acf250a6cabb56e0464102dabedb0a562f933facd3cd7b387e665459da46bf29
|
||||
[root@docker-server ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
mycentos v1 acf250a6cabb 9 seconds ago 209MB
|
||||
nginx latest d1a364dc548d 2 weeks ago 133MB
|
||||
hello-world latest d1165f221234 3 months ago 13.3kB
|
||||
centos latest 300e315adb2f 6 months ago 209MB
|
||||
```
|
||||
|
||||
适用场景:主要用来制作基础镜像,比如从一个ubuntu镜像启动一个容器,然后安装一些软件和进行一些设置后,使用docker export保存为一个基础镜像。然后把这个镜像分发给其他人使用,作为基础的开发环境。(因为export导出的镜像只会保留从镜像运行到export之间对文件系统的修改,所以只适合做基础镜像)
|
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 51 KiB |
@@ -1,469 +0,0 @@
|
||||
# 04.Docker镜像制作
|
||||
|
||||
## 04.Docker镜像制作
|
||||
|
||||
### 1. Docker镜像制作
|
||||
|
||||
### 2. 基于rocky手动构建nginx镜像
|
||||
|
||||
Docker镜像制作类似于虚拟机的模板制作,即按照公司的实际业务将需要安装的软件、相关配置等基础环境配置完成,然后将容器再提交为模板,最后再批量从模板批量创建新的虚拟机,这样可以极大地简化业务中相同环境的虚拟机运行环境的部署工作,Docker的镜像制作分为手动制作可自动制作(基于DockerFile),企业通常都是基于DockerFile制作镜像。
|
||||
|
||||
#### 2.1 从初始镜像开始构建
|
||||
|
||||
一、启动一个RockyLinux容器,安装好nginx以及常用软件
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -it -d --name mynginx_server rockylinux:9 bash
|
||||
18914b0f6005e7b20122508f8bc70a830845711ff6200392bf0a7c76dc4a8a60
|
||||
[root@localhost ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
18914b0f6005 rockylinux:9 "bash" 3 seconds ago Up 2 seconds mynginx_server
|
||||
[root@localhost ~]# docker exec -it mynginx_server bash
|
||||
|
||||
# 进入容器以后,安装nginx以及一些常用的软件
|
||||
[root@18914b0f6005 /]# yum install -y epel-release nginx
|
||||
[root@18914b0f6005 /]# yum install vim wget pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop -y
|
||||
```
|
||||
|
||||
二、关闭nginx后台运行
|
||||
|
||||
```bash
|
||||
[root@18914b0f6005 /]# vim /etc/nginx/nginx.conf
|
||||
......
|
||||
daemon off;
|
||||
......
|
||||
```
|
||||
|
||||
三、自定义web界面
|
||||
|
||||
```bash
|
||||
[root@18914b0f6005 /]# vim /etc/nginx/nginx.conf
|
||||
[root@18914b0f6005 /]# echo "<h1>Welcome to Eagle nginx...</h1>" > /usr/share/nginx/html/index.html
|
||||
```
|
||||
|
||||
#### 2.2 镜像提交
|
||||
|
||||
通过commit提交为镜像
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker commit --help
|
||||
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
|
||||
|
||||
Create a new image from a container's changes
|
||||
|
||||
Aliases:
|
||||
docker container commit, docker commit
|
||||
|
||||
Options:
|
||||
-a, --author string Author (e.g., "John Hannibal Smith
|
||||
<hannibal@a-team.com>")
|
||||
-c, --change list Apply Dockerfile instruction to the created image
|
||||
-m, --message string Commit message
|
||||
-p, --pause Pause container during commit (default true)
|
||||
|
||||
# 重新打包为新镜像
|
||||
[root@localhost ~]# docker commit -a "Eagle_nls" -m "my nginx image v1" 18914b0f6005 rocky_nginx:v1
|
||||
sha256:9411e13b57d003a6d709054ccbbc026a7b005a1727ec470755f987e25ff45a6b
|
||||
[root@localhost ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
rocky_nginx v1 9411e13b57d0 33 seconds ago 357MB
|
||||
mynginx v1 81ef4ae01fed 2 hours ago 190MB
|
||||
codercom/code-server latest 5d9cf2e7e6bb 10 days ago 718MB
|
||||
neosmemo/memos latest 8f07b54db502 6 weeks ago 65.9MB
|
||||
```
|
||||
|
||||
docker commit**适用场景:**主要作用是将配置好的一些容器复用,再生成新的镜像。
|
||||
commit是合并了save、load、export、import这几个特性的一个综合性的命令,它主要做了:
|
||||
1、将container当前的读写层保存下来,保存成一个新层
|
||||
2、和镜像的历史层一起合并成一个新的镜像
|
||||
|
||||
#### 2.3 从新镜像启动容器
|
||||
|
||||
从自己的镜像启动容器
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -d -p 80:80 --name mynginx_rocky rocky_nginx:v1 /usr/sbin/nginx
|
||||
dc4225c68d28ffdcc559662b8680f9e4b4b95bdaeeca2f1ed566d638aa8fc8fe
|
||||
[root@localhost ~]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
dc4225c68d28 rocky_nginx:v1 "/usr/sbin/nginx" 2 seconds ago Up 1 second 0.0.0.0:80->80/tcp, [::]:80->80/tcp mynginx_rocky
|
||||
```
|
||||
|
||||
访问测试:
|
||||
|
||||

|
||||
|
||||
### 3. DockerFile制作镜像
|
||||
|
||||
Dockerfile 是一种可以被 Docker 程序解释的脚本,它是一个文本文件,包含了一系列指令,用于定义如何构建 Docker 镜像。每一条指令都会创建镜像的一层,最终生成的镜像是由这些层叠加而成的。Dockerfile 中的指令关键字必须大写,执行顺序是从上到下,且每条指令创建一个镜像层。
|
||||
|
||||
Docker 程序会读取 Dockerfile 并根据指令生成 Docker 镜像。Dockerfile 的指令类似于 Linux 下的命令,但 Docker 程序会将这些 Dockerfile 指令翻译成真正的 Linux 命令来执行。相比手动制作镜像的方式,Dockerfile 能更直观地展示镜像是如何产生的。有了写好的 Dockerfile 文件,当后期某个镜像有额外的需求时,只需在之前的 Dockerfile 中添加或修改相应的操作,即可重新生成新的 Docker 镜像,避免了重复手动制作镜像的麻烦。
|
||||
|
||||
#### 3.1 指令说明
|
||||
|
||||
##### 3.1.1 配置指令
|
||||
|
||||
| 指令 | 说明 |
|
||||
| :------------ | :--------------------------------- |
|
||||
| `ARG` | 定义创建镜像过程中使用的变量 |
|
||||
| `FROM` | 指定所创建镜像的基础镜像 |
|
||||
| `LABEL` | 为生成的镜像添加元数据标签信息 |
|
||||
| `EXPOSE` | 声明镜像内服务监听的端口 |
|
||||
| `ENV` | 指定环境变量 |
|
||||
| `ENTRYPOINT` | 指定镜像的默认入口命令 |
|
||||
| `VOLUME` | 创建一个数据卷挂载点 |
|
||||
| `USER` | 指定运行容器时的用户名或UID |
|
||||
| `WORKDIR` | 配置工作目录 |
|
||||
| `ONBUILD` | 创建子镜像时指定自动执行的操作指令 |
|
||||
| `STOPSIGNAL` | 指定退出的信号值 |
|
||||
| `HEALTHCHECK` | 配置所启动容器如何进行健康检查 |
|
||||
| `SHELL` | 指定默认shell类型 |
|
||||
|
||||
##### 3.1.2 操作指令
|
||||
|
||||
| 指令 | 说明 |
|
||||
| :----- | :--------------------------- |
|
||||
| `RUN` | 运行指定命令 |
|
||||
| `CMD` | 启动容器时指定默认执行的命令 |
|
||||
| `ADD` | 添加内容到镜像 |
|
||||
| `COPY` | 复制内容到镜像 |
|
||||
|
||||
#### 3.2 配置指令详解
|
||||
|
||||
##### 3.2.1 ARG
|
||||
|
||||
定义创建过程中使用到的变量,例如 `HTTP_PROXY`、`HTTPS_PROXY`、`FTP_PROXY`、`NO_PROXY` 等,不区分大小写。
|
||||
|
||||
##### 3.2.2 FROM
|
||||
|
||||
指定所创建镜像的基础镜像。为了保证镜像精简,可以选用体积较小的 Alpin 或 Debian 作为基础镜像。
|
||||
|
||||
##### 3.2.3 EXPOSE
|
||||
|
||||
声明镜像内服务监听的端口。例如:
|
||||
|
||||
```bash
|
||||
EXPOSE 22 80 8443
|
||||
```
|
||||
|
||||
该指令只是起到声明作用,并不会自动完成端口映射。
|
||||
|
||||
##### 3.2.4 ENTRYPOINT
|
||||
|
||||
指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。支持两种格式:
|
||||
|
||||
- `ENTRYPOINT ["executable","param1","param2"]`(exec 调用执行)
|
||||
- `ENTRYPOINT command param1 param2`(在 shell 中执行)
|
||||
|
||||
此时 `CMD` 指令指定值将作为根命令的参数。每个 Dockerfile 中只能有一个 `ENTRYPOINT`,当指定多个时只有最后一个起效。
|
||||
|
||||
##### 3.2.5 VOLUME
|
||||
|
||||
创建一个数据卷挂载点。例如:
|
||||
|
||||
```bash
|
||||
VOLUME ["/data"]
|
||||
```
|
||||
|
||||
##### 3.2.6 WORKDIR
|
||||
|
||||
为后续的 `RUN`、`CMD`、`ENTRYPOINT` 指令配置工作目录。例如:
|
||||
|
||||
```bash
|
||||
WORKDIR /path/to/workdir
|
||||
```
|
||||
|
||||
可以使用多个 `WORKDIR` 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如:
|
||||
|
||||
```bash
|
||||
WORKDIR /a
|
||||
WORKDIR b
|
||||
WORKDIR c
|
||||
RUN pwd
|
||||
```
|
||||
|
||||
最终路径为 `/a/b/c`。因此,为了避免出错,推荐在 `WORKDIR` 指令中只使用绝对路径。
|
||||
|
||||
##### 3.2.7 操作指令详解
|
||||
|
||||
##### 3.2.8 RUN
|
||||
|
||||
运行指定Linux命令。每条 `RUN` 指令将在当前镜像基础上执行指定命令,并提交为新的镜像层。当命令较长时可以使用 `\` 来换行。
|
||||
|
||||
##### 3.2.9 CMD
|
||||
|
||||
`CMD` 指令用来指定启动容器时默认执行的命令。支持三种格式:
|
||||
|
||||
- `CMD ["executable","param1","param2"]`(相当于执行 `executable param1 param2`)
|
||||
- `CMD command param1 param2`(在默认的 shell 中执行,提供给需要交互的应用)
|
||||
- `CMD ["param1","param2"]`(提供给 `ENTRYPOINT` 的默认参数)
|
||||
|
||||
每个 Dockerfile 只能有一条 `CMD` 命令。如果指定了多条命令,只有最后一条会被执行。
|
||||
|
||||
##### 3.2.10 ADD
|
||||
|
||||
添加内容到镜像。例如:
|
||||
|
||||
```bash
|
||||
ADD <src> <dest>
|
||||
```
|
||||
|
||||
该命令将复制指定的 `src` 路径下内容到容器中的 `dest` 路径下。`src` 可以是 Dockerfile 所在目录的一个相对路径,也可以是一个 URL,还可以是一个 tar 文件。`dest` 可以是镜像内绝对路径,或者相对于工作目录的相对路径。
|
||||
|
||||
##### 3.2.11 COPY
|
||||
|
||||
复制内容到镜像。例如:
|
||||
|
||||
```bash
|
||||
COPY <src> <dest>
|
||||
```
|
||||
|
||||
`COPY` 与 `ADD` 指令功能类似,当使用本地目录为源目录时,推荐使用 `COPY`。
|
||||
|
||||
#### 3.3 制作nginx镜像
|
||||
|
||||
DockerFile可以说是一种可以被Docker程序解释的脚本,DockerFIle是由一条条的命令组成的,每条命令对应Linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的Linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像。
|
||||
|
||||
##### 3.3.1 基于编译安装制作nginx小游戏网站
|
||||
|
||||
###### 3.3.1.1 环境准备
|
||||
|
||||
一、下载镜像
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker pull rockylinux:9
|
||||
```
|
||||
|
||||
二、创建所需文件存放的目录环境
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# mkdir -pv dockerfile/nginx
|
||||
mkdir: created directory 'dockerfile'
|
||||
mkdir: created directory 'dockerfile/nginx'
|
||||
```
|
||||
|
||||
三、进入到指定目录中
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# cd dockerfile/nginx/
|
||||
[root@localhost nginx]# pwd
|
||||
/root/dockerfile/nginx
|
||||
```
|
||||
|
||||
四、下载nginx和小游戏网页的源码包
|
||||
|
||||
```bash
|
||||
[root@localhost nginx]# wget http://nginx.org/download/nginx-1.22.0.tar.gz
|
||||
[root@localhost nginx]# wget http://file.eagleslab.com:8889/%E8%AF%BE%E7%A8%8B%E7%9B%B8%E5%85%B3%E8%BD%AF%E4%BB%B6/%E4%BA%91%E8%AE%A1%E7%AE%97%E8%AF%BE%E7%A8%8B/%E8%AF%BE%E7%A8%8B%E7%9B%B8%E5%85%B3%E6%96%87%E4%BB%B6/games.tar.gz
|
||||
[root@localhost nginx]# ll
|
||||
total 125100
|
||||
-rw-r--r--. 1 root root 127022187 Jan 18 2022 games.tar.gz
|
||||
-rw-r--r--. 1 root root 1073322 May 24 2022 nginx-1.22.0.tar.gz
|
||||
```
|
||||
|
||||
###### 3.3.1.2 编写Dockerfile
|
||||
|
||||
一、编写DockerFile
|
||||
|
||||
```bash
|
||||
[root@docker-server nginx]# vim Dockerfile
|
||||
# 第一行先定义基础镜像,后面的本地有效的镜像名,如果本地没有,会从远程仓库下载
|
||||
FROM rockylinux:9
|
||||
|
||||
# 镜像作者的信息
|
||||
MAINTAINER Eagle_nls 2898485992@qq.com
|
||||
|
||||
# 接下来在基础镜像之上构建nginx等所需环境
|
||||
|
||||
# 1. 编译安装nginx
|
||||
# 1.1 安装所需环境及工具
|
||||
RUN yum install -y vim wget unzip tree lrzsz gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel iproute net-tools iotop
|
||||
|
||||
# 1.2 上传nginx的官方源码包到指定目录
|
||||
ADD nginx-1.22.0.tar.gz /usr/local/src/
|
||||
|
||||
# 1.3 由于ADD会直接解压好,所以直接编译nginx
|
||||
RUN cd /usr/local/src/nginx-1.22.0 \
|
||||
&& ./configure --prefix=/usr/local/nginx --with-http_sub_module \
|
||||
&& make \
|
||||
&& make install \
|
||||
&& cd /usr/local/nginx
|
||||
|
||||
# 如果有配置文件,可以上传自己准备好的配置文件
|
||||
# ADD nginx.conf /usr/local/nginx/conf/nginx.conf
|
||||
|
||||
# 2. 完善网站
|
||||
RUN useradd -s /sbin/nologin nginx \
|
||||
&& ln -sv /usr/local/nginx/sbin/nginx /usr/sbin/nginx
|
||||
|
||||
# 3. 上传小游戏网页源码
|
||||
ADD games.tar.gz /usr/local/nginx/html/
|
||||
|
||||
# 4. 声明端口号
|
||||
EXPOSE 80 443
|
||||
|
||||
# 5. 设定启动时执行命令
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
|
||||
###### 3.3.1.3 构建镜像
|
||||
|
||||
一、通过docker build来构建镜像
|
||||
|
||||
```bash
|
||||
[root@localhost nginx]# docker build -t nginx_games:v1 .
|
||||
[root@localhost nginx]# docker images |grep nginx_games
|
||||
nginx_games v1 9c86d96dfba0 4 minutes ago 686MB
|
||||
```
|
||||
|
||||
二、镜像运行测试
|
||||
|
||||
```bash
|
||||
[root@localhost nginx]# docker run -d -it -p 80:80 --name nginx_games nginx_games:v1
|
||||
e3c415425f95b3deac80ecb772d1de2a89e18a611c2ecc603f3c0b175bbea335
|
||||
[root@localhost nginx]# docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
e3c415425f95 nginx_games:v1 "nginx -g 'daemon of…" 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp, [::]:80->80/tcp, 443/tcp nginx_games
|
||||
```
|
||||
|
||||
三、访问测试
|
||||
|
||||

|
||||
|
||||
### 4. 镜像上传
|
||||
|
||||
#### 4.1 官方docker仓库
|
||||
|
||||
- 准备账户
|
||||
|
||||
登陆到docker hub官网创建账号,登陆后点击settings完善信息
|
||||
|
||||
- 填写账户基本信息
|
||||
|
||||

|
||||
|
||||
- 登陆仓库
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker login docker.io
|
||||
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
|
||||
Username: smqy
|
||||
Password:
|
||||
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
|
||||
Configure a credential helper to remove this warning. See
|
||||
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
|
||||
|
||||
Login Succeeded
|
||||
[root@docker-server ~]# ls -a
|
||||
. .bash_history .bashrc dockerfile .tcshrc
|
||||
.. .bash_logout .cshrc docker_in.sh .viminfo
|
||||
anaconda-ks.cfg .bash_profile .docker .pki
|
||||
[root@docker-server ~]# cat .docker/config.json
|
||||
{
|
||||
"auths": {
|
||||
"https://index.docker.io/v1/": {
|
||||
"auth": "YmJqMTAzMDp6aGFuZ2ppZTEyMw=="
|
||||
}
|
||||
}
|
||||
}[root@docker-server ~]#
|
||||
|
||||
```
|
||||
|
||||
- 给镜像tag标签并上传
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker tag nginx:v1 docker.io/smqy/nginx:v1
|
||||
[root@docker-server ~]# docker images
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
nginx v1 fbd06c1753c0 12 minutes ago 581MB
|
||||
smqy/nginx v1 fbd06c1753c0 12 minutes ago 581MB
|
||||
centos_nginx v1 74acdcca8c97 21 hours ago 525MB
|
||||
nginx latest 2b7d6430f78d 3 weeks ago 142MB
|
||||
centos 7 eeb6ee3f44bd 12 months ago 204MB
|
||||
nginx 1.8 0d493297b409 6 years ago 133MB
|
||||
[root@docker-server ~]# docker push docker.io/smqy/nginx:v1
|
||||
The push refers to repository [docker.io/smqy/nginx]
|
||||
4f86a3bf507f: Pushed
|
||||
0d11c01ff3ef: Pushed
|
||||
45fc5772a4e4: Pushed
|
||||
174f56854903: Mounted from library/centos
|
||||
v1: digest: sha256:385bfe364839b645f1b2aa70a1d779b0dca50256ea01ccbe4ebde53aabd1d96d size: 1164
|
||||
```
|
||||
|
||||
- 到docker官网进行验证
|
||||
|
||||

|
||||
|
||||
- 更换到其他docker服务器下载镜像
|
||||
|
||||
```bash
|
||||
[root@docker-server ~]# docker login docker.io
|
||||
```
|
||||
|
||||
#### 4.2 阿里云仓库
|
||||
|
||||
将本地镜像上传至阿里云,实现镜像备份与统一分发的功能
|
||||
|
||||
https://cr.console.aliyun.com/
|
||||
|
||||
注册并且登录阿里云镜像仓库,创建namespace空间,创建一个普通的镜像仓库
|
||||
|
||||

|
||||
|
||||
具体如何拉取镜像,上传镜像,可以查看阿里云仓库下方提供的操作指南
|
||||
|
||||
##### 4.2.1 Push镜像案例
|
||||
|
||||
一、登录阿里云仓库
|
||||
|
||||
```bash
|
||||
[root@localhost nginx]# docker login --username=Echooool registry.cn-hangzhou.aliyuncs.com
|
||||
|
||||
i Info → A Personal Access Token (PAT) can be used instead.
|
||||
To create a PAT, visit https://app.docker.com/settings
|
||||
|
||||
|
||||
Password:
|
||||
Error response from daemon: Get "https://registry.cn-hangzhou.aliyuncs.com/v2/": unauthorized: authentication required
|
||||
[root@localhost nginx]# docker login --username=Echooool registry.cn-hangzhou.aliyuncs.com
|
||||
|
||||
i Info → A Personal Access Token (PAT) can be used instead.
|
||||
To create a PAT, visit https://app.docker.com/settings
|
||||
|
||||
|
||||
Password:
|
||||
|
||||
WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
|
||||
Configure a credential helper to remove this warning. See
|
||||
https://docs.docker.com/go/credential-store/
|
||||
|
||||
Login Succeeded
|
||||
```
|
||||
|
||||
二、推送镜像
|
||||
|
||||
```bash
|
||||
# 先给要推送的镜像打上标签
|
||||
[root@localhost nginx]# docker tag 9c86d96dfba0 registry.cn-hangzhou.aliyuncs.com/atopos/docker_hub:nginx_games-v1
|
||||
|
||||
# 推送镜像
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/atopos/docker_hub:nginx_games-v1
|
||||
```
|
||||
|
||||
三、阿里云查看
|
||||
|
||||

|
||||
|
||||
四、拉取镜像
|
||||
|
||||
```bash
|
||||
[root@localhost nginx]# docker pull registry.cn-hangzhou.aliyuncs.com/atopos/docker_hub:nginx_games-v1
|
||||
nginx_games-v1: Pulling from atopos/docker_hub
|
||||
446f83f14b23: Already exists
|
||||
d9262d5a1401: Already exists
|
||||
7330c5b74c49: Already exists
|
||||
55e1c23f0b49: Already exists
|
||||
5de772a29709: Already exists
|
||||
f4819c5e7596: Already exists
|
||||
Digest: sha256:f9a6ac50b9771c524017304847f3d8b2ffa4acbe01cef9279052272e50a9a3f3
|
||||
```
|
Before Width: | Height: | Size: 323 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 834 KiB |
Before Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 97 KiB |
@@ -1,314 +0,0 @@
|
||||
# 05.Docker数据管理
|
||||
|
||||
## 05.Docker数据管理
|
||||
|
||||
### 1. Docker数据管理
|
||||
|
||||
### 2. 数据管理
|
||||
|
||||
#### 2.1 UnionFS(联合文件系统)
|
||||
|
||||
Docker 中的 UnionFS(联合文件系统)是一种分层、轻量级且高性能的文件系统,其核心功能是将多个目录内容联合挂载到同一个目录下,形成一个统一的文件系统视图。以下是其主要特点和作用:
|
||||
|
||||
##### 2.1.1 核心特点
|
||||
|
||||
- **分层存储**:UnionFS 可以将不同层次的文件和目录合并成单一的目录树。在 Docker 中,每一层可以代表一个镜像层,最低层通常是只读的基础镜像层,上面的层是可写的容器层。
|
||||
- **写时复制(Copy-on-Write, CoW)**:当容器需要修改一个文件时,UnionFS 不会直接更改底层只读镜像中的文件,而是将更改写入到一个可写的上层。这样,原始镜像层保持不变,可以被多个容器共享。
|
||||
- **隔离性**:由于底层的只读镜像层保持不变,每个容器看到的是一个完整的文件系统视图,包括它们的改动,但这些改动仅存在于它们自己的可写层中。
|
||||
- **性能优化**:UnionFS 通过仅对发生更改的文件进行操作,以及通过页面缓存共享等机制,减少了磁盘 I/O 操作,加快了容器启动时间。
|
||||
|
||||
##### 2.1.2 在 Docker 中的应用
|
||||
|
||||
- **镜像分层**:Docker 镜像是由多个只读层叠加而成的,每一层都代表了镜像构建过程中的一个状态。UnionFS 将这些层联合起来,形成一个完整的文件系统。
|
||||
- **容器运行时的文件系统**:当启动一个容器时,Docker 会在镜像的最顶层添加一个新的可写层。容器的所有写操作都在这个可写层中进行,而不会影响到镜像的只读层。
|
||||
- **镜像继承与共享**:由于镜像的分层结构,新的镜像可以基于已有的镜像构建,只需添加新的层即可。同时,多个容器可以共享同一个镜像的只读层,极大地节省了磁盘空间。
|
||||
|
||||
##### 2.1.3 常见的 UnionFS 实现
|
||||
|
||||
虽然 UnionFS 是一个理念,但 Linux 内核中有多种具体的实现方式,Docker 默认使用的是 Overlay2。Overlay2 是一种先进的联合文件系统实现,具有更好的性能和一些先进的功能,如页面缓存共享。
|
||||
|
||||
#### 2.2 镜像层与可写层
|
||||
|
||||
在 Docker 中,镜像层和容器可写层是基于联合文件系统(UnionFS)实现的关键概念。它们共同构成了容器的文件系统结构,使得 Docker 能够高效地管理和运行容器。以下是对镜像层和容器可写层的详细解释:
|
||||
|
||||
##### 2.2.1 一、镜像层
|
||||
|
||||
镜像层是 Docker 镜像的组成部分,每个镜像由多个只读层组成,这些层是不可修改的。
|
||||
|
||||
1. **镜像层的生成**
|
||||
|
||||
- 当你构建一个 Docker 镜像时,Dockerfile 中的每一条指令(如 `RUN`、`COPY`、`ADD` 等)都会生成一个新的镜像层。
|
||||
|
||||
- 例如,一个简单的 Dockerfile 如下:
|
||||
|
||||
```dockerfile
|
||||
FROM ubuntu:20.04
|
||||
RUN apt-get update && apt-get install -y nginx
|
||||
COPY ./my_nginx.conf /etc/nginx/nginx.conf
|
||||
```
|
||||
|
||||
- 第一层是基础镜像层,如 `ubuntu:20.04`,这是从 Docker Hub 拉取的预构建镜像。
|
||||
- 第二层是通过 `RUN` 指令安装 Nginx 生成的层,包含了安装过程中产生的所有文件和目录变化。
|
||||
- 第三层是通过 `COPY` 指令将本地的 `my_nginx.conf` 文件复制到镜像中的 `/etc/nginx/nginx.conf` 位置生成的层。
|
||||
|
||||
- 每一层都是基于前一层构建的,新的层只包含与前一层的差异部分。
|
||||
|
||||
2. **镜像层的特点**
|
||||
|
||||
- **只读性**:镜像层是只读的,一旦创建就不能修改。如果需要修改镜像层中的内容,必须通过构建新的镜像层来实现。
|
||||
- **共享性**:多个容器可以共享同一个镜像层,因为镜像层是不可变的,这大大节省了磁盘空间。
|
||||
- **不可变性**:镜像层的不可变性保证了镜像的一致性和可重复性,无论在什么环境下运行,基于同一镜像启动的容器都具有相同的文件系统结构。
|
||||
|
||||
3. **镜像层的作用**
|
||||
|
||||
- **构建高效**:通过分层构建,Docker 可以缓存中间层,避免重复构建相同的操作。例如,如果基础镜像层和安装 Nginx 的层已经构建过,再次构建时可以直接使用缓存的层,而不是重新执行命令。
|
||||
- **节省空间**:多个容器可以共享镜像层,减少了磁盘空间的占用。例如,10 个基于同一个基础镜像的容器,只需要存储一份基础镜像层,而不是每份都单独存储。
|
||||
- **便于分发**:镜像层的结构使得镜像可以方便地分发和共享。用户可以从 Docker Hub 等镜像仓库拉取镜像,而无需关心镜像的具体构建过程。
|
||||
|
||||
##### 2.2.2 二、容器可写层
|
||||
|
||||
容器可写层是容器运行时特有的一个层,它是可写的,用于存储容器运行时产生的所有变更。
|
||||
|
||||
1. **容器可写层的生成**
|
||||
- 当你启动一个容器时,Docker 会在镜像的最顶层添加一个新的可写层。这个可写层是容器独有的,用于存储容器运行时的文件系统变更。
|
||||
- 例如,如果你在容器中创建了一个新文件、修改了一个现有文件或删除了一个文件,这些操作都会反映在容器可写层中,而不会影响到镜像层。
|
||||
2. **容器可写层的特点**
|
||||
- **可写性**:容器可写层是可写的,容器运行时的所有文件系统操作(如创建、修改、删除文件)都在这个层中进行。
|
||||
- **独立性**:每个容器都有自己的可写层,容器之间的可写层是隔离的。一个容器的变更不会影响到其他容器。
|
||||
- **临时性**:容器可写层的内容在容器被删除时也会被删除。如果需要持久化数据,需要将数据存储在外部存储(如卷)中。
|
||||
3. **容器可写层的作用**
|
||||
- **隔离性**:容器可写层保证了容器之间的隔离性。每个容器在自己的可写层中进行操作,不会影响到其他容器或镜像层。
|
||||
- **灵活性**:容器可写层允许容器在运行时动态地修改文件系统,而不会影响到镜像的原始状态。这使得容器可以灵活地运行各种应用程序。
|
||||
- **数据持久化**:虽然容器可写层的内容在容器删除时会被删除,但你可以通过挂载卷(Volumes)将数据持久化到宿主机或其他存储设备中,从而实现数据的持久化存储。
|
||||
|
||||
##### 2.2.3 三、镜像层与容器可写层的关系
|
||||
|
||||
镜像层和容器可写层通过联合文件系统(UnionFS)联合起来,形成了容器的完整文件系统视图。
|
||||
|
||||
1. **联合挂载**
|
||||
- Docker 使用联合文件系统将镜像层和容器可写层联合挂载到同一个目录下。从容器的角度来看,它看到的是一个完整的文件系统,包含了镜像层和容器可写层的内容。
|
||||
- 例如,当你在容器中访问一个文件时,Docker 会先在容器可写层中查找该文件。如果找不到,就会在镜像层中查找。如果在镜像层中找到了文件,就会将该文件的内容返回给容器。
|
||||
2. **写时复制(Copy-on-Write)**
|
||||
- 当容器需要修改一个文件时,Docker 会使用写时复制机制。具体来说,Docker 会将文件从镜像层复制到容器可写层,然后在可写层中进行修改。这样,镜像层保持不变,而容器可写层存储了修改后的文件。
|
||||
- 例如,假设镜像层中有一个文件 `/etc/nginx/nginx.conf`,容器需要修改这个文件。Docker 会将该文件从镜像层复制到容器可写层,然后在可写层中进行修改。从容器的角度来看,它看到的是修改后的文件,而镜像层中的文件保持不变。
|
||||
3. **删除操作**
|
||||
- 当容器删除一个文件时,Docker 会在容器可写层中记录一个删除操作,而不是真正删除镜像层中的文件。这样,镜像层保持不变,而容器可写层记录了文件的删除状态。
|
||||
- 例如,假设容器删除了一个文件 `/etc/nginx/nginx.conf`,Docker 会在容器可写层中记录一个删除标记。从容器的角度来看,该文件已经被删除,而镜像层中的文件仍然存在。
|
||||
|
||||
##### 2.2.4 总结
|
||||
|
||||
- **镜像层**:是 Docker 镜像的组成部分,是只读的、不可变的,多个容器可以共享镜像层。镜像层通过分层构建,提高了构建效率、节省了磁盘空间,并保证了镜像的一致性和可重复性。
|
||||
- **容器可写层**:是容器运行时的可写层,用于存储容器运行时的文件系统变更。容器可写层是独立的、可写的、临时的,保证了容器之间的隔离性和运行时的灵活性。
|
||||
- **联合文件系统(UnionFS)**:将镜像层和容器可写层联合挂载,形成了容器的完整文件系统视图。通过写时复制机制,Docker 在不影响镜像层的情况下,允许容器在可写层中进行文件系统操作。
|
||||
|
||||
#### 2.3 查看镜像的详细信息
|
||||
|
||||
##### 2.3.1 一、查看镜像数据信息
|
||||
|
||||
```bash
|
||||
[root@localhost nginx]# docker inspect nginx_games:v1
|
||||
"Architecture": "amd64",
|
||||
"Os": "linux",
|
||||
"Size": 685997316,
|
||||
"GraphDriver": {
|
||||
"Data": {
|
||||
"LowerDir": "/var/lib/docker/overlay2/ilm8ifbi2gcrqg156w7kbu22f/diff:/var/lib/docker/overlay2/u51fr5eul9csiwghxmnm1acsi/diff:/var/lib/docker/overlay2/lo6sgoxbliga9l2qqqxcu2tvp/diff:/var/lib/docker/overlay2/bi4orr0yujicfufabnw7u8tym/diff:/var/lib/docker/overlay2/e51d5c1c74a99e1b1e41980bb9270fcba562976e40ae7dbf65ff585689a783d2/diff",
|
||||
"MergedDir": "/var/lib/docker/overlay2/talgtlohecyw3kt8d8idpzw4g/merged",
|
||||
"UpperDir": "/var/lib/docker/overlay2/talgtlohecyw3kt8d8idpzw4g/diff",
|
||||
"WorkDir": "/var/lib/docker/overlay2/talgtlohecyw3kt8d8idpzw4g/work"
|
||||
|
||||
LoweDir:image镜像层本身(只读)
|
||||
UpperDir:容器的上层读写层
|
||||
MergeDir:容器的文件系统,使用Union FS(联合文件系统)将镜像层和容器层合并给容器使用
|
||||
WorkDir:容器在宿主机的工作目录
|
||||
```
|
||||
|
||||
##### 2.3.2 二、查看镜像层构建过程
|
||||
|
||||
```bash
|
||||
[root@localhost nginx]# docker history nginx_games:v1
|
||||
IMAGE CREATED CREATED BY SIZE COMMENT
|
||||
9c86d96dfba0 25 hours ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
|
||||
<missing> 25 hours ago EXPOSE map[443/tcp:{} 80/tcp:{}] 0B buildkit.dockerfile.v0
|
||||
<missing> 25 hours ago ADD games.tar.gz /usr/local/nginx/html/ # bu… 164MB buildkit.dockerfile.v0
|
||||
<missing> 25 hours ago RUN /bin/sh -c useradd -s /sbin/nologin ngin… 297kB buildkit.dockerfile.v0
|
||||
<missing> 25 hours ago RUN /bin/sh -c cd /usr/local/src/nginx-1.22.… 16.6MB buildkit.dockerfile.v0
|
||||
<missing> 25 hours ago ADD nginx-1.22.0.tar.gz /usr/local/src/ # bu… 6.46MB buildkit.dockerfile.v0
|
||||
<missing> 25 hours ago RUN /bin/sh -c yum install -y vim wget unzip… 323MB buildkit.dockerfile.v0
|
||||
<missing> 25 hours ago MAINTAINER Eagle_nls 2898485992@qq.com 0B buildkit.dockerfile.v0
|
||||
<missing> 16 months ago CMD ["/bin/bash"] 0B buildkit.dockerfile.v0
|
||||
<missing> 16 months ago ADD layer.tar.xz / # buildkit 176MB buildkit.dockerfile.v0
|
||||
```
|
||||
|
||||
如果想要缩小所构建镜像的大小,我们可以尝试少创建镜像层,在一层中多做一些事情,尽可能减少**RUN命令**
|
||||
|
||||
### 3. 数据卷
|
||||
|
||||
#### 3.1 什么是数据卷?
|
||||
|
||||
数据卷实际上就是宿主机上的目录或者是文件,可以被直接mount到容器当中使用。
|
||||
|
||||
实际生产环境中,需要针对不同类型的服务、不同类型的数据存储要求做相应的规划,最终保证服务的可扩展性、稳定性以及数据的安全性。
|
||||
|
||||

|
||||
|
||||
#### 3.2 数据卷案例
|
||||
|
||||
- 创建目录并准备页面
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# mkdir -p /data/web
|
||||
[root@docker-server1 ~]# echo 'eaglslab nginx test!' > /data/web/index.html
|
||||
[root@docker-server1 ~]# cat /data/web/index.html
|
||||
eaglslab nginx test
|
||||
```
|
||||
|
||||
- 启动两个容器并验证数据
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker run -d -it --name web1 -v /data/web/:/usr/share/nginx/html/ -p 8080:80 nginx
|
||||
588c494dc9098e0a43e15bce3162c34676dd981609edc32d46bf4beb59b9cf19
|
||||
[root@docker-server1 ~]# docker run -d -it --name web2 -v /data/web/:/usr/share/nginx/html/ -p 8081:80 nginx
|
||||
ff6b3731a9ba3e0f91d2c8d89bb6573eb5e5a9b840163bc1122a9e5678d108b7
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8080
|
||||
eaglslab nginx test!
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8081
|
||||
eaglslab nginx test!
|
||||
[root@docker-server1 ~]# echo 'hello world!' > /data/web/index.html
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8080
|
||||
hello world!
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8081
|
||||
hello world!
|
||||
```
|
||||
|
||||
- 进入到容器内测试写入数据
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker exec -it web1 bash
|
||||
root@588c494dc909:/# echo 'docker test!' > /usr/share/nginx/html/index.html
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8080
|
||||
docker test!
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8081
|
||||
docker test!
|
||||
```
|
||||
|
||||
- 尝试只读挂载
|
||||
|
||||
```bash
|
||||
# 删除容器的时候不会删除宿主机的目录
|
||||
[root@docker-server1 ~]# docker rm -fv web1
|
||||
web1
|
||||
[root@docker-server1 ~]# docker rm -fv web2
|
||||
web2
|
||||
[root@docker-server1 ~]# cat /data/web/index.html
|
||||
docker test!
|
||||
# 通过只读方式挂载以后,在容器内部是不允许修改数据的
|
||||
[root@docker-server1 ~]# docker run -d -it --name web1 -v /data/web/:/usr/share/nginx/html/:ro -p 8080:80 nginx
|
||||
a395b27958ca0cdcf52a86bd17813dcbcda4ed774895adcc99e85fc114ab84ff
|
||||
[root@docker-server1 ~]# docker exec -it web1 bash
|
||||
root@a395b27958ca:/# echo 123 > /usr/share/nginx/html/index.html
|
||||
bash: /usr/share/nginx/html/index.html: Read-only file system
|
||||
|
||||
```
|
||||
|
||||
- 文件挂载
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker run -d -it --name web2 -v /data/web/index.html:/usr/share/nginx/html/index.html:ro -p 8081:80 nginx
|
||||
4b34c957372d314cdb0f85d7e2c65b095615adfe3051ae6b4266b7bacd50f374
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8081
|
||||
docker test!
|
||||
```
|
||||
|
||||
#### 3.3 数据卷特点
|
||||
|
||||
1. 数据卷是宿主机的目录或者文件,并且可以在**多个容器之间共同使用**
|
||||
2. 在宿主机对数据卷更改数据后会在所有容器里面会**立即更新**
|
||||
3. 数据卷的数据可以**持久保存**,即使删除使用该数据卷卷的容器也不影响
|
||||
4. 在容器里面写入数据不会影响到镜像本身(**隔离性**)。
|
||||
5. 需要挂载多个目录或者文件的时候可以使用多个-v参数指定
|
||||
6. 数据卷使用场景包括日志输出、静态web页面、应用配置文件、多容器间目录或文件共享
|
||||
|
||||
#### 3.4 数据卷容器
|
||||
|
||||
##### 3.4.1 什么是数据卷容器
|
||||
|
||||
数据卷容器是一个普通的容器,专门用于提供数据卷供其他容器挂载。它允许用户创建一个专门用于数据存储的容器,并将其数据卷挂载到其他容器中。数据卷容器的主要用途是将数据卷的生命周期与应用容器分离,使数据可以在容器之间共享和持久化。
|
||||
|
||||
##### 3.4.2 数据卷容器的用途
|
||||
|
||||
1. **数据持久化**:数据卷容器可以确保数据即使在容器被删除后也不会丢失。例如,对于数据库应用,数据卷容器可以持久化数据库文件,避免因容器删除而导致数据丢失。
|
||||
2. **数据共享**:多个容器可以通过挂载同一个数据卷容器来共享数据。这在多容器应用中非常有用,例如在微服务架构中,多个服务容器可以共享数据库数据。
|
||||
3. **备份与恢复**:数据卷容器可以用于备份和恢复数据。通过将数据卷容器中的数据卷备份到宿主机或其他存储设备,可以在需要时恢复数据。
|
||||
4. **迁移数据**:数据卷容器可以方便地迁移数据。通过将数据卷容器中的数据卷迁移到其他主机,可以快速实现数据的迁移。
|
||||
|
||||
##### 3.4.3 数据卷容器与本地数据挂载的区别
|
||||
|
||||
| 特性 | 数据卷容器 | 本地数据挂载 |
|
||||
| :--------------------- | :----------------------------------------------------------- | :----------------------------------------------------------- |
|
||||
| **目录来源** | Docker 自动创建的目录 | 宿主机上已存在的目录 |
|
||||
| **适用场景** | 数据持久化、容器间共享数据 | 开发调试、快速文件同步 |
|
||||
| **容器间共享** | 支持 | 不支持 |
|
||||
| **宿主机文件系统依赖** | 无依赖 | 依赖宿主机文件系统 |
|
||||
| **数据持久化** | 数据卷的生命周期独立于容器,即使容器被删除,数据卷仍然存在 | 如果容器被删除,挂载的目录和文件仍然存在,但需要手动管理 |
|
||||
| **数据初始化** | 如果宿主机没有对应的文件,数据卷容器会自动将容器运行所需的文件复制到数据卷中 | 如果宿主机没有对应的文件,容器可能会因缺少运行所需的文件而出错 |
|
||||
| **数据覆盖** | 数据卷中的数据会覆盖容器内的数据 | 容器内的数据会覆盖宿主机上的数据 |
|
||||
|
||||
##### 3.4.4 实例演示
|
||||
|
||||
- 先启动一个卷容器Server
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker run -d --name nginx-web -v /data/web/:/usr/share/nginx/html/:ro -p 8081:80 nginx
|
||||
```
|
||||
|
||||
- 启动两个客户端容器
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker run -d --name web1 -p 8082:80 --volumes-from nginx-web nginx:latest
|
||||
ac22faa405ec07c065042465cd7f9d456be891effdd5d13d9571b96ef9c550f7
|
||||
[root@docker-server1 ~]# docker run -d --name web2 -p 8083:80 --volumes-from nginx-web nginx:latest
|
||||
e084845475b01dedfdae7362f6fbece7b5ab57ff6289c8c9bf08251f5ba448ed
|
||||
```
|
||||
|
||||
- 访问测试
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8081
|
||||
docker test!
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8082
|
||||
docker test!
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8083
|
||||
docker test!
|
||||
```
|
||||
|
||||
- 停止卷容器可以创建新容器
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker stop nginx-web
|
||||
nginx-web
|
||||
[root@docker-server1 ~]# docker run -d -it --name web3 -p 8084:80 --volumes-from nginx-web nginx:latest
|
||||
6ebd95c132ee1a9e4b43d1849efc628ca7185187a59d70b3816ff16dd47b6e8e
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8084
|
||||
docker test!
|
||||
```
|
||||
|
||||
- 删除卷容器之后不可以再创建新容器
|
||||
|
||||
```bash
|
||||
[root@docker-server1 ~]# docker rm -fv nginx-web
|
||||
nginx-web
|
||||
[root@docker-server1 ~]# docker run -d -it --name web4 -p 8085:80 --volumes-from nginx-web nginx:latest
|
||||
docker: Error response from daemon: No such container: nginx-web.
|
||||
See 'docker run --help'.
|
||||
# 但是之前已经创建好的容器不会有任何影响
|
||||
[root@docker-server1 ~]# curl 192.168.175.10:8082
|
||||
docker test!
|
||||
```
|
||||
|
||||
##### 3.4.5 总结
|
||||
|
||||
在当前环境下,即使把提供卷的容器Server删除,已经运行的容器Client依然可以使用挂载的卷,因为容器是通过挂载的方式访问数据的,但是无法创建新的卷容器客户端,但是再把卷容器Server创建后即可正常创建卷容器client,此方式可以用于线上共享数据目录等环境,因为即使数据卷容器被删除了,其他已经运行的容器依然可以挂载使用
|
||||
|
||||
数据卷容器可以作为共享的方式为其他容器提供文件共享,可以在容器生成中启动一个实例挂载本地的目录,然后其他的容器分别挂载此容器的目录,即可保证各个容器之间的数据一致性。
|
||||
|
Before Width: | Height: | Size: 20 KiB |
@@ -1,363 +0,0 @@
|
||||
# 06.Docker网络管理
|
||||
|
||||
## 06.Docker网络管理
|
||||
|
||||
### 1. 容器之间的互联
|
||||
|
||||
在同一个宿主机上的容器之间可以通过端口映射的方式,经过宿主机中转进行互相访问,也可以通过docker0网桥互相访问
|
||||
|
||||
#### 1.1 直接互联
|
||||
|
||||
- 启动两个容器
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -d -it nginx
|
||||
[root@localhost ~]# docker run -d -it nginx
|
||||
```
|
||||
|
||||
- 安装相关工具包
|
||||
|
||||
```bash
|
||||
root@855ab8d0bd74:/# apt update
|
||||
root@855ab8d0bd74:/# apt install net-tools -y
|
||||
root@855ab8d0bd74:/# apt install iputils-ping -y
|
||||
root@855ab8d0bd74:/# apt install procps -y
|
||||
|
||||
```
|
||||
|
||||
- 检测网络连通性
|
||||
|
||||
```bash
|
||||
root@855ab8d0bd74:/# ping 172.17.0.3 -c 2
|
||||
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
|
||||
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.052 ms
|
||||
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.081 ms
|
||||
|
||||
--- 172.17.0.3 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 1ms
|
||||
rtt min/avg/max/mdev = 0.052/0.066/0.081/0.016 ms
|
||||
```
|
||||
|
||||
#### 1.2 使用名称互联
|
||||
|
||||
- 启动两个容器
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -d -it --name web1 nginx:1.8
|
||||
[root@localhost ~]# docker run -d -it --name web2 --link web1 nginx:1.8
|
||||
```
|
||||
|
||||
- 查看web2容器的hosts文件,发现已经实现名称解析
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker exec -it web2 bash
|
||||
root@8a3e9cee9e37:/# cat /etc/hosts
|
||||
127.0.0.1 localhost
|
||||
::1 localhost ip6-localhost ip6-loopback
|
||||
fe00::0 ip6-localnet
|
||||
ff00::0 ip6-mcastprefix
|
||||
ff02::1 ip6-allnodes
|
||||
ff02::2 ip6-allrouters
|
||||
172.17.0.2 web1 622eff54876f
|
||||
172.17.0.3 8a3e9cee9e37
|
||||
```
|
||||
|
||||
- 连通性测试
|
||||
|
||||
```bash
|
||||
root@8a3e9cee9e37:/# ping web1 -c 2
|
||||
PING web1 (172.17.0.2) 56(84) bytes of data.
|
||||
64 bytes from web1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.068 ms
|
||||
64 bytes from web1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.045 ms
|
||||
|
||||
--- web1 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 1ms
|
||||
rtt min/avg/max/mdev = 0.045/0.056/0.068/0.013 ms
|
||||
```
|
||||
|
||||
#### 1.3 使用别名互联
|
||||
|
||||
自定义的容器名称可能后期会发生变化,那么一旦发生变化也会带来一些影响,这个时候如果每次都更改名称又比较麻烦,这个时候可以使用定义别名的方式解决,即容器名称可以随意更改,只要不更改别名即可。
|
||||
|
||||
- 启动一个容器
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -d -it --name web3 --link web1:nginx-web1 nginx:1.8
|
||||
```
|
||||
|
||||
- 查看容器web3的hosts文件
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker exec -it web3 bash
|
||||
root@c85c73ebf00b:/# cat /etc/hosts
|
||||
127.0.0.1 localhost
|
||||
::1 localhost ip6-localhost ip6-loopback
|
||||
fe00::0 ip6-localnet
|
||||
ff00::0 ip6-mcastprefix
|
||||
ff02::1 ip6-allnodes
|
||||
ff02::2 ip6-allrouters
|
||||
172.17.0.2 nginx-web1 622eff54876f web1
|
||||
172.17.0.4 c85c73ebf00b
|
||||
```
|
||||
|
||||
- 连通性测试
|
||||
|
||||
```bash
|
||||
root@c85c73ebf00b:/# ping nginx-web1 -c2
|
||||
PING nginx-web1 (172.17.0.2) 56(84) bytes of data.
|
||||
64 bytes from nginx-web1 (172.17.0.2): icmp_seq=1 ttl=64 time=0.112 ms
|
||||
64 bytes from nginx-web1 (172.17.0.2): icmp_seq=2 ttl=64 time=0.055 ms
|
||||
|
||||
--- nginx-web1 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 2ms
|
||||
rtt min/avg/max/mdev = 0.055/0.083/0.112/0.029 ms
|
||||
|
||||
```
|
||||
|
||||
### 2. Docker网络
|
||||
|
||||
#### 2.1 四类网络模式
|
||||
|
||||
| Docker网络模式 | 配置 | 说明 |
|
||||
| -------------- | ------------------------- | ------------------------------------------------------------ |
|
||||
| host模式 | –net=host | 容器和宿主机共享Network namespace。 |
|
||||
| container模式 | –net=container:NAME_or_ID | 容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。 |
|
||||
| none模式 | –net=none | 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。 |
|
||||
| bridge模式 | –net=bridge | (默认为该模式) |
|
||||
|
||||
Docker服务安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡,其ip地址都是172.17.0.1/16,并且会生成三种不同类型的网络
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# ifconfig
|
||||
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
|
||||
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
|
||||
ether 02:42:14:75:bf:4c txqueuelen 0 (Ethernet)
|
||||
RX packets 0 bytes 0 (0.0 B)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 0 bytes 0 (0.0 B)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 192.168.80.10 netmask 255.255.255.0 broadcast 192.168.80.255
|
||||
inet6 fe80::eaf3:dc40:2bf:6da2 prefixlen 64 scopeid 0x20<link>
|
||||
ether 00:0c:29:f4:79:06 txqueuelen 1000 (Ethernet)
|
||||
RX packets 13079 bytes 18637594 (17.7 MiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 1747 bytes 124995 (122.0 KiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
|
||||
inet 127.0.0.1 netmask 255.0.0.0
|
||||
inet6 ::1 prefixlen 128 scopeid 0x10<host>
|
||||
loop txqueuelen 1 (Local Loopback)
|
||||
RX packets 72 bytes 5776 (5.6 KiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 72 bytes 5776 (5.6 KiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
[root@localhost ~]# docker network list
|
||||
NETWORK ID NAME DRIVER SCOPE
|
||||
787342a0d883 bridge bridge local
|
||||
9a6d7244e807 host host local
|
||||
beace8354cca none null local
|
||||
```
|
||||
|
||||
在启动容器的时候可以使用--network参数去指定网络类型,默认使用的是bridge网络类型
|
||||
|
||||
#### 2.2 none网络类型
|
||||
|
||||
在使用none模式后,docker容器**不会进行任何网络配置**,其没有网卡、没有ip也没有路由,因此默认无法与外界进行通信,需要手动添加网卡配置ip等,所以**极少使用**
|
||||

|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -d -it --name web4 --network none nginx:1.8
|
||||
```
|
||||
|
||||
#### 2.3 container网络类型
|
||||
|
||||
这个模式指定新创建的容器和**已经存在的一个容器共享**一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡(环回接口)设备通信。
|
||||
|
||||

|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -d -it --name web5 --network container:web1 nginx
|
||||
83db4f9af6f3d9d42bbd57691fcf82ef06cbf1a5874750effa314a4ec242aaaa
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 2.4 host网络类型
|
||||
|
||||
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是**使用宿主机的IP和端口。**
|
||||
|
||||
使用host模式的容器可以直接使用宿主机的IP地址与外界通信**,容器内部的服务端口也可以使用宿主机的端口**,不需要进行NAT,host最大的优势就是**网络性能比较好**,但是docker host上已经使用的端口就不能再用了,**网络的隔离性不好。**
|
||||
|
||||

|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -d -it --name web7 --network host nginx
|
||||
e90cb3bfc1a3fbd187319ac3b995b116feb37422534b03662d624680e35eb2bb
|
||||
[root@localhost ~]# docker exec -it web7 bash
|
||||
root@localhost:/# ifconfig
|
||||
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
|
||||
inet6 fe80::42:14ff:fe75:bf4c prefixlen 64 scopeid 0x20<link>
|
||||
ether 02:42:14:75:bf:4c txqueuelen 0 (Ethernet)
|
||||
RX packets 9647 bytes 394222 (384.9 KiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 10932 bytes 43303360 (41.2 MiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 192.168.175.10 netmask 255.255.255.0 broadcast 192.168.175.255
|
||||
inet6 fe80::eaf3:dc40:2bf:6da2 prefixlen 64 scopeid 0x20<link>
|
||||
ether 00:0c:29:f4:79:06 txqueuelen 1000 (Ethernet)
|
||||
RX packets 60855 bytes 81177548 (77.4 MiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 17770 bytes 1472014 (1.4 MiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
|
||||
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
|
||||
inet 127.0.0.1 netmask 255.0.0.0
|
||||
inet6 ::1 prefixlen 128 scopeid 0x10<host>
|
||||
loop txqueuelen 1 (Local Loopback)
|
||||
RX packets 72 bytes 5776 (5.6 KiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 72 bytes 5776 (5.6 KiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 2.5 bridge网络类型(默认)
|
||||
|
||||
当Docker进程启动时,会在主机上创建一个名为**docker0的虚拟网桥**,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
|
||||
|
||||
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
|
||||
|
||||
bridge模式是docker的**默认网络模式**,不写--network参数,就是bridge模式。**使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。**
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
### 3. 创建自定义网络
|
||||
|
||||
可以基于docker命令创建自定义网络,自定义网络可以自定义ip地址范围和网关等信息。
|
||||
|
||||
- 创建一个网络
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker network create -d bridge --subnet 10.10.0.0/16 --gateway 10.10.0.1 eagleslab-net
|
||||
74ee6ecdfc0382ac0abb1b46a3c90e3c6a39f0b7388aa9ba99fddc6bac72e8ce
|
||||
[root@localhost ~]# docker network list
|
||||
NETWORK ID NAME DRIVER SCOPE
|
||||
787342a0d883 bridge bridge local
|
||||
74ee6ecdfc03 eagleslab-net bridge local
|
||||
9a6d7244e807 host host local
|
||||
beace8354cca none null local
|
||||
```
|
||||
|
||||
- 使用自定义网络创建容器
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -d -it --name web8 --network eagleslab-net nginx
|
||||
```
|
||||
|
||||
- 检查网络
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker exec -it web8 bash
|
||||
root@a7edddb4114e:/# ifconfig
|
||||
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
|
||||
inet 10.10.0.2 netmask 255.255.0.0 broadcast 10.10.255.255
|
||||
ether 02:42:0a:0a:00:02 txqueuelen 0 (Ethernet)
|
||||
RX packets 1064 bytes 8764484 (8.3 MiB)
|
||||
RX errors 0 dropped 0 overruns 0 frame 0
|
||||
TX packets 738 bytes 41361 (40.3 KiB)
|
||||
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
|
||||
root@a7edddb4114e:/# ping www.baidu.com -c2
|
||||
PING www.a.shifen.com (112.34.112.83) 56(84) bytes of data.
|
||||
64 bytes from 112.34.112.83 (112.34.112.83): icmp_seq=1 ttl=127 time=37.8 ms
|
||||
64 bytes from 112.34.112.83 (112.34.112.83): icmp_seq=2 ttl=127 time=36.9 ms
|
||||
|
||||
--- www.a.shifen.com ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 3ms
|
||||
rtt min/avg/max/mdev = 36.865/37.320/37.776/0.494 ms
|
||||
|
||||
```
|
||||
|
||||
- iptables会生成nat的相应规则
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# iptables -t nat -vnL
|
||||
Chain PREROUTING (policy ACCEPT 12 packets, 759 bytes)
|
||||
pkts bytes target prot opt in out source destination
|
||||
2 136 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
|
||||
|
||||
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
|
||||
pkts bytes target prot opt in out source destination
|
||||
|
||||
Chain OUTPUT (policy ACCEPT 1 packets, 76 bytes)
|
||||
pkts bytes target prot opt in out source destination
|
||||
0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
|
||||
|
||||
Chain POSTROUTING (policy ACCEPT 1 packets, 76 bytes)
|
||||
pkts bytes target prot opt in out source destination
|
||||
12 759 MASQUERADE all -- * !br-74ee6ecdfc03 10.10.0.0/16 0.0.0.0/0
|
||||
32 1940 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
|
||||
|
||||
Chain DOCKER (2 references)
|
||||
pkts bytes target prot opt in out source destination
|
||||
0 0 RETURN all -- br-74ee6ecdfc03 * 0.0.0.0/0 0.0.0.0/0
|
||||
1 84 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
|
||||
```
|
||||
|
||||
### 4. Docker一键搭建typecho博客
|
||||
|
||||
镜像选择:**80x86/typecho:latest**
|
||||
|
||||
一、部署容器
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -d \
|
||||
--name=typecho \
|
||||
--restart always \
|
||||
-e PHP_TZ=Asia/Shanghai \
|
||||
-e PHP_MAX_EXECUTION_TIME=600 \
|
||||
-p 80:80 80x86/typecho:latest
|
||||
|
||||
[root@localhost ~]# ss -nlt
|
||||
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
|
||||
LISTEN 0 4096 0.0.0.0:80 0.0.0.0:*
|
||||
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
|
||||
LISTEN 0 4096 [::]:80 [::]:*
|
||||
LISTEN 0 128 [::]:22 [::]:*
|
||||
```
|
||||
|
||||
二、浏览器访问初始化博客
|
||||
|
||||

|
||||
|
||||
三、完善信息,数据库选择内置的SQL Lite方便一点
|
||||
|
||||

|
||||
|
||||
四、安装完成
|
||||
|
||||

|
||||
|
||||
五、更改主题,默认带了几个主题
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 1.8 MiB |
@@ -1,332 +0,0 @@
|
||||
# 07.Docker资源限制
|
||||
|
||||
## 07.Docker资源限制
|
||||
|
||||
### 1. Docker 容器资源限制与 OOM 异常处理
|
||||
|
||||
#### 1.1 容器资源限制
|
||||
|
||||
默认情况下,容器没有资源限制,可以使用主机内核调度程序允许的尽可能多的给定资源。Docker 提供了控制容器可以使用多少内存或者 CPU 的方法,通过设置 `docker run` 命令的运行时配置标志来实现。
|
||||
|
||||
其中一些功能要求宿主机的内核支持 Linux 功能。要检查支持情况,可以使用 `docker info` 命令。如果内核中禁用了某项功能,可能会在输出结尾处看到警告。
|
||||
|
||||
#### 1.2 OOM 异常
|
||||
|
||||
对于 Linux 主机,如果没有足够的内存来执行其他重要的系统任务,将会抛出 OOM 异常(内存溢出、内存泄漏、内存异常)。随后系统会开始杀死进程以释放内存,凡是运行在宿主机上的进程都有可能被 kill,包括 `dockerd` 和其他的应用程序。如果重要的系统进程被 kill,会导致和该进程相关的服务全部宕机。
|
||||
|
||||
产生 OOM 异常时,`dockerd` 会尝试通过调整 Docker 守护程序上的 OOM 优先级来减轻这些风险,以便它比系统上的其他进程更不可能被杀死。但是,容器的 OOM 优先级未调整时,单个容器被杀死的可能性更大(不推荐调整容器的优先级这种方式)。
|
||||
|
||||
#### 1.3 Linux 进程 OOM 评分机制
|
||||
|
||||
Linux 会为每个进程计算一个分数,最终它会将分数最高的进程 kill 掉。相关文件说明如下:
|
||||
|
||||
- `/proc/PID/oom_score_adj`
|
||||
- 范围为 -1000 到 1000。
|
||||
- 值越高越容易被宿主机 kill 掉。
|
||||
- 如果将该值设置为 -1000,则进程永远不会被宿主机 kernel kill。
|
||||
- `/proc/PID/oom_adj`
|
||||
- 范围为 -17 到 +15。
|
||||
- 取值越高越容易被干掉。
|
||||
- 如果是 -17,则表示不能被 kill。
|
||||
- 该设置参数的存在是为了和旧版本的 Linux 内核兼容。
|
||||
- `/proc/PID/oom_score`
|
||||
- 这个值是系统综合进程的内存消耗量、CPU 时间(`utime + stime`)、存活时间(`uptime - start time`)和 `oom_adj` 计算出的进程得分。
|
||||
- 消耗内存越多得分越高,越容易被宿主机 kernel 强制杀死。
|
||||
|
||||
### 2. 容器的内存限制
|
||||
|
||||
Docker可以强制执行**硬性内存限制**,即只允许容器使用给定的内存大小
|
||||
|
||||
Docker也可以执行**非硬性内存限制**,即容器可以使用尽可能多的内存,除非内核检测到主机上的内存不够用了
|
||||
|
||||
#### 2.1 内存限制参数
|
||||
|
||||
##### 2.1.1 `-m` 或 `--memory`
|
||||
|
||||
- **功能**:限制容器最大可用内存。
|
||||
|
||||
- **最小值**:4m。
|
||||
|
||||
- **示例**:
|
||||
|
||||
```bash
|
||||
docker run -m 512m my_image
|
||||
```
|
||||
|
||||
##### 2.1.2 `--memory-swap`
|
||||
|
||||
- **功能**:限制容器可用的内存 + swap 总量。
|
||||
|
||||
- **前提**:需先设置 `--memory`。
|
||||
|
||||
- **特殊值**:`-1` 表示不限制 swap 使用。
|
||||
|
||||
- **示例**:
|
||||
|
||||
```bash
|
||||
docker run --memory 256m --memory-swap 512m my_image
|
||||
```
|
||||
|
||||
##### 2.1.3 `--memory-swappiness`
|
||||
|
||||
- **功能**:控制容器使用 swap 的倾向性。
|
||||
|
||||
- **范围**:0(尽量不使用 swap)到 100(尽量使用 swap)。
|
||||
|
||||
- **示例**:
|
||||
|
||||
```bash
|
||||
docker run --memory-swappiness 30 my_image
|
||||
```
|
||||
|
||||
##### 2.1.4 `--kernel-memory`
|
||||
|
||||
- **功能**:限制容器使用的内核内存。
|
||||
|
||||
- **最小值**:4m。
|
||||
|
||||
- **注意事项**:不推荐设置,可能影响宿主机和其他容器。
|
||||
|
||||
- **示例**:
|
||||
|
||||
```bash
|
||||
docker run --kernel-memory 64m my_image
|
||||
```
|
||||
|
||||
##### 2.1.5 `--memory-reservation`
|
||||
|
||||
- **功能**:设置软内存限制,低于 `--memory`。
|
||||
|
||||
- **激活条件**:主机内存争用或不足时生效。
|
||||
|
||||
- **注意事项**:必须小于 `--memory`,且不保证容器一定不超过此限制。
|
||||
|
||||
- **示例**:
|
||||
|
||||
```bash
|
||||
docker run --memory 1g --memory-reservation 512m my_image
|
||||
```
|
||||
|
||||
##### 2.1.6 `--oom-kill-disable`
|
||||
|
||||
- **功能**:禁止 OOM 时杀死容器内进程。
|
||||
|
||||
- **前提**:必须与 `--memory` 一起使用。
|
||||
|
||||
- **注意事项**:若未设置 `--memory`,OOM 时仍可能杀死进程。
|
||||
|
||||
- **示例**:
|
||||
|
||||
```bash
|
||||
docker run --memory 512m --oom-kill-disable my_image
|
||||
```
|
||||
|
||||
#### 2.2 内从限制案例
|
||||
|
||||
如果一个容器未作内存使用限制,则该容器可以利用到系统内存最大空间,默认创建的容器没有做内存资源限制
|
||||
|
||||
一、拉取容器压测工具镜像
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker pull tylersmith22/docker-stress-ng
|
||||
[root@localhost ~]# docker run -it --rm tylersmith22/docker-stress-ng -help
|
||||
```
|
||||
|
||||
二、使用压测工具开启两个工作进程,每个工作进程最大允许使用内存256M,且宿主机不限制当前容器的最大内存
|
||||
|
||||
```bash
|
||||
[root@localhost nginx]# docker run -it --rm --name test1 tylersmith22/docker-stress-ng --vm 2 --vm-bytes 256m
|
||||
stress-ng: info: [1] defaulting to a 86400 second run per stressor
|
||||
stress-ng: info: [1] dispatching hogs: 2 vm
|
||||
|
||||
# 新建窗口查看
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
3ca32774fc20 test1 185.16% 514.3MiB / 1.781GiB 28.21% 648B / 0B 0B / 0B 5
|
||||
|
||||
# 可以看到容器的内存占用大概为256的两倍,因为两个进程
|
||||
```
|
||||
|
||||
三、宿主机限制最大内存使用
|
||||
|
||||
```bash
|
||||
[root@localhost nginx]# docker run -it --rm -m 256m --name test2 tylersmith22/docker-stress-ng --vm 2 --vm-bytes 256m
|
||||
stress-ng: info: [1] defaulting to a 86400 second run per stressor
|
||||
stress-ng: info: [1] dispatching hogs: 2 vm
|
||||
|
||||
# 新建窗口查看
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
d612ce9b0776 test2 0.00% 255.9MiB / 256MiB 99.97% 1.02kB / 126B 4.83GB / 36.8GB 5
|
||||
```
|
||||
|
||||
#### 2.3 **内存软限制**
|
||||
|
||||
软限制不会真正限制到内存的使用
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -it --rm -m 256m --memory-reservation 128m --name test1 tylersmith22/docker-stress-ng --vm 2 --vm-bytes 256m
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
0ffb4b8fdbde test1 174.52% 255.9MiB / 256MiB 99.95% 648B / 0B 5.33GB / 18.1GB 5
|
||||
```
|
||||
|
||||
**交换分区限制**
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -it --rm -m 256m --memory-swap 512m --name test1 tylersmith22/docker-stress-ng --vm 2 --vm-bytes 256m
|
||||
```
|
||||
|
||||
### 3. 容器的CPU限制
|
||||
|
||||
一个宿主机,有几十个核心的cpu,但是宿主机上可以同时运行成百上千个不同的进程用以处理不同的任务,多进程共用一个cpu的核心依赖计数就是为可压缩资源,即一个核心cpu可以通过调度而运行多个进程,但是在同一个单位时间内只能由一个进程在cpu上运行,那么这么多的进程怎么在cpu上执行和调度的呢?(进程优先级)
|
||||
|
||||
默认情况下,每个容器对主机cpu周期的访问权限是不受限制的,但是我们可以人为干扰
|
||||
|
||||
#### 3.1 CPU限制参数
|
||||
|
||||
##### 3.1.1 `--cpus`
|
||||
|
||||
- **功能**:指定容器可以使用的 CPU 资源数量。
|
||||
|
||||
- **示例**:主机有 2 个 CPU,设置 `--cpus=1.5`,容器最多可使用 1.5 个 CPU。
|
||||
|
||||
- **示例命令**:
|
||||
|
||||
```bash
|
||||
docker run --cpus 1.5 my_image
|
||||
```
|
||||
|
||||
##### 3.1.2 `--cpu-period` 和 `--cpu-quota`
|
||||
|
||||
- **功能**:设置 CPU 调度周期和配额。
|
||||
|
||||
- **关系**:必须一起使用,计算方式为 `cpu-quota / cpu-period`。
|
||||
|
||||
- **示例**:
|
||||
|
||||
```bash
|
||||
docker run --cpu-period 100000 --cpu-quota 50000 my_image
|
||||
```
|
||||
|
||||
##### 3.1.3 `--cpuset-cpus`
|
||||
|
||||
- **功能**:指定容器运行的 CPU 编号(绑核)。
|
||||
|
||||
- **示例**:限制容器在 CPU 0 和 CPU 1 上运行。
|
||||
|
||||
- **示例命令**:
|
||||
|
||||
```bash
|
||||
docker run --cpuset-cpus 0,1 my_image
|
||||
```
|
||||
|
||||
##### 3.1.4 `--cpuset-mems`
|
||||
|
||||
- **功能**:设置容器使用的内存节点(仅对 NUMA 架构有效)。
|
||||
|
||||
- **示例**:限制容器使用内存节点 0。
|
||||
|
||||
- **示例命令**:
|
||||
|
||||
```bash
|
||||
docker run --cpuset-mems 0 my_image
|
||||
```
|
||||
|
||||
##### 3.1.5 `--cpu-shares`
|
||||
|
||||
- **功能**:设置容器的 CPU 时间片权重。
|
||||
|
||||
- **默认值**:1024。
|
||||
|
||||
- **范围**:最小 2,最大 262144。
|
||||
|
||||
- **示例**:容器 A 设置为 1024,容器 B 设置为 2048,容器 B 的 CPU 时间片是容器 A 的两倍。
|
||||
|
||||
- **示例命令**:
|
||||
|
||||
```bash
|
||||
docker run --cpu-shares 2048 my_image
|
||||
```
|
||||
|
||||
#### 3.2 CPU限制案例
|
||||
|
||||
##### 3.2.1 **未限制容器cpu**
|
||||
|
||||
- 启动1个进程,占用4核cpu,未限制容器会把cpu全部占完
|
||||
|
||||
```bash
|
||||
# 查看我们宿主机的cup数量
|
||||
[root@localhost ~]# top
|
||||
top - 21:32:49 up 43 min, 2 users, load average: 3.54, 1.82, 0.80
|
||||
Tasks: 186 total, 1 running, 185 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.5 hi, 0.0 si, 0.0 st
|
||||
%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
|
||||
[root@localhost ~]# docker run -it --rm --name test1 tylersmith22/docker-stress-ng --vm 1 --cpu 4
|
||||
stress-ng: info: [1] defaulting to a 86400 second run per stressor
|
||||
stress-ng: info: [1] dispatching hogs: 4 cpu, 1 vm
|
||||
|
||||
# 新建窗口查看
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
c6a795e4c09f test1 396.78% 282.6MiB / 1.703GiB 16.21% 876B / 126B 0B / 0B 7
|
||||
|
||||
# 可以看出CPU的使用率大概是400% 因为我们是4个核心,单个核心跑满是100%
|
||||
```
|
||||
|
||||
##### 3.2.2 **限制容器cpu**
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -it --rm --cpus 2 --name test1 tylersmith22/docker-stress-ng --vm 1 --cpu 4
|
||||
stress-ng: info: [1] defaulting to a 86400 second run per stressor
|
||||
stress-ng: info: [1] dispatching hogs: 4 cpu, 1 vm
|
||||
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
5b7dcb36d738 test1 200.65% 279.7MiB / 1.703GiB 16.04% 876B / 126B 0B / 0B 7
|
||||
|
||||
[root@localhost ~]# top
|
||||
top - 21:36:15 up 47 min, 3 users, load average: 1.38, 1.92, 1.05
|
||||
Tasks: 198 total, 8 running, 190 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu0 : 50.7 us, 1.4 sy, 0.0 ni, 47.2 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
|
||||
%Cpu1 : 52.9 us, 0.0 sy, 0.0 ni, 47.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
%Cpu2 : 50.7 us, 0.0 sy, 0.0 ni, 48.6 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
|
||||
%Cpu3 : 50.4 us, 0.0 sy, 0.0 ni, 48.9 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
|
||||
|
||||
# 并且是平均使用所有的cup核心
|
||||
```
|
||||
|
||||
##### 3.2.3 将容器运行到指定的cpu上
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -it --rm --cpus 2 --cpuset-cpus 0,2 --name test1 tylersmith22/docker-stress-ng --vm 1 --cpu 4
|
||||
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
ee11d834dde5 test1 186.68% 1.488GiB / 1.781GiB 83.60% 648B / 0B 44.8GB / 95.7MB 25
|
||||
|
||||
[root@localhost ~]# top
|
||||
top - 21:38:25 up 49 min, 3 users, load average: 0.92, 1.40, 0.96
|
||||
Tasks: 197 total, 6 running, 191 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu0 : 97.3 us, 2.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
|
||||
%Cpu1 : 0.3 us, 0.0 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
|
||||
%Cpu2 : 98.3 us, 1.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.7 hi, 0.0 si, 0.0 st
|
||||
%Cpu3 : 0.0 us, 0.3 sy, 0.0 ni, 99.3 id, 0.0 wa, 0.3 hi, 0.0 si, 0.0 st
|
||||
MiB Mem : 1743.4 total, 457.2 free, 924.2 used, 531.4 buff/cache
|
||||
MiB Swap: 2048.0 total, 2047.2 free, 0.8 used. 819.2 avail Mem
|
||||
```
|
||||
|
||||
- 基于cpu-shares对cpu进行切分
|
||||
|
||||
```bash
|
||||
[root@localhost ~]# docker run -it --rm -d --cpu-shares 1000 --name test1 tylersmith22/docker-stress-ng --vm 1 --cpu 4
|
||||
[root@localhost ~]# docker run -it --rm -d --cpu-shares 500 --name test2 tylersmith22/docker-stress-ng --vm 1 --cpu 4
|
||||
|
||||
[root@localhost ~]# docker stats
|
||||
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
|
||||
d6dd34edb722 test1 543.41% 819.6MiB / 1.781GiB 44.95% 648B / 0B 102MB / 154MB 13
|
||||
154b07a94e2f test2 241.15% 711.1MiB / 1.781GiB 39.00% 648B / 0B 406MB / 145MB
|
||||
```
|