⼀、Docker
1、Docker介绍.pdf
1、Docker 是什么?
Docker 是⼀个开源的应⽤容器引擎,可以实现虚拟化,完全采⽤"沙
盒"机制,容器之间不会存在任何接⼝。
Docker 通过 Linux Container(容器)技术将任意类型的应⽤进⾏包
装,变成⼀种轻量级、标准化、可移植、⾃管理的组件。在包装应
⽤的同时,可连带该应⽤的依赖和环境⼀并进⾏打包,所以可以将
这种"包"移植到任意环境去运⾏,省去兼容性的问题。
2、Docker 和虚拟机的区别
Docker和虚拟机在以下⼋个⽅⾯存在差异:1. **启动速度:**Docker 启动速度⾮常快,属于秒级别,⽽虚拟机通
常需要⼏分钟去启动。
2. **资源消耗:**Docker 需要的资源更少,它直接运⾏在宿主机的内
核上,以⼀系列进程的结合形式存在。⽽虚拟机则需要消耗更多
的资源,因为它在操作系统级别进⾏虚拟化。
3. **轻量级:**Docker 更轻量,它的架构可以共⽤⼀个内核与共享应
⽤程序库,所占内存极⼩。⽽虚拟机则相对较重,需要消耗更多
的内存。
4. **隔离性:**虚拟机可以实现系统级别的隔离,⽽ Docker 则属于进
程之间的隔离,隔离性相对较弱。
5. **安全性:**Docker 的安全性也更弱。
6. **可管理性:**Docker 的集中化管理⼯具还不算成熟。
7. **兼容性:**开发⼈员不需要关系具体是哪个 Linux 操作系统,基本
市⾯上主流系统都可使⽤ Docker。
8. **数据持久性:**Docker ⽆法存储数据,当容器重启后,数据会消
失;⽽虚拟机可以存储各种数据,包括⽇志、数据库等。
3、Docker 解决的问题
(1)系统环境不⼀致问题
环境不同时可能会出现的环境问题:使⽤ docker 容器时:
将简易的操作系统、编写好的代码、部署完成的应⽤服务配置等打
包放到容器内,再转到鲸⻥上,由鲸⻥送到服务器,此时,⽆论是
什么运⾏环境,docker 容器都可以运⾏。(2)应⽤隔离问题
Linux 是⼀个⽀持多⽤户的操作系统,正因如此,可能会造成⽤户使
⽤时,互相之间占⽤资源过多,以致于服务器资源空间不⾜,⽽
docker 具有隔离性,可以在启动时就限定好硬件的使⽤率,当某个
容器到达或超过限定的阈值时,就会被 kill,此时需要运维⼈员对其
进⾏调试。
(3)服务器扩展问题
⽇常的业务量⼤多很平均,但在业务量繁多时期,⽐如"双⼗⼀",
"春运购票"等场景,就需要对服务器进⾏横向扩展才能将负载均衡下
来,⽽如果⼤规模地扩展服务器,待服务器满载时期过去,回到⽇
常业务量后,就会导致剩余资源极⼤地浪费。并且在扩展时,还要
对各种应⽤服务进⾏部署、调试等,⼯作量也⼗分庞⼤,所以,此
时使⽤ Docker 将会真正意义上实现快速部署,且耗费资源较少,尤
其不会出现兼容性的问题。
4、Docker 的优缺点
(1)优点
- **体积⼩:**减⼩系统的开销值,⼀台主机可以运⾏上千个容器。
- **启动迅捷:**更快速的交付和部署,docker容器 ,⽐传统虚拟机
要快很多,docker核⼼解决的问题就是利⽤容器实现VM类似的
功能。3. **操作⽅便:**通过配置 dockerfile 便⽀持灵活的⾃动化创建和部
署。 - **更轻松的扩展:**可以实现更简单的、更可靠的迁移,避免了兼容
性等问题。 - 更强的可扩展性和可移植性。
(2)缺点 - **安全问题:**如果没有正确配置,⼀个容器中的恶意代码可能会影
响到主机上的其他容器以及主机本身的安全。 - **存储问题:**当使⽤⼤量容器时,存储和管理容器映像可以变得⾮
常困难。这可能需要使⽤分布式存储或其他解决⽅案来管理⼤量
容器的存储。 - **性能问题:**在某些情况下,容器和虚拟机相⽐会导致性能损失。
这些性能问题越来越少,但是仍然需要考虑。 - **⽹络问题:**Docker 可能会在⽹络配置上存在⼀些问题,这可能
需要更多的时间来诊断和解决。 - **复杂性:**Docker 是⼀个⾮常灵活的系统,但这同时也让它更加
复杂。⻓时间使⽤ Docker 会产⽣⼤量的脚本和配置⽂件,这些
可能变得难以维护。 - **资源消耗:**使⽤ Docker 必须占⽤⼀些资源,包括 CPU、内
存、磁盘等等。如果运⾏容器的主机资源不⾜,可能会导致性能
问题。7. **学习曲线:**Docker 是⼀个相对新的技术,相⽐传统环境需要⼀
定的学习曲线。需要了解Docker 基本概念、命令和配置⽂件
等。 - **需要花费时间配置和管理:**使⽤ Docker 需要花时间配置和管理
容器集群和应⽤程序。需要配置每个容器,管理 Jenkins、
Kubernetes 等运⾏ Docker 容器的⼯具。 - **映像构建复杂:**构建Docker映像需要按照特定格式编写
Dockerfile 脚本,需要遵循⼀定的规范和流程,这可能需要更多
的时间和精⼒。
5、Docker 架构 - ⽤ docker pull 命令从 hub.docker.com 官⽹上下载 images (镜
像)。2. 可以⽤ docker save 命令将镜像保存到本地 tar ⽂件,也可以⽤
docker load 命令将本地tar ⽂件导⼊镜像。 - 可以⽤ docker build 构建 Dockerfile 镜像。
- 可以⽤ docker run 和 docker create 将镜像运⾏成 container
(容器),容器内可以安装所需要的 APP。 - 可以⽤ docker commit/export 将容器做成镜像反复的使⽤。
- 可以将⾃⼰制作的镜像发布到 hub.docker.com ⽹站,需要注册
账号。
6、Docker 核⼼概念 - 镜像(images):⼀个⾯向 docker 容器引擎的只读模板,也
是容器的基础,类似于 iso 镜像⽂件。 - **容器(container):**基于镜像所创建的虚拟实例,相当于⼀个
简易的 Linux 环境,可启停,且多个容器之间互相隔离。 - **仓库(Repository):**集中存放 docker 镜像的位置,可使⽤
docker pull 或 push 命令下载或上传到私有或公有仓库。 - **仓库注册服务器(registry):**存放仓库的地⽅,如果没有私有
仓库,则使⽤公共仓库 docker hub。
7、Docker 特性
**⽂件系统隔离:每个进程容器运⾏在⼀个完全独⽴的根⽂件系统
⾥。
资源隔离: 实现不同的容器的资源配额和调度,cgroup。⽹络隔离:**每个进程容器运⾏在⾃⼰的⽹络空间,拥有虚拟接⼝
和 IP 地址。
**⽇志记录:**Docker将收集到和记录的每个进程容器的标准流
(stdout/stderr/stdin),⽤于实时检索或者批量检索。
**变更管理:**容器⽂件系统的变更可以提交到新的镜像中,并可重
复使⽤以创建更多的容器。
**交互式shell:**Docker可以分配⼀个虚拟终端并且关联到任何容
器的标准输出上,例如运⾏⼀个⼀次性交互shell。
⼆、安装 Docker
1、Docker 要求2、安装 Docker
root@doc \~\]# cat \<\< EOF \| tee /etc/modules load.d/k8s.conf \> overlay \> br_netfilter \> EOF \[root@doc \~\]# modprobe overlay # 加载overlay内核 模块 \[root@doc \~\]# modprobe br_netfilter # 加载 br_netfilter内核模块\[root@doc \~\]# cat \<\< EOF \| tee /etc/sysctl.d/k8s.conf \> net.bridge.bridge-nf-call-iptables = 1 \> net.bridge.bridge-nf-call-ip6tables = 1 \> net.ipv4.ip_forward = 1 \> EOF net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 \[root@doc \~\]# sysctl --system \[root@doc \~\]# yum install -y yum-utils device mapper-persistent-data lvm2 \[root@doc \~\]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker ce/linux/centos/docker-ce.repo # 添加阿⾥云yum源 \[root@doc \~\]# yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose plugin -y --allowerasing # 安装docker,allowerasing:允许卸载旧版本 **overlay:**是⼀种⽂件系统层叠技术,常⽤于容器化平台(⽐如 Docker)中。它允许将多个⽂件系统叠加在⼀起,从⽽创建⼀个 统⼀可⻅的⽂件系统。通过加载 overlay 模块,可以在 Linux 系 统中使⽤ overlay ⽂件系统,并且它将提供⼀些额外的功能,⽐ 如联合挂载、⽂件层叠等。 **br_netfilter:**Linux 内核中的⼀个模块,它提供了桥接设备(bridge device) 和⽹络过滤器(netfilter) 之间的集成。它允许在桥 接设备上使⽤⽹络过滤器功能,如防⽕墙规则、⽹络地址转换 (NAT) 等。通过加载 br_netfilter 模块,你可以在 Linux 系统中的 桥接设备上应⽤⽹络过滤规则对⽹络流量进⾏管理和控制。 **device-mapper-persistent-data:**⼀个Linux内核模块,它为 Device Mapper设备提供持久存储功能。DMPD提供了⼀个⽤于 存储映射关系的数据库,使得Device Mapper可以持久化存储映 射数据,以便在系统重新启动后仍然可以恢复之前的映射关系。 **lvm2:**Linux系统下的逻辑卷管理⼯具,LVM 的升级版,它是对 磁盘分区进⾏管理的⼀种机制,建⽴在硬盘和分区之上的⼀个逻 辑层,⽤来提⾼磁盘管理的灵活性。 **3、设置阿⾥云镜像加速器** **阿⾥云官⽹:**https://www.aliyun.com/ **登录后点击控制台**控制台搜索"容器镜像服务ACR" **点击红框位置镜像⼯具⾃⼰的加速器地址:红框内代码复制到终端(每个⼈的不⼀样,要复制⾃⼰)命令** **解释** docker login(logout) 登录(登出) docker hub 账户,也可以指定某 个私有仓库登录,⽐如"docker login 私有仓 库地址 -u 登录⽤户" **三、Docker 基本操作** **1、镜像操作** \[root@doc \~\]# sudo mkdir -p /etc/docker \[root@doc \~\]# sudo tee /etc/docker/daemon.json \<\<- 'EOF' \> { \> "registry-mirrors": \["https://9ghz4eu4.mirror.aliyuncs.com"
> }
> EOF
{
"registry-mirrors":
"https://9ghz4eu4.mirror.aliyuncs.com"
}
root@doc \~\]# sudo systemctl daemon-reload \[root@doc \~\]# sudo systemctl restart docker \[root@doc \~\]# docker info \| grep "https" # 查看 ⾃⼰的镜像加速器地址 https://9ghz4eu4.mirror.aliyuncs.com/docker search 镜 像名 查找镜像,可根据名称、星级、是否官⽅发 布等条件查找(starts、official 等) docker pull 镜像 名 下载某个镜像,不加标签默认下载最新版本 的镜像 docker images 查看现有镜像 docker inspect 镜 像名 查看镜像详细信息 docker tag 旧镜 像:标签 新镜像:标 签 可更改镜像的标签名,也可镜像名连同标签 ⼀起修改成新镜像 docker rmi 镜像 名或镜像 id 删除某个镜像 docker save -o 保存位置 镜像名 保存导出某个镜像到某⼀位置 docker load \< 保 存后⽣成的镜像 ⽂件 导⼊本地保存的镜像⽂件 docker push 镜像 名 上传镜像,在上传之前需要将镜像使⽤ tag 命 令改名,改名为"仓库名/镜像"这种格式,才 可以上传 docker info 查看 docker 信息 cat 镜像⽂件 \| docker import - 镜像名:标签 导⼊本地镜像⽂件并设置名称docker system prune --all --force --volumes 删除所有未使⽤的⽂件,在 /var/lib/docker/ 下 docker volume prune 删除所有未使⽤的 卷,/var/lib/docker/volumes docker system df 列出所有未使⽤的 docker ⽂件 docker image prune -a 删除所有未使⽤的镜像 **命令** **解释** docker create -it 镜像 运⾏的程序 创建容器-i:让容器的输⼊保持打开-t:为容器 分配伪终端运⾏的程序:需要容器运⾏的某个 命令,如果想要容器持续运⾏,给/bin/bash docker ps 查看所有容器,包括已退出的容器 docker ps -a 查看正在运⾏的容器 docker start/stop/restart 容器名或 ID 启动/停⽌/重启某个容器 docker run \[-itd
容器名 运⾏的程
序 [-c 命令 ]
创建并启动容器等于 docker pull 命令+docker
create 命令+docker start 命令
docker attach 容 进⼊容器内部,可使⽤ exit 或 CTRL+D 退
2、容器操作器名/ID
出,也可以使⽤ CTRL+p+q
docker exec [-
itd] 容器名/ID
/bin/bash
分配⼀个 bash 环境再进⼊容器
docker export
容器名/ID > 保存
位置
导出容器到某个位置
docker import
本地容器⽂件 新
镜像名
导⼊某个容器⽂件到 docker 镜像并给新镜像
命名
docker commit
容器名/ID 新镜
像名
将某个容器保存⾄镜像
docker rm -f 容
器名/ID
删除容器,-f:强制删除
docker logs 容
器名/ID
查看容器标准输出的内容
docker run 的逻辑原理:执⾏此命令后,docker 后台会检测此容器
需要的镜像是否存在,如果本地不存在则去公共仓库下载。下载完
毕后,根据镜像创建⼀个容器,分配⼀个⽂件系统给容器,在只读
的镜像层外边挂载⼀层可读写层 ,从宿主机配置的⽹桥接⼝中桥接
⼀个虚拟机接⼝ 到容器中,分配⼀个地址池中的ip地址给容器执⾏⽤
户所执⾏的命令,执⾏完成后将容器终⽌运⾏。如果想让容器执⾏
完命令后继续运⾏,选项加 -d,此容器会在执⾏完命令后在后台运⾏。
0.启动docker守护进程
systemctl start docker
1.配置docker镜像站
{
"registry-mirrors": [
"https://do.nark.eu.org",
"https://dc.j8.work",
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker.nju.edu.cn"
]
}
2.docker search centos
3.dock pull centos
回顾29天 上午
1.介绍了docker
2.配置了dock的环境和安装了docker客户端和服务器
1.配置环境
3.启动了和关闭服务
4.查看镜像
/etc/modules-load.d/k8s.conf
/etc/sysctl.d/k8s.conf
#配置⼀个仓库
yum-config-manager --add-repo
https://mirrors.aliyun.com/docker
ce/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io
docker-buildx-plugin docker-compose-plugin -y
systemctl start|stop|restart docker.service
docker images5.搜索镜像
docker search tomcat|centos
6.下载镜像
vim /etc/docker/daemon.json
{
"registry-mirrors":[
"https://do.nark.eu.org",
"https://dc.j8.work",
"https://docker.m.daocloud.io",
"https://dockerproxy.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker.nju.edu.cn"
]
}
docker pull centos
1.运⾏容器
systemctl start docker.service
docker images
docker run -it --name=c0 centos:latest /bin/bash
2.当前运⾏的进程
3.当前位置和启动时间
4.cat /etc/redhat-release查看版本5.镜像是模版,容器是实例
6.容器中没有命令运
7.容器总是能轻易获取
8.配置yum
9.安装http
10.修改index⽂件
11.httpd -k start
12.访问
13.退出就没有服务了
14.查看docker进程
14.退出之后就没进程了
root@4f651d1035c6 \~\]# cat /etc/redhat-release CentOS Linux release 8.4.210515.再次启动 16.接⼊到管理界⾯,将容器的命令⾏附加到当前的终端 17.启动服务,退出但是不中断 ctrl+p+q 不建议在⽣产中使⽤,不要⼿动启动和关闭容器,由编排⼯具 步骤 # 第⼀次创建容器 docker run -it --name=c0 centos:latest /bin/bash # 配置阿⾥云的yum仓库 yum clean all \&\& yum makecache yum -y install httpdecho "docker_httpd_server" \> /var/www/html/index.html # systemctl start httpd httpd -k start curl localhost:80 # 在宿主上访问⽄ curl 172.17.0.2:80 # ⽆法在物理机器上访问,也⽆法ping到这个主机 # 如果没有指令正在执⾏,容器就会停⽌ exit # 重启容器 docker start c0 c0 # 将c0的终端附加到当前的终端 docker attach c0 # 这个时候,httpd⼜停了 # 期望退出,服务继续运⾏ # ctrl+p+q() **·⼀、Namespace** **1、概念** Namespace 是实现 Linux 资源隔离的核⼼技术,实现了 6 项资源隔 离,包括主机名、⽤户权限、⽂件系统、⽹络、进程号、进程通 信。 **2、作⽤** 1. **实现资源隔离:**通过使⽤Linux的Namespaces技术,Docker可 以在容器中创建独⽴的进程、⽂件系统、⽹络等环境。 2. **提⾼安全性:**使⽤namespace可以实现不同⽤户或者不同进程 之间的隔离,防⽌相互⼲扰和攻击。 3. **实现资源的限制和优化。** 4. **构建多租户系统:**通过namespace可以构建多租户系统,允许 多个⽤户或多个团队共享主机资源,但彼此之间的数据和权限是 隔离的,保证数据安全和系统稳定性。 **3、资源隔离项** 1. **cgroup:**该 namespace 可单独管理⾃⼰的 cgroup,隐藏了进 程所属的控制组身份。 2. **ipc:** 隔离 IPC,⽐如共享内存、信息量等。3. **network:**隔离⽹络资源,包括⽹络协议栈、⽹络设备、路由 表、防⽕墙、端⼝等。 4. **mount:**隔离挂载信息,拥有独⽴的⽬录层次。 5. **pid:**隔离进程号,使 namespace 中的进程 PID 单独编号。 6. **time:**隔离启动时间点信息和单调时间。 7. **user:**隔离⽤户管理权限机制(UID/GID),使 namespace 更 安全。 8. **uts:**隔离主机信息,包括主机名、NIS domain name。 **⼆、CGroup** **1、概念** cgroup 是 Linux 内核提供的⼀种机制,该机制可以根据特定的⾏ 为,将⼀系列任务及⼦任务整合或分隔到按资源划分等级的不同的 组内,为系统资源管理提供⼀个统⼀的框架。 cgroup可以限制被 namespace 隔离起来的资源,还可以为资源设置 权重、计算使⽤量、控制进程启停。 task 任务:cgroups 的属于中,task就表示系统的⼀个进程,在计 算机中的每⼀个进程都叫⼀个 task,task ⼀般使⽤PID进程表示。**2、特点** 1. cgroups 的 API 以⼀个伪⽂件系统的⽅式实现,即⽤户可以通 过⽂件操作实现 cgroups 的组织管理。 2. cgroups 的组织管理操作单元可以细粒度到线程级别,⽤户态代 码也可以针对系统分配的资源创建和销毁 cgroups,从⽽实现资 源再分配和管理。 3. 所有资源管理的功能都以"subsystem (⼦系统)"的⽅式实现,接 ⼝统⼀。 4. ⼦进程创建之初与其⽗进程处于同⼀个 cgroups 的控制组。本 质上来说,cgroups 是内核附加在程序上的⼀系列钩⼦ (hooks),通过程序运⾏时对资源的调度触发相应的钩⼦以达到 资源追踪和限制的⽬的。 **3、⽬的** 1. 为不同⽤户层⾯的资源管理,提供⼀个统⼀化的接⼝ 2. 单个进程的资源控制到操作系统层⾯的虚拟化 **4、作⽤** 1. **资源限制(Resource Limitation):**cgroups 可以对进程组使⽤ 的资源总额进⾏限制。如设定应⽤运⾏时使⽤内存的上限,⼀旦 超过这个配额就发出 OOM (Out of Memory) 。 2. **优先级分配(Prioritization):**通过分配的 CPU 时间⽚数量及硬 盘 IO 带宽⼤⼩,实际上就相当于控制了进程运⾏的优先级。3. **资源统计 (Accounting):**cgroups 可以统计系统的资源使⽤ 量,如 CPU 使⽤时⻓、内存⽤量等等,这个功能⾮常适⽤于计 费。 4. **进程控制(Control):**cgroups 可以对进程组执⾏挂起、恢复等 操作。 **三、Chroot** **1、概念** chroot 是在 Linux 系统中的⼀种操作,它可以改变正在运作的软件 进程及其⼦进程的外显根⽬录。 **2、作⽤** 1. **增加了系统的安全性,限制了⽤户的权⼒** 2. 1. 在经过 chroot 之后,在新根下将访问不到旧系统的根⽬录 结构和⽂件,这样就增强了系统的安全性。⼀般会在⽤户登 录前应⽤ chroot,把⽤户的访问能⼒控制在⼀定的范围之 内。 3. **建⽴⼀个与原系统隔离的系统⽬录结构,⽅便⽤户的开发** 4. 1. 使⽤ chroot 后,系统读取的是新根下的⽬录和⽂件,这是 ⼀个与原系统根下⽂件不相关的⽬录结构。在这个新的环境 中,可以⽤来测试软件的静态编译以及⼀些与系统不相关的 独⽴开发。5. **切换系统的根⽬录位置,引导 Linux 系统启动以及急救系统等** 6. 1. chroot 的作⽤就是切换系统的根位置,⽽这个作⽤最为明显 的是在系统初始引导磁盘的处理过程中使⽤,从初始 RAM 磁盘(initrd)切换系统的根位置并执⾏真正的 init。 **四、虚拟化状态** **1、完全解耦状态** 完全解耦虚拟化状态就是为每个软件提供⼀个独⽴的运⾏环境。这 个环境在 hypervisor 层实现硬件的物理划分,并在每个划分的空间 内安装⼀个操作系统,然后在这个操作系统上运⾏想要的软件。**2、半解耦状态** 在同⼀个环境下可以同时运⾏两个相同的软件,分担软件服务器的 压⼒。这种状态下,所有东⻄都是以软连接的形式创建的,甚⾄包 括内核。⽽且不会改变内核的情况下放进去,为了兼容不同的操作 系统。 **3、解耦和半解耦的区别** 解耦是直接从硬件上⾯进⾏隔离的,在⼀个单独的系统中运⾏项 ⽬。 半解耦运⾏在相对来说不是独⽴的容器⾥,相同的资源仪器使 ⽤,以软链接的形式同步到容器中,需要不同的资源时,再单独 下载。 **五、namespace:命名空间五、namespace:命名空间** **1、查看 apache 的 namespace** \[root@iZbp \~\]# yum -y install httpd \[root@iZbp \~\]# systemctl start httpd.service \[root@iZbp \~\]# netstat -anpt \|grep httpd tcp6 0 0 :::80 :::\* LISTEN 2578447/httpd \[root@iZbp \~\]# pidof httpd #⽤于查找httpd(指定服 务)的进程ID,包括主进程和其⼦进程 2578451 2578450 2578449 2578448 2578447 \[root@iZbp \~\]# cd /proc/2578447/ #进⼊到该服务进程⽬ 录下 \[root@iZbp 2578447\]# ll ns #查看Apache服务的 namespace total 0 lrwxrwxrwx 1 root root 0 Dec 5 20:35 cgroup -\> 'cgroup:\[4026531835\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 ipc -\> 'ipc: \[4026531839\]' lrwxrwxrwx 1 root root 0 Dec 5 20:31 mnt -\> 'mnt: \[4026532268\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 net -\> 'net: \[4026531992\]'**2、查看 pid=2 的 namespace** lrwxrwxrwx 1 root root 0 Dec 5 20:31 pid -\> 'pid: \[4026531836\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 pid_for_children -\> 'pid:\[4026531836\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 time -\> 'time:\[4026531834\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 time_for_children -\> 'time:\[4026531834\]' lrwxrwxrwx 1 root root 0 Dec 5 20:31 user -\> 'user:\[4026531837\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 uts -\> 'uts: \[4026531838\]'**3、查看容器是否与 nginx 进⾏隔离** \[root@doc 43866\]# ls -l /proc/2/ns 总⽤量 0 lrwxrwxrwx. 1 root root 0 12⽉ 11 17:00 cgroup -\> 'cgroup:\[4026531835\]' lrwxrwxrwx. 1 root root 0 12⽉ 11 17:00 ipc -\> 'ipc:\[4026531839\]' lrwxrwxrwx. 1 root root 0 12⽉ 11 17:00 mnt -\> 'mnt:\[4026531840\]' lrwxrwxrwx. 1 root root 0 12⽉ 11 17:00 net -\> 'net:\[4026531992\]' lrwxrwxrwx. 1 root root 0 12⽉ 11 17:00 pid -\> 'pid:\[4026531836\]' lrwxrwxrwx. 1 root root 0 12⽉ 11 17:00 pid_for_children -\> 'pid:\[4026531836\]' lrwxrwxrwx. 1 root root 0 12⽉ 11 17:00 time -\> 'time:\[4026531834\]' lrwxrwxrwx. 1 root root 0 12⽉ 11 17:00 time_for_children -\> 'time:\[4026531834\]' lrwxrwxrwx. 1 root root 0 12⽉ 11 17:00 user -\> 'user:\[4026531837\]' lrwxrwxrwx. 1 root root 0 12⽉ 11 17:00 uts -\> 'uts:\[4026531838\]' \[root@iZbp \~\]# ps #此时的bash是当前系统的进程号 PID TTY TIME CMD 2646243 pts/0 00:00:00 bash 2665910 pts/0 00:00:00 ps \[root@iZbp \~\]# docker run -itd --name test centos:7 /bin/bash #运⾏docker容器 1af03b3055f728022d6a5acd51869e4982f3d13fd67625c614 12ea2021d59131 \[root@iZbp \~\]# ps #此时多出来的2666343是容器的进程 PID TTY TIME CMD 2646243 pts/0 00:00:00 bash 2666343 pts/0 00:00:00 bash 2666546 pts/0 00:00:00 ps \[root@iZbp \~\]# docker inspect --format '{{.State.Pid}}' test #使⽤--format参数直接提取容器 的pid, docker inspect是⽤来获取有关容器的详细信息,其中 {{.State.Pid}}表示获取容器的进程pid。 2666343 #查看test容器中的namespace信息,以及上⾯apache的进程的 namespace信息 \[root@iZbp \~\]# ll /proc/2666343/ns total 0 lrwxrwxrwx 1 root root 0 Dec 5 21:03 cgroup -\> 'cgroup:\[4026531835\]' lrwxrwxrwx 1 root root 0 Dec 5 21:03 ipc -\> 'ipc: \[4026532208\]' lrwxrwxrwx 1 root root 0 Dec 5 20:58 mnt -\> 'mnt: \[4026532206\]'lrwxrwxrwx 1 root root 0 Dec 5 20:58 net -\> 'net: \[4026532211\]' lrwxrwxrwx 1 root root 0 Dec 5 20:58 pid -\> 'pid: \[4026532209\]' lrwxrwxrwx 1 root root 0 Dec 5 21:03 pid_for_children -\> 'pid:\[4026532209\]' lrwxrwxrwx 1 root root 0 Dec 5 21:03 time -\> 'time:\[4026531834\]' lrwxrwxrwx 1 root root 0 Dec 5 21:03 time_for_children -\> 'time:\[4026531834\]' lrwxrwxrwx 1 root root 0 Dec 5 20:58 user -\> 'user:\[4026531837\]' lrwxrwxrwx 1 root root 0 Dec 5 21:03 uts -\> 'uts: \[4026532207\]' \[root@iZbp \~\]# ll /proc/2578447/ns/ total 0 lrwxrwxrwx 1 root root 0 Dec 5 20:35 cgroup -\> 'cgroup:\[4026531835\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 ipc -\> 'ipc: \[4026531839\]' lrwxrwxrwx 1 root root 0 Dec 5 20:31 mnt -\> 'mnt: \[4026532268\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 net -\> 'net: \[4026531992\]' lrwxrwxrwx 1 root root 0 Dec 5 20:31 pid -\> 'pid: \[4026531836\]'**4、对⽐得出结论** 这⾥的数字就是"命名空间的名字",数字相同,则表示在同⼀个空间 内,不相同则表示不在同⼀个空间内。若在同⼀个空间内,表示会 发⽣"耦合"或"冲突",⽐如实验中 43866 和 2 的进程中 net 相同, 则他们不能使⽤相同的端⼝、IP等⽹络栈。但实验中 43866 和 2 的 进程中 mnt 的编号不相同,则不会发⽣冲突。 **5、proc ⽬录** proc 是 Linux 系统下⼀个很重要的⽬录。 它跟 /etc,/home 等这些 系统⽬录不同,它不是⼀个真正的⽂件系统, ⽽是⼀个虚拟的⽂件 系统。 它不存在于磁盘, ⽽是存在于系统内存中。 lrwxrwxrwx 1 root root 0 Dec 5 20:35 pid_for_children -\> 'pid:\[4026531836\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 time -\> 'time:\[4026531834\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 time_for_children -\> 'time:\[4026531834\]' lrwxrwxrwx 1 root root 0 Dec 5 20:31 user -\> 'user:\[4026531837\]' lrwxrwxrwx 1 root root 0 Dec 5 20:35 uts -\> 'uts: \[4026531838\]' #cgroup先不要考虑,观察其他的数值是否在同⼀个空间 #只有namespace的user和time没有被隔离。docker默认没有对 user和time的单独namespace/proc/cpuinifo CPU的信息 (型号、家族、缓存⼤⼩等),对应命 令 top /proc/meminfo 物理内存、交换空间,对应命令 free /proc/mounts 已加载的⽂件系统的列表 /proc/devices 可⽤设备的列表 /proc/filesystems 被⽀持的⽂件系统 /proc/modules 已加载的模块 /proc/version 内核版本 /proc/cmdline 系统启动时输⼊的内核命令⾏参数 /proc/XXX XXX是指以进程PID(数字编号)命名的⽬ 录,每⼀个⽬录表示⼀个进程(即线程组) /proc/swaps 要获知swap空间的使⽤情况 /proc/uptime 获取系统的正常运⾏时间 /proc/fs/nfsd/exports 列出由NFS共享的⽂件系统/proc/kmsg 该⽂件被作为内核⽇志信息源,它可以被 作为⼀个系统信息调⽤的接⼝使⽤ /proc/self 到当前进程/proc⽬录的符号链接,通过这 个⽬录可以获取当前运⾏进程的信息 /proc/pci 挂接在PCI总线上的设备 /proc/tty/driver/serial 串⼝配置、统计信息 /proc/version 系统版本信息,对应系统命令 uname -a 或 lsb_release /proc/sys/kernel/ostype /proc/sys/kernel/osrelease /proc/sys/kernel/version /proc/sys/kernel/hostname 主机名 /proc/sys/kernel/domainname 域名 /proc/partitions 硬盘设备分区信息 /proc/sys/dev/cdrom/info CDROM信息/proc/locks 当前系统中所有的⽂件锁 /proc/loadavg 系统负荷信息,对应系统命令 top /proc/uptime 系统启动后的运⾏时间,对应命 令 uptime /proc/N\[N 对应 pid 号
获取进程运⾏状态,系统命令
ps aux 或 top
- /proc/N pid为N的进程信息
- /proc/N/cmdline 进程启动命令
- /proc/N/cwd 链接到进程当前⼯作⽬录
- /proc/N/environ 进程环境变量列表
- /proc/N/exe 链接到进程的执⾏命令⽂件
- /proc/N/fd 包含进程相关的所有的⽂件描述符
- /proc/N/maps 与进程相关的内存映射信息
- /proc/N/mem 指代进程持有的内存,不可读
- /proc/N/root 链接到进程的根⽬录
- /proc/N/stat 进程的状态
- /proc/N/statm 进程使⽤的内存的状态
- /proc/N/status 进程状态信息,⽐stat/statm更具可读性
- /proc/self 链接到当前正在运⾏的进程14. /proc/N/ns 程序的namespace空间
六、namespace 隔离项
1、准备⼯作
root@iZbp \~\]# yum -y install gcc gcc-c++ #安装c
语⾔环境
\[root@iZbp \~\]# vim test.c #编写脚本⽂件
#define _GNU_SOURCE
#include \
"AliYunDunMonito"""25\*\[{AliYunDunMonito}\]
"smartd
$"sshd"""sshd"""sshd"""bash"""pid.o"""bash"""pstre
e #可以看到进程之间的关系
root@C测试 \~\]# ps aux #主机上的1号进程是systemd USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 1 0.0 0.6 184304 12060 ? Ss Nov30 0:09 /usr/lib/systemd/systemd root 2 0.0 0.0 0 0 ? S Nov30 0:00 \[kthreadd
#此时可以看出⽬前查到的都是主机系统上的进程信息,⽽不是新空
间内的。是因为此时的proc⽬录没有改变
root@C测试 \~\]# ls /proc/ #proc⽬录下的进程还是主机
上的进程
1 157 28 434 721 845170
interrupts partitions
10 158 29 435 732015 845172
iomem sched_debug
1004 16 290 437 732482 847191
ioports schedstat
11 160 291 437402 732485 847192
irq scsi
1131 161 292 438 732491 850882
kallsyms self
12 162 295 444 732492 9
kcore slabinfo
1211 17 3 464 743 acpi
keys softirqs
1224 1719 30 466 747 buddyinfo
key-users stat
13 18 300 467 750 bus
kmsg swaps1305 1878 302 468 751 cgroups
kpagecgroup sys
1327 2 31 469 752 cmdline
kpagecount sysrq-trigger
1341 20 32 470 753 consoles
kpageflags sysvipc
1344 22 33 471 759 cpuinfo
loadavg thread-self
1347 23 34 472 779100 crypto
locks timer_list
1349 24 35 473 791 devices
mdstat tty
1359 2578447 36 579 794 diskstats
meminfo uptime
1360 2578448 37 6 796 dma
misc version
14 2578449 38 614 799312 driver
modules vmallocinfo
1435 2578450 4 62 825610 execdomains
mounts vmstat
15 2578451 40 681 825617 fb
mtrr zoneinfo
155 26 41 693437 827638 filesystems
net
156 27 428472 719 844328 fs
pagetypeinfo**5、MOUNT 隔离**
1. MOUNT命名空间是linux系统上实现的第⼀种类型的命名空间。
所以它的标识⽐较特殊是CLONE_NEWNS
2. 隔离后,不同mountnamespace中的⽂件结构发⽣变化也互不
影响
3. mount传播挂载命令。默认所有挂载都是私有的
4. 1. 设置共享挂载:mount --make-shared 。共享挂载克隆的
挂载对象也是共享挂载;他们相互传播挂载事件
2. 从属挂载:mount --make-slave 。从属挂载克隆的挂载对
象也是从属的挂载
3. 将⼀个从属挂载对象设置为共享、从属挂载,可以执⾏
mount --make-shared
1. 1. 如果想把修改过的挂载对象重新标记为私有
mount --make-private
1. 1. 挂载对象标记为不可绑定
mount --make-unbindable
#proc⽬录没有改变是因为没有对⽂件系统进程隔离,需要对mount
隔离1. 测试mount挂载
\[root@C测试 \~\]# vim test.c #添加mount隔离
int main() {
printf("程序开始: \\n");
int child_pid = clone(child_main, child_stack +
STACK_SIZE,CLONE_NEWUTS \| CLONE_NEWIPC
\|CLONE_NEWPID\| CLONE_NEWNS\| SIGCHLD, NULL); #添加
CLONE_NEWNS
waitpid(child_pid, NULL, 0);
printf("已退出\\n");
return 0;
}
\[root@C测试 \~\]# gcc -Wall test.c -o mnt.o #将脚本
⽣成程序
\[root@C测试 \~\]# ls #查看⽣成后的程序⽂件
ipc.o mnt.o pid.o test.c test.o uts.o
\[root@C测试 \~\]# ./mnt.o #运⾏mnt程序
程序开始:
在⼦进程中!
#此时并没有实现完全隔离,需要⼿动执⾏mount命令
\[root@C测试 \~\]# mount --make-private -t proc proc
/proc/ #对容器内的proc⽬录设置为私有挂载
\[root@C测试 \~\]# ls /proc/ #此时查看proc⽬录,发现已
经只有容器内的进程信息了1 crypto interrupts kpagecgroup
mounts slabinfo tty
46 devices iomem kpagecount
mtrr softirqs uptime
acpi diskstats ioports kpageflags
net stat version
buddyinfo dma irq loadavg
pagetypeinfo swaps vmallocinfo
bus driver kallsyms locks
partitions sys vmstat
cgroups execdomains kcore mdstat
sched_debug sysrq-trigger zoneinfo
cmdline fb keys meminfo
schedstat sysvipc
consoles filesystems key-users misc
scsi thread-self
cpuinfo fs kmsg modules
self timer_list
\[root@C测试 \~\]# ps aux #查看容器所有进程信息,只有容
器内的进程
USER PID %CPU %MEM VSZ RSS TTY
STAT START TIME COMMAND
root 1 0.0 0.3 27824 5856 pts/0 S
10:19 0:00 /bin/bash
root 47 0.0 0.2 58732 3924 pts/0
R+ 10:22 0:00 ps aux
\[root@C测试 \~\]# exitexit
已退出
#这个挂载修改后还会影响宿主机上⾯的挂载,宿主机也需要重新挂
载才可以还原
\[root@iZbp \~\]# mount --make-private -t proc proc
/proc/ #在宿主机上⾯执⾏proc的挂载
\[root@iZbp \~\]# ls /proc/ #查看proc⽬录
1 13 18 300 467 794
iomem sched_debug
10 1305 1878 302 468 796
ioports schedstat
1002231 1327 2 31 469 9
irq scsi
1004 1341 20 32 470 941511
kallsyms self
1033693 1344 22 33 471 991980
kcore slabinfo
1052123 1347 23 34 472 acpi
keys softirqs
1054700 1349 24 35 473 buddyinfo
key-users stat
1065188 1359 2578447 36 579 bus
kmsg swaps
1065189 1360 2578448 37 6 cgroups
kpagecgroup sys
1071096 14 2578449 38 614 cmdline
kpagecount sysrq-trigger1076512 1435 2578450 4 62 consoles
kpageflags sysvipc
1077826 15 2578451 40 681 cpuinfo
loadavg thread-self
1077830 155 26 41 719 crypto
locks timer_list
1077895 156 27 428472 721 devices
mdstat tty
1078161 157 28 434 743 diskstats
meminfo uptime
1078162 158 29 435 747 dma
misc version
1080287 16 290 437 750 driver
modules vmallocinfo
11 160 291 437402 751 execdomains
mounts vmstat
1131 161 292 438 752 fb
mtrr zoneinfo
12 162 295 444 753 filesystems
net
1211 17 3 464 759 fs
pagetypeinfo
1224 1719 30 466 791 interrupts
partitions
#此时宿主机上⾯的proc⽬录恢复正常\[root@iZbp \~\]# cat /boot/config-4.18.0-
305.3.1.el8.x86_64 \| grep -i ns #查看那些是需要内核实
现的
CONFIG_INSTRUCTION_DECODER=y
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
CONFIG_UTS_NS=y
CONFIG_TIME_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y。。。。。
#这些namespace是没有被mount的
1. systemd是使⽤内核,所以依旧⽆法⽤systemd进程启动程序。
2. 解决⽅案⼀:/sbin/init是systemd的软连接。可以使⽤/sbin/init
进⼊容器。此⽅法在最新版本中已经不建议使⽤
\[root@iZbp \~\]# docker run -d --name test --
privileged rockylinux /sbin/init #增加--
privileged参数才能有权限执⾏systemd
795851a713f9ded5b250dfd0861c4dc97490409a5a745c4b28
587267e573ca1c
\[root@iZbp \~\]# docker exec -it test bash #进⼊容器
\[root@795851a713f9 /\]# yum -y install httpd #安装
httpd\[root@795851a713f9 /\]# systemctl start httpd #使
⽤systemd启动httpd程序
\[root@iZbp \~\]# which ps #在宿主机上⾯查看ps命令的安装
包
/usr/bin/ps
\[root@iZbp \~\]# rpm -qf /usr/bin/ps
procps-ng-3.3.15-6.el8.x86_64
\[root@795851a713f9 /\]# yum -y install procps-ng
#安装ps命令
USER PID %CPU %MEM VSZ RSS TTY
STAT START TIME COMMAND
root 1 0.1 0.5 89900 10200 ?
Ss 02:39 0:00 /sbin/init
root 18 0.0 0.4 87356 8120 ?
Ss 02:39 0:00 /usr/lib/systemd/systemd
dbus 26 0.0 0.2 54056 4172 ?
Ss 02:39 0:00 /usr/bin/dbus-daemon --s
root 45 0.0 0.2 19352 3712 pts/0
Ss 02:39 0:00 bash
root 135 0.0 0.6 258080 10852 ?
Ss 02:39 0:00 /usr/sbin/httpd -DFOREGR
apache 136 0.0 0.4 260664 7956 ? S
02:39 0:00 /usr/sbin/httpd -DFOREGR
apache 137 0.0 0.5 1908356 9588 ?
Sl 02:39 0:00 /usr/sbin/httpd -DFOREGR
apache 138 0.0 0.5 1777220 9700 ?
Sl 02:39 0:00 /usr/sbin/httpd -DFOREGRapache 139 0.0 0.5 1777220 9700 ?
Sl 02:39 0:00 /usr/sbin/httpd -DFOREGR
root 358 0.0 0.2 51864 3808 pts/0
R+ 02:40 0:00 ps aux
1. 解决⽅案⼆:直接使⽤execstart启动
\[root@iZbp \~\]# docker run -itd --name ssh
rockylinux bash #创建⼀个容器,⽤来演示sshd服务在容器
内如何启动
0cac21a08a57ee6de38e16e744d07d8d5a72d6eda40a9259fc
1b3997c5ecff7f
\[root@iZbp \~\]# docker exec -it ssh bash #进⼊
\[root@0cac21a08a57 /\]# yum -y install httpd #安装
httpd服务
\[root@0cac21a08a57 /\]# cat
/usr/lib/systemd/system/httpd.service #找到启动⽂
件
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND #
找到启动程序命令的路径
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
\[root@0cac21a08a57 /\]# /usr/sbin/httpd $OPTIONS -
DFOREGROUND \& #使⽤命令启动程序,并放在后台运⾏
\[1\] 549\[root@0cac21a08a57 /\]# AH00558: httpd: Could not
reliably determine the server's fully qualified
domain name, using 172.17.0.2. Set the
'ServerName' directive globally to suppress this
message
\[root@0cac21a08a57 /\]# ps aux #查看进程已经开始运⾏
USER PID %CPU %MEM VSZ RSS TTY
STAT START TIME COMMAND
root 1 0.0 0.2 19240 3740 pts/0
Ss+ 02:47 0:00 bash
root 13 0.0 0.2 19352 3736 pts/1
Ss 02:48 0:00 bash
root 549 0.3 0.6 258080 10744 pts/1 S
02:55 0:00 /usr/sbin/httpd -DFOREGR
apache 550 0.0 0.4 260664 8044 pts/1 S
02:55 0:00 /usr/sbin/httpd -DFOREGR
apache 551 0.0 0.6 1908344 11696 pts/1
Sl 02:55 0:00 /usr/sbin/httpd -DFOREGR
apache 552 0.0 0.5 1777208 9648 pts/1
Sl 02:55 0:00 /usr/sbin/httpd -DFOREGR
apache 553 0.0 0.5 1777208 9648 pts/1
Sl 02:55 0:00 /usr/sbin/httpd -DFOREGR
root 765 0.0 0.2 51864 3780 pts/1
R+ 02:55 0:00 ps aux
#在宿主机上查看docker的IP地址
\[root@iZbp /\]# docker inspect ssh \|grep 172 #过
滤dockerip的详细信息"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
#docker的IP地址
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
\[root@iZbp /\]# curl 172.17.0.2
\
\
#访问成功后显示httpd的图形测试⻚⾯
#启动容器内sshd服务
\[root@iZbp \~\]# docker exec -it ssh bash
\[root@0cac21a08a57 /\]# yum -y install passwd
iproute openssh-server #安装sshd需要的⼀些必要命令
#passwd:ssh连接需要密码,所以需要passwd设置root的密码
#openssh-server:ssh服务
\[root@0cac21a08a57 /\]# passwd root #设置root密码
Changing password for user root.
New password:
BAD PASSWORD: The password is shorter than 8
characters
Retype new password:
passwd: all authentication tokens updated
successfully.
\[root@0cac21a08a57 /\]# /usr/sbin/sshd -D $OPTIONS
$CRYPTO_POLICY #启动sshd服务提示缺少三个秘钥⽂件
Unable to load host key: /etc/ssh/ssh_host_rsa_keyUnable to load host key:
/etc/ssh/ssh_host_ecdsa_key
Unable to load host key:
/etc/ssh/ssh_host_ed25519_key
sshd: no hostkeys available -- exiting.
\[root@0cac21a08a57 /\]# ssh-keygen -f
/etc/ssh/ssh_host_rsa_key #创建秘钥⽂件,回⻋使⽤默认
配置
\[root@0cac21a08a57 /\]# ssh-keygen -f
/etc/ssh/ssh_host_ecdsa_key
\[root@0cac21a08a57 /\]# ssh-keygen -f
/etc/ssh/ssh_host_ed25519_key
\[root@0cac21a08a57 /\]# vi /etc/ssh/sshd_config
PermitRootLogin yes #允许root⽤户登录
#UsePAM yes # #注释PAM认证,
\[root@0cac21a08a57 /\]# /usr/sbin/sshd -D \& #启动
sshd服务
\[1\] 851
\[root@0cac21a08a57 /\]# ip a #查看ip地址
1: lo: \
Get "https://192.168.15.3:5000/v2/": http: server
gave HTTP response to HTTPS client
报错(1)报错情况
(2)报错原因
因为Docker 从 1.3.X 之后默认 docker registry 使⽤的是 https,所
以当⽤dockerpull/push 命令下载、上传远程镜像时,如果远程
docker registry 是⾮ https 的时候就会报上⾯的错误,所以需要修改
⼀下docker启动参数。
(3)错误处理
root@doc \~\]# docker push 192.168.15.3:5000/nginx:v1 The push refers to repository \[192.168.15.3:5000/nginx
Get "https://192.168.15.3:5000/v2/": http: server
gave HTTP response to HTTPS client
报错
root@doc \~\]# vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -H fd:// -- containerd=/run/containerd/containerd.sock -- insecure-registry 192.168.15.3:5000 # 添加参数 \[root@doc \~\]# systemctl daemon-reload \[root@doc \~\]# systemctl restart docker.service--insecure-registry:⼀个⽤于将 Docker 客户端配置为信任不安 全的 Docker Registry 的选项。在默认情况下,Docker 客户端 只信任通过 HTTPS 进⾏通信的 Docker Registry,以确保安全 性。 **5、再次上传镜像** \[root@doc \~\]# docker push 192.168.15.3:5000/nginx:v1 The push refers to repository \[192.168.15.3:5000/nginx
d874fd2bc83b: Pushed
32ce5f6a5106: Pushed
f1db227348d0: Pushed
b8d6e692a25e: Pushed
e379e8aedd4d: Pushed
2edcec3590a4: Pushed
v1: digest:
sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0b
fd5c4c20a2fa2aaa7ede3 size: 1570
root@doc \~\]# curl http://127.0.0.1:5000/v2/_catalog {"repositories":\["nginx"\]} # 上传成功 \[root@doc \~\]# curl http://127.0.0.1:5000/v2/nginx/tags/list {"name":"nginx","tags":\["v1"\]} # 查看nginx镜像版 本**6、拉取私有镜像** \[root@doc \~\]# ls /opt/data/registry/docker/registry/v2/repositories / # 镜像存放于宿主机的位置 nginx \[root@doc \~\]# docker rmi 192.168.15.3:5000/nginx:v1 # 先删除刚才的镜像 Untagged: 192.168.15.3:5000/nginx:v1 Untagged: 192.168.15.3:5000/nginx@sha256:ee89b00528ff4f02f24 05e4ee221743ebc3f8e8dd0bfd5c4c20a2fa2aaa7ede3 \[root@doc \~\]# docker pull 192.168.15.3:5000/nginx:v1 # 再拉取私有仓库内的镜像 v1: Pulling from nginx Digest: sha256:ee89b00528ff4f02f2405e4ee221743ebc3f8e8dd0b fd5c4c20a2fa2aaa7ede3 Status: Downloaded newer image for 192.168.15.3:5000/nginx:v1 192.168.15.3:5000/nginx:v1 \[root@doc \~\]# docker tag 192.168.15.3:5000/nginx:v1 nginx:v2 # 改名 \[root@doc \~\]# docker images # 查看所有镜像 REPOSITORY TAG IMAGE ID CREATED SIZE**7、其他主机上传** 只要同在⼀个局域⽹内的所有主机都可向本地镜像仓库内上传镜 像,⽅法同上,在上传时只需注意: 当添加完参数后,就可向本地私有仓库上传。 busybox latest beae173ccac6 23 months ago 1.24MB 192.168.15.3:5000/nginx v1 605c77e624dd 23 months ago 141MB nginx latest 605c77e624dd 23 months ago 141MB nginx v2 605c77e624dd 23 months ago 141MB registry latest b8604a3fe854 2 years ago 26.2MB \[root@doc \~\]# vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -H fd:// -- containerd=/run/containerd/containerd.sock -- insecure-registry 192.168.15.3:5000 # 添加参数 \[root@doc \~\]# systemctl daemon-reload \[root@doc \~\]# systemctl restart docker.service Docker允许通过外部访问容器或者容器之间互联的⽅式来提供⽹络 服务。 容器启动之后,容器中可以运⾏⼀些⽹络应⽤,通过-p或-P参数来 指定端⼝映射。 宿主机的⼀个端⼝只能映射到容器内部的某⼀个端⼝上,⽐如: 8080-\>80之后,就不能8080-\>81。 容器内部的某个端⼝可以被宿主机的多个端⼝映射,⽐如: 8080- \>80,8090-\>80,8099-\>80。 **⼀、为容器绑定宿主机端⼝** -p ⼩写p表示docker会选择⼀个具体的宿主机端⼝映射到容器 内部开放的⽹络端⼝上。 -P ⼤写P表示docker会随机选择⼀个宿主机端⼝映射到容器内 部开放的⽹络端⼝上。 \[root@doc \~\]# docker run -itd --name nginx1 -p 8080:80 nginx:latest d9df73aa43cb496df80717f91170ea97912601fc25757cd4b7 125d3054f6d61a \[root@doc \~\]# docker run -itd --name nginx2 -P nginx:latest8cf5a8dce583990619ad38d847438564600edd490917d94fe4 cbd144ce7da195 \[root@doc \~\]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8cf5a8dce583 nginx:latest "/docker entrypoint...." 10 seconds ago Up 9 seconds 0.0.0.0:32768-\>80/tcp, :::32768-\>80/tcp nginx2 d9df73aa43cb nginx:latest "/docker entrypoint...." 16 seconds ago Up 15 seconds 0.0.0.0:8080-\>80/tcp, :::8080-\>80/tcp nginx1 9ab3d198bf05 registry:latest "/entrypoint.sh /etc..." About an hour ago Up 48 minutes 0.0.0.0:5000-\>5000/tcp, :::5000-\>5000/tcp registry \[root@doc \~\]# netstat -anpt \| grep 8080 tcp 0 0 0.0.0.0:8080 0.0.0.0:\* LISTEN 9922/docker proxy tcp6 0 0 :::8080 :::\* LISTEN 9930/docker-proxy \[root@doc \~\]# netstat -anpt \| grep 32768访问本机地址:8080 即可访问到 nginx1 容器。 访问本机地址:32768 即可访问到 nginx2 容器,这是 -P 的随机映射 端⼝。 **⼆、为容器绑定宿主机 IP** tcp 0 0 0.0.0.0:32768 0.0.0.0:\* LISTEN 10046/docker proxy tcp6 0 0 :::32768 :::\* LISTEN 10052/docker-proxy\[root@doc \~\]# docker run -itd --name nginx3 -p 127.0.0.1:8888:80 nginx:latest 66347b8f5295247146ecfeeee4bf9cda313eb8b67c662a1fa0 7f10649c602ddf \[root@doc \~\]# docker run -itd --name nginx4 -p 192.168.15.3:9999:80 nginx:latest fd2c230b4c562e9531dd4e2208a59800284395e6afaa66eae6 41d75933442a1c \[root@doc \~\]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fd2c230b4c56 nginx:latest "/docker entrypoint...." 3 seconds ago Up 2 seconds 192.168.15.3:9999-\>80/tcp nginx4 66347b8f5295 nginx:latest "/docker entrypoint...." 10 seconds ago Up 9 seconds 127.0.0.1:8888-\>80/tcp nginx3 访问 127.0.0.1:8888 即可访问到 nginx3 容器 访问 192.168.15.3:9999 即可访问到 nginx4 容器 但访问 192.168.15.3:8888 和 127.0.0.1:9999 就⽆法访问到 nginx**三、容器指定通信协议** **四、查看容器绑定端⼝和容器的 IP 地址** \[root@doc \~\]# docker run -itd --name nginx5 -p 7777:80/udp nginx:latest 9a90cd757d59de57c247543e9dda5d186798e12677e83239cd 28394e8424f467 \[root@doc \~\]# docker ps \| grep nginx5 9a90cd757d59 nginx:latest "/docker entrypoint...." 16 seconds ago Up 15 seconds 80/tcp, 0.0.0.0:7777-\>80/udp, :::7777-\>80/udp nginx5 \[root@doc \~\]# netstat -anpu \| grep 7777 udp 0 0 0.0.0.0:7777 0.0.0.0:\* 10998/docker proxy udp6 0 0 :::7777 :::\* 11004/docker-proxy **五、错误处理** **1、启动容器时报错** **错误信息:** \[root@doc \~\]# docker port nginx4 80/tcp -\> 192.168.15.3:9999 # 容器绑定宿主机的IP和端 ⼝ \[root@doc \~\]# docker inspect nginx4 \| grep IPAddress "SecondaryIPAddresses": null, "IPAddress": "172.17.0.6", # 容器的 IP地址 "IPAddress": "172.17.0.6", /usr/bin/docker-current: Error response from daemon: driver failed programming external connectivity on endpoint my-nginx (db5a0edac68d1ea7ccaa3a1e0db31ebdf278076ef4851ee42 50221af6167f9ac): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 -- dport 8088 -j DNAT --to-destination 172.17.0.2:80 ! -i docker0: iptables: No chain/target/match by that name.**解决⽅案:** 1. 重启 docker 服务:systemctl restart docker 2. 再 docker start $(docker ps -qa) **2、容器端⼝映射到宿主机后,外部⽆法访问宿主机绑定端** **⼝** **错误信息:** 创建 docker 容器的时候,做了端⼝映射到宿主机,防⽕墙已关闭, 但是外部始终⽆法访问宿主机端⼝。 **错误原因:** 1. 这种情况基本就是因为宿主机没有开启路由转发功能,从⽽导致 外部⽹络访问宿主机对应端⼝是没能转发到 Docker Container 所对应的端⼝上。 2. 也可能是宿主机对应端⼝被占⽤。 **解决⽅案:** 1. **设置路由转发** 在 Linux 中开启 ip 转发的内核参数为:net.ipv4.ip_forward,查看是 否开启 ip转发:# cat /proc/sys/net/ipv4/ip_forward // 0:未开启,1:已开启 ====== 打开ip转发功能, 下⾯两种⽅法都是临时打开ip转发功能! # echo 1 \> /proc/sys/net/ipv4/ip_forward # sysctl -w net.ipv4.ip_forward=1 ====== 永久⽣效的ip转发 # vim /etc/sysctl.conf net.ipv4.ip_forward = 1 # sysctl -p /etc/sysctl.conf // ⽴即⽣效 Linux 系统中也可以通过重启⽹卡来⽴即⽣效 (修改 sysctl.conf ⽂件 后⽣效) 1. **关闭被占⽤端⼝的服务或修改容器端⼝** # netstat -anpt \| grep 占⽤端⼝确认端⼝冲突是哪个服务,可以选择关闭服务,也可以选择修改服 务端⼝ ====== 通过 docker 容器管理命令可以先将端⼝冲突的容器删除(docker rm -f 容器名/ID),再通过 docker run -itd -p 命令重新指定,在删 除前要做好该容器的备份,以免数据丢失。 ====== 在指定容器的端⼝映射时,⼀定要确认好宿主机的端⼝是否已经被 占⽤,否则在真正的⽣产环境时,⼀旦处理起来,可能会造成⼀定 的数据损失。