主机级虚拟化
例子:VM…
概念:虚拟机虚拟出来的场景或者环境是一个完整独立的硬件平台。因此用户使用这个虚拟机的话需在虚拟机上部署完整的操作系统(操作系统上包括(内核、内核之上又包括用户空间、用户空间里面跑进程))
如果一个程序想要执行,需要进行两级调度和资源分派(1:虚拟机中的内核调度管理 2:宿主机的内核调度管理)
chroot
chroot,即 change root directory (更改 root 目录)。在 linux 系统中,系统默认的目录结构都是以 /,即是以根 (root) 开始的。而在使用 chroot 之后,系统的目录结构将以指定的位置作为 / 位置
chroot(能干吗)
docker容器实现(每个用户空间都有一个自己独立根文件系统,以此做相互隔离)
在经过 chroot 之后,系统读取到的目录和文件将不在是旧系统根下的而是新根下(即被指定的新的位置)的目录结构和文件,因此它带来的好处大致有以下3个:
- 增加了系统的安全性,限制了用户的权力;在经过 chroot 之后,在新根下将访问不到旧系统的根目录结构和文件,这样就增强了系统的安全性。这个一般是在登录 (login) 前使用 chroot,以此达到用户不能访问一些特定的文件。
- 建立一个与原系统隔离的系统目录结构,方便用户的开发;使用 chroot 后,系统读取的是新根下的目录和文件,这是一个与原系统根下文件不相关的目录结构。在这个新的环境中,可以用来测试软件的静态编译以及一些与系统不相关的独立开发。
- 切换系统的根目录位置,引导 Linux 系统启动以及急救系统等。chroot 的作用就是切换系统的根位置,而这个作用最为明显的是在系统初始引导磁盘的处理过程中使用,从初始 RAM 磁盘 (initrd) 切换系统的根位置并执行真正的 init。另外,当系统出现一些问题时,我们也可以使用 chroot 来切换到一个临时的系统。
- 限制被CHROOT的使用者所能执行的程式,如SetUid的程式,或是会造成 Load 的Compiler等等。
- 防止使用者存取某些特定档案,如/etc/passwd。
- 防止入侵者/bin/rm -rf /。
- 提供Guest服务以及处罚不乖的使用者。
- 增进系统的安全。
- 可以将(UTS、IPC、PID、Network、Mount、User)此六类只要可以在内核级切割划分成不同环境相互隔离我们就称为名称空间
- Linux已经将这六种所划分在不同环境的功能通过名称空间的机制提供原生支持
- Linux内所有的容器化技术都是通过chroot+namespaces(UTS、IPC、PID、Network、Mount、User)实现的

User在内核3.8版本才被加入
容器级虚拟化
Control Groups可以实现用户空间的资源分配
- 相对于主机级虚拟化来说,不在是每个虚拟环境中都有一个内核,而是让所有虚拟环境使用同一内核
cgroups(把系统级资源分给多个组,把每个组内的资源量指派或者分配到特定的用户空间的进程上去实现 )
- 组还可以继续划分
LXC
(Linux container)
介绍:将完整的容器技术用一组简易使用的工具和模板来极大简化了容器使用的方案。
lxc-create(创建名称空间)telmplate模板(脚本,通过执行写好的脚本将所需要安装软件文件直接从官网拉取到所在用户空间的目录下)
LXC的出现简化了虚拟环境中用户操作名称空间的方式,但是如果批量创建多个容器,或者将容器内数据迁移出去LXC就不能够很好的实现
从LXC到Docker
lxc是docker的增强版!!!
docker解决了批量安装的问题:通过镜像技术,将一个操做系统用户空间所需要用到的所有组件,事先准备编排好,将其整体打包成一个文件,此文件为镜像文件image。
docker是一个容器内放一个进程(每个容器中对应每个进程都有一个问题追踪的调试工具) 而LXC则是一个容器内有一个名称空间,里面可以有n个进程D
Docker:分层构载联合挂载一个基础镜像可以共享给多个上层镜像使用(比如,nginx、tomcat、mysql都需要一个centos7操作系统,我们就可将一个centos7镜像做为一个基础层,上层分别有nginx、tomcat、mysql,比如需要nginx时就将nginx与centos7挂载,当tomcat需要centos7时就将tomcat与centos7挂载)每一层镜像都只是只读的
修改层作用:1、当通过进程删除文件时,对应修改层对删除文件打上标签(进程不可读)
2、当进程需要修改nginx文件时,先将nginx文件复制过来,然后再修改层修改。
迁移:打算长期使用此容器!!!需要在容器外部挂载一个共享存储服务器。
Docker自己的编排工具(machine+swarm+compose)
试验机安装docker
试验机centos版本号:
清华官方镜像站:https://mirrors.tuna.tsinghua.edu.cn/
1:到达此地址下:https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/
(或将docker-ce.repo)下载到本地上传至服务端/etc/yum.repos.d/目录下
(或将docker-ce.repo)wget到/etc/repso.d/下 wget -P /etc/yum.repos.d/ [https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo](https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo)
2:修改docker-ce.repo文件中的url
vim docker-ce.repo

