2. Docker容器管理---------------- 接容器(一)续写
2.2 Docker****容器操作
容器创建:就是将镜像加载到容器的过程。
新创建的容器默认处于停止状态,不运行任何程序,需要在其中发起一个进程来启动容器。
2.2.1****创建容器
格式:docker create [选项] 镜像
常用选项:
-i:让容器开启标准输入
-t:让 Docker 分配一个伪终端 tty
-it :合起来实现和容器交互的作用,运行一个交互式会话 shell
docker create :创建一个新容器,但不启动它。
示例: docker create -it nginx:latest
docker create -it nginx:latest /bin/bash

2.2.2 启动容器
docker start :启动已创建的容器。
示例: docker start <container_id> 。
格式:docker start 容器的ID/名称

2.2.3****停止容器
docker stop :停止正在运行的容器。
示例: docker stop <container_id> 。 
2.2.4****查看容器状态
docker ps :查看正在运行的容器。
docker ps - a :查看所有容器,包括已停止的容器。
#查看容器的运行状态
[root@localhost ~]# docker ps -a #-a 选项可以显示所有的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
06991f608812 nginx:latest "/docker-entrypoint...." 22 seconds ago Created boring_napier
容器的ID号 加载的镜像 运行的程序 创建时间 当前的状态 端口映射 名称
2.2.5****创建并启动容器
可以直接执行 docker run 命令, 等同于先执行 docker create 命令,再执行 docker start 命令。
注意:容器是一个与其中运行的 shell 命令共存亡的终端,命令运行容器运行, 命令结束容器退出。
docker 容器默认会把容器内部第一个进程,也就是 pid=1 的程序作为 docker 容器是否正在运行的依 据,如果 docker 容器中 pid = 1 的进程挂了,那么 docker 容器便会直接退出,也就是说 Docker 容器中 必须有一个前台进程,否则认为容器已经挂掉。
容器的生命周期包括创建、启动、停止、重启、删除等操作。容器会根据其进程的状态自动结束,例如当容器中的 PID=1 的进程退出时,容器也会停止。
docker run centos:7 /usr/bin/bash -c ls /
docker ps -a #会发现创建了一个新容器并启动执行一条 shell 命令,之后就停止了