stable/Packages/地址: https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7.6/x86_64/stable/Packages/
vim中替换docker官方下载地址%s#https://download.docker.com/#https://mirrors.tuna.tsinghua.edu.cn/docker-ce/#
清华镜像站镜像安装时报错 故使用阿里镜像仓库。。。
1:首先将清华大学镜像包备份mv docker-ce.repo docekr-ce.repo.qinghuabak
2:通过 uname -r 命令查看你当前的内核版本uname -r
3、使用 root 权限登录 Centos。确保 yum 包更新到最新。sudo yum update
4、卸载旧版本(如果安装过旧版本的话)sudo yum remove docker docker-common docker-selinux docker-engine
5、安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的sudo yum install -y yum-utils device-mapper-persistent-data lvm2
6、设置yum源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

7、可以查看所有仓库中所有docker版本,并选择特定版本安装
yum list docker-ce --showduplicates | sort -r7、下载安装docker
yum install docker-ce
---------------------------------------------------------------------
如选择特定版本:
sudo yum install <FQPN> # 例如:sudo yum install docker-ce-17.12.0.ce
8、启动并加入开机启动
sudo systemctl enable docker
9、验证安装是否成功(有client和service两部分表示docker安装启动都成功了)docker version
安装中可能出现问题
1、因为之前已经安装过旧版本的docker,在安装的时候报错如下:
Transaction check error:
file /usr/bin/docker from install of docker-ce-17.12.0.ce-1.el7.centos.x86_64 conflicts with file from package docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64
file /usr/bin/docker-containerd from install of docker-ce-17.12.0.ce-1.el7.centos.x86_64 conflicts with file from package docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64
file /usr/bin/docker-containerd-shim from install of docker-ce-17.12.0.ce-1.el7.centos.x86_64 conflicts with file from package docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64
file /usr/bin/dockerd from install of docker-ce-17.12.0.ce-1.el7.centos.x86_64 conflicts with file from package docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64
2、卸载旧版本的包
sudo yum erase docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64
3、再次安装docker
sudo yum install docker-ce
安装完成后修改docker默认存储路径
4. 修改docker.service文件.
vim /usr/lib/systemd/system/docker.service
- 在里面的EXECStart的后面增加后如下:
ExecStart=/usr/bin/dockerd --graph /home/docker配置Docker阿里镜像加速
配置文件:/etc/docker/daemon.json
创建文件:mkdir /etc/docker/
编辑配置文件:vim /etc/docker/daemon.json
将配置信息填入:(切记有缩进){ "registry-mirrors": ["https://registry.docker-cn.com"] }重新启动docker
systemctl restart docker 查看服务状态: systemctl status docker查看docker client\server端的版本信息
docker version
查看详细的容器信息
docker info
输出内容如下 ``` [root@autotest /]# 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: 14 ###容器数量
Running: 14 ###正在运行容器数
Paused: 0 ###暂停状态容器数
Stopped: 0 ###停止状态容器数
Images: 13 ###镜像数
Server Version: 20.10.6 ###docker服务器版本
Storage Driver: overlay2 ###存储驱动后端
Backing Filesystem: xfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
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
Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 05f951a3781f4f2c1911b05e61c160e9c30eaa8e
runc version: 12644e614e25b05da6fd08a38ffa0cfe1903fdec
init version: de40ad0
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-957.el7.x86_64 ###内核版本
Operating System: CentOS Linux 7 (Core)
OSType: linux
Architecture: x86_64
CPUs: 16
Total Memory: 15.67GiB
Name: autotest
ID: GV7D:DDO2:665I:MOYR:JMEX:R6V3:GH5T:FFC6:G6NC:76I5:B6DM:I565
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
Registry Mirrors: ###加速镜像
https://registry.docker-cn.com/ ###加速镜像地址
Live Restore Enabled: false
WARNING: bridge-nf-call-iptables is disabled WARNING: bridge-nf-call-ip6tables is disabled
镜像的apine版本是用于测试用的,非常小。
<a name="ga7Uq"></a>
## 实验
从远程仓库上下载nginx的alpine的1.14版本到本地
docker image pull nginx:1.14-alpine
<br />从远程仓库上下载busybox的到本地
docker pull bustbox

<a name="eCTLj"></a>
# Docker镜像管理
Docker镜像含有启动容器所需的文件系统及其内容,因此,其用于创建并启动Docker容器。
- 采用分成构建机制,最底层为bootfs,其之为rootfs
- **bootfs**:用于系统引导的文件系统,包括bootloader和kernel,容器启动完成后会被卸载以节约内存资源;
- **rootfs**:位于bootfs之上,表现为docker容器的根文件系统;
- 传统模式中,系统启动之时,内核挂载rootfs时会首先将其挂载到“只读”模式,完整性自检完成后将其重新挂载为读写模式。
- docker中,rootfs由内核挂载为“只读”模式,而后通过“联合挂载”技术额外挂载一个“读写”层

- 位于下层的镜像称为父镜像(parent image),最底层的称为基础镜像(base image)。
- 最上层为“可读写”层,其下的均为“只读”层。

- 启动容器时,docker daemon会尝试从本地获取相关镜像,本地镜像不存在时,其将从Registry中下载该镜像并保存到本地。
Registry
- Registry用于保存docker镜像,包括镜像的层次结构和元数据
- 用户可自建Registry,也可使用官方的Docker Hub
Registry分类
- Sponsor Registry:第三方的registry,供客户和Docker社区使用
- Mirror Registry:第三方的registry,只让客户使用
- Vendor Registry:由发布docker镜像的供应商提供registry
- Private Registry:通过设有防火墙和额外的安全层的私有实体提供的registry
**Repository**
- 由特定的docker镜像的所有迭代版本组成的镜像仓库
- 一个Registry中可以存在多个Repository
- Registry中可分为“顶层仓库”和“用户仓库”
- 用户仓库名称格式为“用户名/仓库名”
- 每个仓库可以包含多个Tag(标签),每个标签对应一个镜像
Index
- 维护用户账户、镜像的校验以及公共命名空间的信息
- 相当于为Registry提供了一个完成用户认证等功能的索引接口
<a name="mPxcL"></a>
# 镜像生成途径
- Dockerfile
- 基于容器制作
- Dokcer Hub automated builds
<a name="HsbGc"></a>
## 基于容器制作镜像
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
OPTIONS说明
- **-a :**提交的镜像作者;<br />
- **-c :**使用Dockerfile指令来创建镜像;修改原有基础镜像的命令。<br />
- **-m :**提交时的说明文字;<br />
- **-p :**在commit时,将容器暂停。<br />
实例基于容器制作的镜像会把容器中的数据一起做出镜像。<br />将容器a404c6c174a2 保存为新的镜像,并添加提交人信息和说明信息。
runoob@runoob:~$ docker commit -a “runoob.com” -m “my apache” a404c6c174a2 mymysql:v1 sha256:37af1236adef1544e8886be23010b66577647a40bc02c0885a6600b33ee28057 runoob@runoob:~$ docker images mymysql:v1 REPOSITORY TAG IMAGE ID CREATED SIZE mymysql v1 37af1236adef 15 seconds ago 329 MB
查看进入容器方式
docker inspect busybox:latest
<br />例子1<br />修改打包镜像的cmd指令
docker commit -a “zhangkai” -c ‘CMD [“/bin/heepd”,”f”,”h”,”/data/html”]’ -p name1 镜像名:标签名
查看docker自带的四种网络类型 <br />`docker network ls`<br /><br />bridge:桥接网络
查看网桥信息<br /><br />
<a name="2lDbL"></a>
# 虚拟化网络
vmware为我们提供了三种网络工作模式,它们分别是:Bridged(桥接模式)、NAT(网络地址转换模式)、Host-Only(仅主机模式)。<br />打开vmware虚拟机,我们可以在选项栏的“编辑”下的“虚拟网络编辑器”中看到VMnet0(桥接模式)、VMnet1(仅主机模式)、VMnet8(NAT模式),那么这些都是有什么作用呢?其实,我们现在看到的VMnet0表示的是用于桥接模式下的虚拟交换机;VMnet1表示的是用于仅主机模式下的虚拟交换机;VMnet8表示的是用于NAT模式下的虚拟交换机。<br /><br />同时,在主机上对应的有VMware Network Adapter VMnet1和VMware Network Adapter VMnet8两块虚拟网卡,它们分别作用于仅主机模式与NAT模式下。在“网络连接”中我们可以看到这两块虚拟网卡,如果将这两块卸载了,可以在vmware的“编辑”下的“虚拟网络编辑器”中点击“还原默认设置”,可重新将虚拟网卡还原。<br /><br />小伙伴看到这里,肯定有疑问,为什么在真机上没有VMware Network Adapter VMnet0虚拟网卡呢?那么接下来,我们就一起来看一下这是为什么。
<a name="heSjc"></a>
## Bridged(桥接模式)
什么是桥接模式?桥接模式就是将主机网卡与虚拟机虚拟的网卡利用虚拟网桥进行通信。在桥接的作用下,类似于把物理主机虚拟为一个交换机,所有桥接设置的虚拟机连接到这个交换机的一个接口上,物理主机也同样插在这个交换机当中,所以所有桥接下的网卡与网卡都是交换模式的,相互可以访问而不干扰。在桥接模式下,虚拟机ip地址需要与主机在同一个网段,如果需要联网,则网关与DNS需要与主机网卡一致。其网络结构如下图所示:<br /><br />接下来,我们就来实际操作,如何设置桥接模式。<br />首先,安装完系统之后,在开启系统之前,点击“编辑虚拟机设置”来设置网卡模式。<br /><br />点击“网络适配器”,选择“桥接模式”,然后“确定”<br /><br />在进入系统之前,我们先确认一下主机的ip地址、网关、DNS等信息。<br /><br />然后,进入系统编辑网卡配置文件,命令为vi /etc/sysconfig/network-scripts/ifcfg-eth0<br /><br />添加内容如下:<br /><br />编辑完成,保存退出,然后重启虚拟机网卡,使用ping命令ping外网ip,[测试](http://lib.csdn.net/base/softwaretest)能否联网。<br /><br />能ping通外网ip,证明桥接模式设置成功。<br />那主机与虚拟机之间的通信是否正常呢?我们就用远程工具来测试一下。<br /><br />主机与虚拟机通信正常。<br />这就是桥接模式的设置步骤,相信大家应该学会了如何去设置桥接模式了。桥接模式配置简单,但如果你的网络环境是ip资源很缺少或对ip管理比较严格的话,那桥接模式就不太适用了。如果真是这种情况的话,我们该如何解决呢?接下来,我们就来认识vmware的另一种网络模式:NAT模式。
<a name="asCCs"></a>
## NAT(地址转换模式)
刚刚我们说到,如果你的网络ip资源紧缺,但是你又希望你的虚拟机能够联网,这时候NAT模式是最好的选择。NAT模式借助虚拟NAT设备和虚拟DHCP服务器,使得虚拟机可以联网。其网络结构如下图所示:<br /><br />在NAT模式中,主机网卡直接与虚拟NAT设备相连,然后虚拟NAT设备与虚拟DHCP服务器一起连接在虚拟交换机VMnet8上,这样就实现了虚拟机联网。那么我们会觉得很奇怪,为什么需要虚拟网卡VMware Network Adapter VMnet8呢?原来我们的VMware Network Adapter VMnet8虚拟网卡主要是为了实现主机与虚拟机之间的通信。在之后的设置步骤中,我们可以加以验证。<br />首先,设置虚拟机中NAT模式的选项,打开vmware,点击“编辑”下的“虚拟网络编辑器”,设置NAT参数及DHCP参数。<br /><br /><br /><br />将虚拟机的网络连接模式修改成NAT模式,点击“编辑虚拟机设置”。<br /><br />点击“网络适配器”,选择“NAT模式”<br /><br />然后开机启动系统,编辑网卡配置文件,命令为vi /etc/sysconfig/network-scripts/ifcfg-eth0<br /><br />具体配置如下:<br /><br />编辑完成,保存退出,然后重启虚拟机网卡,动态获取ip地址,使用ping命令ping外网ip,测试能否联网。<br /><br />之前,我们说过VMware Network Adapter VMnet8虚拟网卡的作用,那我们现在就来测试一下。<br /><br /><br />如此看来,虚拟机能联通外网,确实不是通过VMware Network Adapter VMnet8虚拟网卡,那么为什么要有这块虚拟网卡呢?<br />之前我们就说VMware Network Adapter VMnet8的作用是主机与虚拟机之间的通信,接下来,我们就用远程连接工具来测试一下。<br /><br />然后,将VMware Network Adapter VMnet8启用之后,发现远程工具可以连接上虚拟机了。<br />那么,这就是NAT模式,利用虚拟的NAT设备以及虚拟DHCP服务器来使虚拟机连接外网,而VMware Network Adapter VMnet8虚拟网卡是用来与虚拟机通信的。
<a name="sTxpl"></a>
## Host-Only(仅主机模式)
Host-Only模式其实就是NAT模式去除了虚拟NAT设备,然后使用VMware Network Adapter VMnet1虚拟网卡连接VMnet1虚拟交换机来与虚拟机通信的,Host-Only模式将虚拟机与外网隔开,使得虚拟机成为一个独立的系统,只与主机相互通讯。其网络结构如下图所示:<br /><br />通过上图,我们可以发现,如果要使得虚拟机能联网,我们可以将主机网卡共享给VMware Network Adapter VMnet1网卡,从而达到虚拟机联网的目的。接下来,我们就来测试一下。<br />首先设置“虚拟网络编辑器”,可以设置DHCP的起始范围。<br /><br />设置虚拟机为Host-Only模式。<br /><br />开机启动系统,然后设置网卡文件。<br /><br />保存退出,然后重启网卡,利用远程工具测试能否与主机通信。<br /><br />主机与虚拟机之间可以通信,现在设置虚拟机联通外网。<br /><br />我们可以看到上图有一个提示,强制将VMware Network Adapter VMnet1的ip设置成192.168.137.1,那么接下来,我们就要将虚拟机的DHCP的子网和起始地址进行修改,点击“虚拟网络编辑器”<br /><br />重新配置网卡,将VMware Network Adapter VMnet1虚拟网卡作为虚拟机的路由。<br /><br />重启网卡,然后通过 远程工具测试能否联通外网以及与主机通信。<br /><br />测试结果证明可以使得虚拟机连接外网
<a name="NcG99"></a>
# Docker容器网络
<a name="CRR9r"></a>
## 实现原理
Docker使用Linux桥接(参考《Linux虚拟网络技术》),在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。<br />Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。
<a name="ru9Fu"></a>
## 四类网络模式
| 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 | (默认为该模式)网桥 |
<a name="5HIUe"></a>
### host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。<br />使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。<br />Host模式如下图所示:<br /><br />Host模式
<a name="870QG"></a>
### container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。<br />Container模式示意图:<br /><br />Container网络模式
<a name="Zm4GS"></a>
### none模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。<br />这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过--network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。<br />None模式示意图:<br /><br />None网络模式
<a name="yUZTN"></a>
### bridge模式
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。<br />从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。<br />bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。<br />bridge模式如下图所示:<br />
<a name="Co5up"></a>
## 实验一none模式
ip netns<br />ip netns 命令是用来管理 网络命名空间 的,网络命名空间可以实现 网络隔离。每个网络命名空间都提供了一个完全独立的标签网络协议栈,包括网络设备接口、IPV4 和 IPV6 协议栈、IP路由表、防火墙规则、端口、sockets 等。像 docker 就是利用 Linux 的网络命名空间来实现容器网络的隔离。具体详见linux笔记中命令<br /><br />创建两个网络名称空间<br /><br />在网络名称空间中执行命令<br /><br /><br />创建一对虚拟网卡(一个网卡有俩端)
ip link add name veth1.1 type veth peer name veth1.2 注释:ip link add name veth1.1(添加网卡1的1端名称) type veth(类型为veth) peer(添加另一端网卡) name veth1.2(添加网卡1的2端名称)
查看网卡信息<br /><br />上图可见veth1.2的另一端为veth1.1 veth1.1的另一端为veth1.2<br />将1.2端放到网络名称空间中1.1留到宿主机上
ip link set dev veth1.2 netns r1 将veth1.2移到网络名称空间r1中 ip link show 列出网卡信息
<br />在r1网络名称空间中修改网卡名称
ip netns exec r1 ip link set dev veth1.2 name eth0
<br />激活宿主机的veth1.1网卡分配地址
ifconfig veth1.1 10.1.0.1/24 up
<br />将名称空间中的eth0激活并分配地址
ip netns exec r1 ifconfig eth0 10.1.0.2/24 up
<br />网络名称空间r1ping宿主机<br /><br />将另一网卡放到r2中<br /><br /><br /><br /><br />实验解释
> 我们在宿主机上创建了两个网络名称空间,,并且创建了一对网卡,第一步将网卡1放到了R1中网卡2放到了宿主机上,ping互通。第二部将原本在宿主机上的网卡二放到放到网络名称空间R2上,ping互通。

<a name="creHv"></a>
## 实验二bridge模式
<br />查看主机名称:默认主机名称就是容器ID号
docker run —name t1 -it —network bridge —rm busybox:latest
<br />还可以将容器创建时就将hostname注入到容器主机中<br /><br />加入此主机通过主机名的方式访问其他主机或者其他容器,需具备(1、这个主机或者容器可以通主机名解析DNS服务器解析出主机名或者2、通过本地/etc/hosts文件解析主机名字)
/etc/hosts 文件存放本地记录的DNS解析
<br /><br /> 给定DNS解析地址:
docker run —name t1 -it —network bridge -h t1 —dns 114.114.114.114 —rm busybox:latest
也可以定以路径名为ilinux.io的DNS解析为114.114.114.114
<br />主动生成本机host文件中的解析记录
docker run —name t1 -it —network bridge -h t1 —dns 114.114.114.114 —add-host www.Dreambeer.io:1.1.1.1 —rm busybox:latest

<a name="f6DxM"></a>
### <br />
实现开放net桥桥接式容器的服务到宿主机外部去<br /><br />上述格式第一种类型<br />将http镜像中的web服务80端口暴露出来
docker run —name t1 -it —network bridge -p 80 —rm busybox:latest
<br />使用`docker inspect mywe`查看宿主机地址容器IP地址<br /><br />测试可以访问到:(这仅仅是内部访问)<br /><br />如果想要通过外部访问的话,需要将访问宿主机的IP地址容器80端口随机映射出宿主机的端口号<br /><br />通过`iptables -t nat -vnl` 查看路由规则<br /><br />实验下:<br /><br />删除掉容器对应规则也会被删除掉<br />上述格式第三种类型<br />
docker port myweb 查看指定容器的映射

docker run —name t1 -it —network bridge -p 172.20.0.67::80 —rm busybox:latest
指定固定主机的随机端口进行映射
> -p 172.20.0.67:***:### 注释:-p 172.20.0.67主机地址:***主机端口:###容器端口
0.0.0.0代表所有IP范围<br /><br />上述IP格式的第二种类型<br />
docker run —name myweb —rm -p 80:80 httpd:v0.2
将容器的80端口映射到宿主机所有IP的80端口

> 将容器的80端口映射到宿主机任意IP地址的80端口
上述IP格式的第四种类型<br />
docker run —name myweb —rm -p 172.20.0.67:8080:80 httpd:v0.2
将容器80端口映射至宿主机172.20.0.67的8080端口

-P(大写的P) 表示暴露所有端口(如果在镜像中已经指定要暴露什么端口,基于镜像启动时默认是不会暴露的,除非你用了-P(大写)选项)
<a name="QDM3d"></a>
## 实验三container模式

> 指例如两个名称空间各自使用独立的USER、PID、Mount和名称空间但是共享UTS、NET、IPC
例子1<br />1、启动两个容器:(效果如下)
docker run —name b1 -it —rm busybox docker run —name b2 -it —rm busybox

<a name="b0A50"></a>
## 
2、共享b1容器的网络名称空间
docker run —name b2 -it —network container:b1 —rm busybox
注释:表示此容器与b1,这样的共享仅仅是网络共享其他的还是隔离的

<a name="KTI5i"></a>
## 实验四host模式
docker run —name b2 —network host -it —rm busybox

<a name="U7ZYR"></a>
## 实验五-修改docker0网桥网络地址
> 默认docker使用docker0的172.17.*.*网络,可以改成其他网络吗?现在创建容器默认使用docker0的172.17.*.*网络
> 我们尝试创建新的网络
<br />1、停掉docker服务
systemctl stop docker
<br />2、编辑/etc/docker/daemon.json文件
> "bip": "10.0.0.1/16"为新加
{ “registry-mirrors”: [“https://4mii0w1b.mirror.aliyuncs.com","https://registry.docker-cn.com“], “bip”: “10.0.0.1/16” }
3、启动docker服务<br />`systemctl start docker `
不指定docker服务器是哪里的话,默认是/var/run/docker.sock<br />如指定的话可以:<br /><br />如果我们希望docker容器能让别人通过外部链接进来,则需要监听TCP端口配置如下:<br />修改/etc/docker/daemon.json文件添加如下行 <br /><br /><br /><br />指定链接固定主机上的容器<br />下图查看172.20.0.67:2375上的容器的镜像,可以通过其他主机远程连接访问<br />
<a name="V0BDL"></a>
## 实验六-创建自定义的桥(net桥、仅主机等等)
查看docker已有的网络
docker network ls
<br />其实docker还支持其他网络类型`docker inif`查看<br /><br />例子1:创建网桥<br />利用`docker network --help`查看<br /><br />利用`docker network create --help`查看<br />
docker network create -d bridge —subnet “172.26.0.1” docker0network
注释:
docker network create -d (网络类型为bridge) —subnet “子网地址为172.26.0.1” 最后跟网桥名称
```


如图查出来的接口名字为br-3291c2f3f6eb如想要修改名称:
- 先down掉改网卡
ip link set dev br-3291c2f3f6eb name docker1
创建新的容器试一下
在两个虚拟机上创建两个容器实验互通:

两边虚拟机网络地址不一致,需开启核心路由转发才可互通
开启Linux核心路由转发
临时开启:命令
[root@localhost network-scripts]# echo 1 > /proc/sys/net/ipv4/ip_forward
永久开启:写入配置文件
source一下立即生效