当利用 docker run 来创建容器时, Docker 在后台的标准运行过程是:
· Dockers引擎会在本地查找镜像
**·**本地找到镜像 然后启动镜像
**·**本地没有找到镜像,然后根据Docker引擎配置的仓库地址,远程去查找镜像。
**·**远程查询到镜像,把镜像下载到本地,然后启动镜像
**·**远程查询到镜像,Docker返回错误,提示镜像远程未找到。
**·**运行中的镜像支持:停止、启动、重启、删除(先停止才可以删除)操作 
2.2.6在后台持续运行docker run****创建的容器
需要在 docker run 命令之后添加 -d 选项让 Docker 容器以守护形式在后台运行。并且容器所运行的 程序不能结束
[root@localhost ~]# docker run -d centos:7 /usr/bin/bash -c "while true;do echo hello;done"
09d772cbe2dd99e2e003a854c29157eb675ec3cac8fa210371bb326ee0fe4e91
[root@localhost ~]# docker ps -a # 可以看出容器始终处于Up,运行状态
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
09d772cbe2dd centos:7 "/usr/bin/bash -c 'w..." 4 seconds ago Up 3 seconds kind_swirles
f430e87f1f31 centos:7 "/usr/bin/bash -c ls..." 2 hours ago Exited (0) 2 hours ago pensive_yonath
06991f608812 nginx:latest "/docker-entrypoint...." 4 hours ago Exited (137) 3 hours ago boring_napier
[root@localhost ~]# docker run -itd --name test1 centos:7 /bin/bash # 创建容器并持续运行容器
e04c449168100a782cc67f3a0235309809a2dc363734de4bea2050111b1f0666
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e04c44916810 centos:7 "/bin/bash" 2 seconds ago Up 1 second test1
09d772cbe2dd centos:7 "/usr/bin/bash -c 'w..." 37 seconds ago Up 37 seconds kind_swirles
f430e87f1f31 centos:7 "/usr/bin/bash -c ls..." 2 hours ago Exited (0) 2 hours ago pensive_yonath
06991f608812 nginx:latest "/docker-entrypoint...." 4 hours ago Exited (137) 3 hours ago boring_napier
docker容器的生命周期 
Docker 容器主要有以下 7 个状态:
created:已创建,还未运行的容器
running:正在运行中的容器
restarting:容器正在重启中
removing:容器正在迁移中
paused:已暂停状态的容器
exited:停止状态的容器
dead:死亡,主要是操作系统出现异常或者断电关机等有可能引发 dead 状态,不是很常见。
暂停和停止状态的区别
docker pause 命令挂起指定容器中的所有进程
docker stop 容器内主进程会在指定时间内被杀死,默认为 10s 后。
2.2.7****容器交互
需要进入容器进行命令操作时,可以使用 docker exec 命令进入运行着的容器。
执行命令 :使用 docker exec 命令在容器内运行命令。
示例: docker exec - it <container_id> bash ,进入容器交互式 shell 。
格式:docker exec -it 容器ID/名称 /bin/bash
-i 选项表示让容器的输入保持打开;
-t 选项表示让 Docker 分配一个伪终端。
[root@localhost opt]# docker start 06991f608812 #进入容器前,确保容器正在运行
06991f608812
[root@localhost opt]# docker exec -it 06991f608812 /bin/bash
root@06991f608812:/# ls
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib media opt root sbin sys usr
root@06991f608812:/# exit #退出容器后,容器仍在运行
exit
[root@localhost opt]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
06991f608812 nginx:latest "/docker-entrypoint...." 5 hours ago Up 55 seconds 80/tcp boring_napier
#不加 -d 选项会创建容器后直接进入容器,但是退出容器,容器也会停止
[root@localhost opt]# docker run -it centos:7 bash
[root@a11726ca114a /]# ls
anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@a11726ca114a /]# exit
exit
[root@localhost opt]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a11726ca114a centos:7 "bash" 16 seconds ago Exited (0) 7 seconds ago intelligent_hugle
06991f608812 nginx:latest "/docker-entrypoint...." 5 hours ago Up About a minute 80/tcp boring_napier
[root@localhost opt]#
2.2.8****复制到容器中
怎么把宿主机的文件传入到容器内部
① linux 怎么复制
cp 原文件路径目标文件路径
docker cp l opt / abc 容器 id: /opt/abc
#======复制到容器中
[root@localhost ~]# echo qwe123 > test.txt
[root@localhost ~]# ls
test.txt
[root@localhost ~]# docker cp test.txt 06991f608812:/opt/
Successfully copied 2.05kB to 06991f608812:/opt/
[root@localhost ~]# docker exec -it 06991f608812 /bin/bash
root@06991f608812:/# cd /opt/
root@06991f608812:/opt# ls
test.txt
root@06991f608812:/opt# cat test.txt
qwe123
root@06991f608812:/opt# exit
exit
[root@localhost ~]#
#从容器复制文件到主机
[root@localhost ~]# docker cp 06991f608812:/opt/test.txt /opt/
Successfully copied 2.05kB to /opt/
[root@localhost ~]# ls /opt/
test.txt
2.2.9****容器的导出与导入
用户可以将任何一个 Docker 容器从一台机器迁移到另一台机器。在迁移过程中,可以使用 docker
export 命令将已经创建好的容器导出为文件,无论这个容器是处于运行状态还是停止状态均可导
出。可将导出文件传输到其他机器,通过相应的导入命令实现容器的迁移。
#导出格式:docker export 容器ID/名称 > 文件名
[root@localhost ~]# docker export 6fb763e4eccd > centos7.tar
[root@localhost ~]# ls
centos7.tar
#导入格式:cat 文件名 | docker import -- 镜像名称:标签
[root@localhost ~]# cat centos7.tar | docker import - centos7:test #导入后会生成镜像,但不会创建容器
sha256:9cff41e475b2525d8b870e119c719315c9520446bc373ab59c4fabc6761940f4
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos7 test b0831576570e 2 minutes ago 204MB
2.2.10****删除容器
格式:docker rm [-f] 容器ID/名称
docker stop 2592d3fad0fb
docker rm 2592d3fad0fb #删除已经终止状态的容器
docker rm -f 2592d3fad0fb #强制删除正在运行的容器
docker ps -a | awk 'NR>=2{print "docker stop "$1}' | bash #批量停止容器
docker ps -a | awk 'NR>=2{print $1}'| xargs docker stop
docker ps -a | awk 'NR>=2{print "docker rm "$1}' | bash #批量删除所有容器
docker ps -a | awk 'NR>=2{print $1}'| xargs docker rm
docker images | awk 'NR>=2{print "docker rmi "$3}'| bash #批量删除镜像
docker images | grep none | awk '{print $3}' | xargs docker rmi #删除none镜像
docker rm $(docker ps -a -q) #批量清理后台停止的容器
3. Docker****网络管理
3.1 Docker****网络实现原理
Docker使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥 (docker0) , Docker 启动一个容器时会根据 Docker网桥的网段分配给容器一个 IP 地址,称为 Container-IP ,同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信。
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法直接通过 Container-IP 访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即 docker run 创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[ 宿主机 IP]:[ 容器端口 ] 访问容器。
[root@localhost ~]# docker run -d --name test1 -P nginx #随机映射端口(从32768开始)
d706efd035aacca888202f2b0e622df5c23b8913542d62bcf294ddf652dea220
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d706efd035aa nginx "/docker-entrypoint...." 4 seconds ago Up 3 seconds 0.0.0.0:49153->80/tcp, :::49153->80/tcp test1
[root@localhost ~]# docker run -d --name test2 -p 4200:80 nginx #指定映射端口
dd567b0b0a0c6fc3b0d991fa164d5407666f21d62da174afa13171e99ba7e274
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dd567b0b0a0c nginx "/docker-entrypoint...." 2 seconds ago Up 2 seconds 0.0.0.0:4200->80/tcp, :::4200->80/tcp test2
d706efd035aa nginx "/docker-entrypoint...." 40 seconds ago Up 39 seconds 0.0.0.0:49153->80/tcp, :::49153->80/tcp test1
浏览器访问:http://192.168.10.61:49153/ http://192.168.10.61:4200
#查看容器的输出和日志信息
docker logs 容器的ID/名称

3.2 Docker****的网络模式
用 docker run 创建 Docker 容器时,可以用 --net 或 --network 选项指定容器的网络模式
3.2.1 host****模式
相当于Vmware 中的桥接模式,与宿主机在同一个网络中,但没有独立 IP 地址。
Docker使用了 Linux 的 Namespaces 技术来进行资源隔离,如 PID Namespace 隔离进程, Mount Namespace隔离文件系统, Network Namespace 隔离网络等。
一个 Network Namespace 提供了一份独立的网络环境,包括网卡、路由、 iptable 规则等都与其他的 Network Namespace隔离。 一个 Docker 容器一般会分配一个独立的 Network Namespace 。 但如果启动容器的时候使用host 模式,那么这个容器将不会获得一个独立的 Network Namespace , 而是和宿主机共用一个Network Namespace 。容器将不会虚拟出自己的网卡、配置自己的 IP 等,而是使用宿主机的 IP 和端口。
docker run -d --name nginx-host --network host nginx

总结:host 模式:容器与宿主机共享网络环境,不具备独立的 IP 和网卡 ,而是使用宿主机的 IP 和端口
3.2.2 Container****模式
在理解了host 模式后,这个模式也就好理解了。这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace ,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP ,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。 
docker run -itd --name test1 centos:7 /bin/bash #--name 选项可以给容器创建一个自定义名称
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cbda1512e1bc centos:7 "/bin/bash" 14 minutes ago Up 14 minutes test
[root@localhost ~]# docker inspect -f '{{.State.Pid}}' cbda1512e1bc
85509
[root@localhost ~]# ls -l /proc/85509/ns
总用量 0
lrwxrwxrwx. 1 root root 0 12月 22 21:23 ipc -> ipc:[4026532815]
lrwxrwxrwx. 1 root root 0 12月 22 21:23 mnt -> mnt:[4026532813]
lrwxrwxrwx. 1 root root 0 12月 22 21:07 net -> net:[4026532818]
lrwxrwxrwx. 1 root root 0 12月 22 21:23 pid -> pid:[4026532816]
lrwxrwxrwx. 1 root root 0 12月 22 21:23 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 12月 22 21:23 uts -> uts:[4026532814]
[root@localhost ~]# docker run -itd --name qwe --net=container:cbda1512e1bc centos:7 /bin/bash
6b0d40d60beaced35c129a321822b8ccba4b3ce275a98993b62e7575baccb716
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6b0d40d60bea centos:7 "/bin/bash" 5 seconds ago Up 3 seconds qwe
cbda1512e1bc centos:7 "/bin/bash" 14 minutes ago Up 14 minutes test
[root@localhost ~]# docker inspect -f '{{.State.Pid}}' 6b0d40d60bea
86216
[root@localhost ~]# ls -l /proc/86216/ns
总用量 0
lrwxrwxrwx. 1 root root 0 12月 22 21:24 ipc -> ipc:[4026532885]
lrwxrwxrwx. 1 root root 0 12月 22 21:24 mnt -> mnt:[4026532883]
lrwxrwxrwx. 1 root root 0 12月 22 21:24 net -> net:[4026532818]
lrwxrwxrwx. 1 root root 0 12月 22 21:24 pid -> pid:[4026532886]
lrwxrwxrwx. 1 root root 0 12月 22 21:24 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 12月 22 21:24 uts -> uts:[4026532884]
总结:与指定的容器共享network 命令空间
3.2.3****无网络模式(none)
使用none 模式, Docker 容器拥有自己的 Network Namespace ,但是,并不为 Docker 容器进行任何网络配置。 也就是说,这个Docker 容器没有网卡、 IP 、路由等信息。这种网络模式下容器只有lo回环网络,没有其他网卡。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。 
总结 : none 模式 是指禁用网络功能 只有 lo 接口 在容器创建时使用 --network=none 指定
3.2.4****桥接模式(bridge)
bridge模式是 docker 的默认网络模式,不用 --net 参数,就是 bridge 模式。
相当于Vmware 中的 nat 模式,容器使用独立 network Namespace ,并连接到 docker0 虚拟网卡。通过 docker0网桥以及 iptables nat 表配置与宿主机通信,此模式会为每一个容器分配 Network
Namespace 、设置 IP 等,并将一个主机上的 Docker 容器连接到一个虚拟网桥上。
( 1 )当 Docker 进程启动时,会在主机上创建一个名为 docker0 的虚拟网桥,此主机上启动的 Docker 容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
( 2 )从 docker0 子网中分配一个 IP 给容器使用,并设置 docker0 的 IP 地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair 设备。 veth 设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth 设备常用来连接两个网络设备。
( 3 ) Docker 将 veth pair 设备的一端放在新创建的容器中,并命名为 eth0 (容器的网卡),另一端放在主机中, 以 * 这样类似的名字命名,并将这个网络设备加入到 docker0 网桥中。可以通过 brctl show 命令查看。
( 4 )使用 docker run -p 时, docker 实际是在 iptables 做了DNAT规则,实现端口转发功能。可以使用 iptables -t nat -vnL 查看。 
virbr0 是 Linux 系统中的一种网络接口,它是支持虚拟机网络通信的一种默认的虚拟桥接网络。当你安装虚拟化技术(比如 KVM 、 VirtualBox 等)的时候,就会创建这样的虚拟网络桥接。
用" 大白话 " 来理解它, virbr0 就像是一个虚拟的交换机或路由器,它把你的计算机和虚拟机连接起来,让虚拟机可以通过它与外界进行网络通信。简单来说,您的电脑和虚拟机可以被看作是在同一个局域网内。
这就像一栋大楼中的各个房间可以通过交换机(这里是虚拟的 virbr0 )和大楼外的世界(互联网)进行通讯一样。每个房间(虚拟机)都有自己的门牌号(IP 地址),通过这个 " 虚拟的交换机 " ,门牌号可以被识别并且数据可以正确地在各个房间(虚拟机)和外部的世界之间传递
总结:bridge 网络模式 容器运行在同一宿主机内的虚拟网桥上,可以通过容器互相通信,与宿主机网络隔离。
3.2.5****自定义模式
自定义网络模式,docker 提供了三种自定义网络驱动: bridge overlay macvlan
bridge驱动类似默认的 bridge 网络模式,但增加了一些新的功能, overlay 和 macvlan 是用于创建跨主机网络
建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS 解析容器名称到 IP 地址
Docker提供了创建这些网络的默认网络驱动程序,你可以创建一个新的 Bridge 网络, Overlay 或 Macvlan网络
bridge 单机网络模式适合在一台宿主机 内容器互联
overlay 跨主机容器互联 docker swarm
macvlan 容器像一台物理机一样 直接获取宿主机的所在的网络的 IP (容器像物理机一样直接连接局域网)
#直接使用bridge模式,是无法支持指定IP运行docker的,例如执行以下命令就会报错
docker run -itd --name test3 --network bridge --ip 172.17.0.10 centos:7 /bin/bash
//创建自定义网络
#可以先自定义网络,再使用指定IP运行docker
docker network create --subnet=172.18.0.0/16 --opt "com.docker.network.bridge.name"="docker1" mynetwork
---------------------------------------------------------------------------------------------------------
#docker1 为执行 ifconfig -a 命令时,显示的网卡名,如果不使用 --opt 参数指定此名称,那你在使用 ifconfig -a 命令查看网络信息时,看到的是类似 br-110eb56a0b22 这样的名字,这显然不怎么好记。
#mynetwork 为执行 docker network list 命令时,显示的bridge网络模式名称。
---------------------------------------------------------------------------------------------------------
docker run -itd --name test4 --net mynetwork --ip 172.18.0.10 centos:7 /bin/bash


3.2.6****总结:
- 桥接模式( bridge ): 默认的网络模式,容器通过虚拟网桥与宿主机和其他容器通信。
- 主机模式( host ): 容器共享宿主机的网络栈,直接使用宿主机的 IP 地址。
- 容器模式( container ): 容器共享另一个容器的网络栈,两个容器可以使用相同的 IP 地址进行通信。
- 无网络模式( none ): 容器没有网络配置,只有回环接口( lo )。
- 自定义网路 :定义网络允许用户自定义容器的网络范围、子网和路由,从而提供更高的网络控制和隔离性。
额外附加: - Overlay :这是 Docker Swarm 模式的网络,主要用于在多个主机上创建一个分布式网络。容器间即便在不同的主机也能完成通信,相当于在跨主机的容器之间创建了一个覆盖网络。
- Macvlan : Macvlan 模式可以让容器直接连接到主机的物理网络,每个 Macvlan 接口都有一个唯一的MAC 地址,此模式使得容器看起来就像是网络上的物理设备。