linux云计算之Docker容器的各种操作,容器各种状态之间如何转换,以及实现容器的底层技术
1.容器
本节讨论容器的各种操作,容器各种状态之间如何转换,以及实现容器的底层技术。
容器: 由镜像运行形成容器
镜像: 构建,制作镜像 docker commit
docker run -it centos
docker images
docker ps
1.启动容器
docker run 是启动容器的方法
在Dockerfile 中,可用三种方式指定容器启动时执行的命令
CMD 指令。
ENTRYPOINT指令。
在 docker run 命令行中指定。
CMD和enterpoint的区别
在Dockerfile中,只能有一个ENTRYPOINT指令,如果有多个ENTRYPOINT指令则以最后一个为准。
在Dockerfile中,只能有一个CMD指令,如果有多个CMD指令则以最后一个为准。
在Dockerfile中,ENTRYPOINT指令或CMD指令,至少必有其一。
例如
docker run --name bbox1 busybox pwd容器启动时执行 pwd,返回的 / 是容器中的当前目录。 / 根 表示镜像工作目录在 / 下面
docker ps docker ps 或 docker container ls 可以查看 Docker host 中当前运行的容器
docker ps -a-a 会显示所有状态的容器, 他的状态为退出exited 一闪而过over
这种“一闪而过”的容器通常不是我们想要的结果,我们希望容器能够保持 runing 状态,这样才能被我们使用。
COMMAD 第三列表示容器启动时使用的命令
2.让容器长期运行
因为容器的生命周期依赖于启动时执行的命令,只要该命令不结束,容器也就不会退出。
例如
docker run busybox /bin/sh -c "while true ; do sleep 1; done"while 语句让 bash 不会退出
docker ps 打开另一个终端查看容器仍处于运行状态 缺点:它占用了一个终端
docker run -d busybox /bin/sh -c "while true ; do sleep 1; done" -d 以后台方式启动容器。 容器启动后回到了 docker host 的终端。docker 返回了一串字符,这是容器的 ID。
docker ps
注意
CONTAINER ID 是容器的 “短ID”,前面启动容器时返回的是 “长ID”。短ID是长ID的前12个字符。
NAMES 字段显示容器的名字,在启动容器时可以通过 --name 参数显示地为容器命名,如果不指定,docker 会自动为容器分配名字。
通过 “长ID”、“短ID” 或者 “名称” 来指定 要操作的容器。
停止一个容器
docker stop 13556b3f36d9 通过 “短ID” 指定了要停止的容器。
通过 while 启动的容器虽然能够保持运行,但实际上没有干什么有意义的事情。
容器常见的用途是运行后台服务
docker run -d --name "my_httpd" httpd用 --name 指定了容器的名字。
docker ps
docker history httpd
看到容器运行的命令是httpd-foreground, 通过 docker history 可知这个命令是通过 CMD 指定的。
3.两种进入容器的方法 attach 和 exec
1.docker attach 可以 attach 到容器 启动命令的终端,
例如:
docker run -d busybox /bin/sh -c "while true; do sleep 1; echo I_am_in container; done"
docker ps
docker attach 7a13aecce97473 通过 “长ID” attach 到了容器的启动命令终端,之后看到的是echo 每隔一秒打印的信息。
注:
可通过 Ctrl+p 然后 Ctrl+q 组合键退出 container 终端。
2.docker exec 进入相同的容器
docker exec -it 7a13aecce974 /bin/sh
ps -elf
hostname
注意
-it 以交互模式打开 pseudo-TTY,执行 bash,其结果就是打开了一个 bash 终端。
进入到容器中,容器的 hostname 就是其 “短ID”。
ps -elf 显示了容器启动进程while 以及当前的 bash 进程。
执行 exit 退出容器,回到 docker host。
docker exec -it <container容器id> /bash|sh 是执行 exec 最常用的方式。
4.attach 和 exec区别
attach 直接进入容器 启动命令 的终端,不会启动新的进程。
exec 则是在容器中打开新的终端,并且可以启动新的进程。
直接在终端中查看启动命令的输出,用 attach; 其他情况使用 exec。
查看日志 查看启动命令的输出 使用 docker logs 命令
docker logs -f 容器-f 的作用与 tail -f 类似,能够持续打印输出。
5.运行容器的分类
按用途容器 分为两类:服务类容器 和 工具类容器。
1. 服务类容器以 daemon 的形式运行,对外提供服务。比如 web server,数据库等。
通过 -d 以后台方式启动这类容器是非常合适的。
如果要排查问题,可以通过 exec -it 进入容器。
2. 工具类容器通常给能我们提供一个临时的工作环境,
通常以 run -it 方式运行,
docker run -it busybox
wget www.baidu.com
exit
注意
运行 busybox,run -it 的作用是在容器启动后就直接进入。
通过 wget 验证了在容器中访问 internet 的能力。
执行 exit 退出终端,同时容器停止。
busybox是一个软件工具箱,里边集成了linux中几百个常用的linux命令以及工具。
工具类容器多使用基础镜像,例如 busybox、debian、ubuntu 等。
6.容器运行小结
容器运行相关的知识点:
当 CMD 或 Entrypoint 或 docker run 命令行指定的命令运行结束时,容器停止。
通过 -d 参数在后台启动容器。
通过 exec -it 可进入容器并执行命令。
指定容器的三种方法:
短ID。
长ID。
容器名称。 可通过 --name 为容器命名。重命名容器可执行docker rename。
容器按用途可分为两类:
服务类的容器
工具类的容器
7.容器常用操作 停止 启动 重启
stop/start/restart +容器
1.docker stop 可以停止运行的容器
docker ps
docker stop id
docker ps -a
容器在 docker host 中实际上是一个进程,docker stop 命令本质上是向该进程发送一个 SIGTERM 信号。
想快速停止容器,可使用 docker kill 命令,其作用是向容器进程发送 SIGKILL 信号。
docker kill my_httpd
2.对于处于停止状态的容器,可以通过 docker start 重新启动。
docker start my_httpd
docker ps
注意
docker start 会保留容器的第一次启动时的所有参数。
docker restart 可以重启容器,其作用就是依次执行 docker stop 和docker start。
3.容器可能会因某种错误而停止运行。 重启
对于服务类容器,启动容器时设置 --restart 重启 就可以达到这个效果。
docker run -d --restart=always httpd
--restart=always 意味着无论容器因何种原因退出(包括正常退出),就立即重启。
该参数的形式还可以是 --restart=on-failure:3,意思是如果启动进程退出代码非0,则重启容器,最多重启3次。
8.pause/unpause 容器
暂时让容器暂停工作一段时间,比如要对容器的文件系统打个快照,或者 dcoker host 需要使用 CPU,这时可以执行 docker pause。暂停
docker pause id
docker ps 处于暂停状态的容器不会占用 CPU 资源,直到通过 docker unpause 恢复运行。
docker unpause
9.删除容器
docker使用一段时间后,host 会有大量已经退出了的容器。这些容器依然会占用 host 的文件系统资源,
如果确认不会再重启此类容器,可以通过 docker rm 删除。
docker rm id
docker rm 一次可以指定多个容器,如果希望批量删除所有已经退出的容器
docker rm -v $(docker ps -aq -f status=exited)
批量删除
docker ps -aq
docker ps -aq -f status=exited查找状态为exited的
docker rm `docker ps -aq -f status=exited`删除
注意:docker rm 是删除容器,而 docker rmi 是删除镜像。
10.容器底层技术cgroup案例
一个 docker host 上会运行若干容器,每个容器都需要 CPU、内存和 IO 资源。
对于 KVM,VMware 等虚拟化技术,用户可以控制分配多少 CPU、内存资源给每个虚拟机。
对于容器Docker 也提供了类似的机制避免某个容器因占用太多资源而影响其他容器乃至整个 host 的性能。
容器的底层实现技术
cgroup 和 namespace 是最重要的两种技术。
cgroup 实现资源限额, namespace 实现资源隔离。
1.cgroup
cgroup 全称 Control Group。Linux 操作系统通过 cgroup 可以设置进程使用 CPU、内存 和 IO 资源的限额。
cgroup 在 /sys/fs/cgroup
实例 启动一个容器,设置 --cpu-shares=512
cd sys/fs/cgroup/cpu/docker
cat cpu.shares
docker run -it --cpu-shares 512 progrium/stress -c 1
该镜像可用于对容器执行压力测试。
docker ps查看容器的 ID
在 /sys/fs/cgroup/cpu/docker 目录中,Linux 会为每个容器创建一个 cgroup 目录,以容器长ID 命名:
ls
目录中包含所有与 cpu 相关的 cgroup 配置,文件 cpu.shares 保存的就是 --cpu-shares 的配置,值为 512。
默认设置下,所有容器可以平等地使用 host CPU 资源并且没有限制。
Docker 可以通过 -c 或 --cpu-shares 设置容器使用 CPU 的权重。如果不指定,默认值为 1024。
通过 -c 设置的 cpu share 并不是 CPU 资源的绝对数量,而是一个相对的权重值。某个容器最终能分配到的 CPU 资源取决于它的 cpu share 占所有容器 cpu share 总和的比例。
通过 cpu share 可以设置容器使用 CPU 的优先级。
/sys/fs/cgroup/memory/docker 和 /sys/fs/cgroup/blkio/docker 中保存的是内存以及 Block IO 的 cgroup 配置。
2.Namespace 命名空间
在每个容器中,我们都可以看到文件系统,网卡等资源,这些资源看上去是容器自己的。拿网卡来说,每个容器都会认为自己有一块独立的网卡,即使 host 上只有一块物理网卡。这种方式非常好,它使得容器更像一个独立的计算机。
Linux 实现这种方式的技术是 namespace。namespace 管理着 host 中全局唯一的资源,并可以让每个容器都觉得只有自己在使用它。namespace 实现了容器间资源的隔离。
Linux 使用了六种 namespace,分别对应六种资源:Mount、UTS、IPC、PID、Network 和 User,
1.Mount namespace 底层硬件设备
Mount namespace 让容器看上去拥有整个文件系统。
容器有自己的 / 目录,可以执行 mount 和 umount 命令。当然我们知道这些操作只在当前容器中生效,不会影响到 host 和其他容器。
2.UTS namespace有自己的主机名
简单的说,UTS(UNIX Time-sharing System) namespace 让容器有自己的 hostname。 默认情况下,容器的 hostname 是它的短ID,可以通过 -h 或 --hostname 参数设置。
docker run -it --hostname bbox4 busybox
hostname
3.IPC namespace 进程间通信的ipc
IPC namespace 让容器拥有自己的共享内存和信号量(semaphore)来实现进程间通信,而不会与 host 和其他容器的 IPC 混在一起。
4.PID namespace 进程号
容器在 host 中以进程的形式运行 docker ps
ps axf 可以查看容器进程
所有容器的进程都挂在 container进程下,同时也可以看到容器自己的子进程。
如果我们进入到某个容器,ps 就只能看到自己的进程了
docker exec -it 70a5fe753756 /bin/sh
/ # ps axf
而且进程的 PID 不同于 host 中对应进程的 PID,容器中 PID=1 的进程当然也不是 host 的 init 进程。也就是说:容器拥有自己独立的一套 PID,这就是 PID namespace 提供的功能。
5.Network namespace
Network namespace 让容器拥有自己独立的网卡、IP、路由等资源。
6.User namespace
User namespace 让容器能够管理自己的用户,host 不能看到容器中创建的用户。
[root@host2 ~]# docker run -it centos
[root@2e89852f6f0b /]# useradd xuld
[root@2e89852f6f0b /]# [root@host2 ~]# su - xuld
在容器中创建了用户 xuld,但 host 中并不会创建相应的用户。
7.小结
本节首先学习了容器的各种操作,以及实现容器的底层技术:cgroup 和 namespace。
容器的常用操作命令:
create 创建容器
run 运行容器
pause 暂停容器
unpause 取消暂停继续运行容器
stop 发送 SIGTERM 停止容器
kill 发送 SIGKILL 快速停止容器
start 启动容器
restart 重启容器
attach attach 到容器启动进程的终端
exec 在容器中启动新进程,通常使用 "-it" 参数
logs 显示容器启动进程的控制台输出,用 "-f" 持续打印
rm 从磁盘中删除容器 -v
3.Docker的网络管理
容器的网络默认与宿主机、与其他容器相互隔离,且容器中可以运行一些网络应用,比如nginx、web应用、数据库等,如果需要让外部也可以访问这些容器中运行的网络应用,那么就需要配置网络来实现。
同样的,不同需求下,容器与宿主机的通信有不同的业务状态这时候就需要容器网络管理以达成管理不同业务下相关的网络配置
bridge network(网桥)模式:默认的网络模式,类似虚拟机的nat模式
host network(主机)模式:容器与宿主机之间的网络无隔离,即容器直接使用宿主机网络。
none network模式:容器禁用所有网络。
overlay network(覆盖)模式:利用vxlan实现的bridge模式。
macvlan network模式:容器具备MAC地址,使其在外部看来是一台真实的网络设备。
查看网络 查看桥
docker network ls
ip a
brctl show
docker network ls 查看网络
docker network create [参数] 网络创建网络
常用参数:
-d 指定网络的驱动,不指定默认为bridge
-- subnet 指定子网网段(192.168.0.0/16)
-- ip-range 指定容器的IP范围
-- gateway 子网的网关
docker network rm 网络 [网络..]删除网络
docker network inspect 网络查看网络详情
docker run/create --network 网络使用网络
docker network connect/disconnect 网络 容器网络连接与断开
4.常见的网络模式简介 none和host和bridge网络
1.none网络模式的特点:
容器上没有网络,也无需任何网络设备
如果需要使用网络,需要用户自行安装与配置
2.host网络模式的特点:
容器完全共享宿主机的网络,网络没有隔离。宿主机的网络就是容器的网络。
容器、主机上的应用所使用的端口不能重复。
外部可以直接访问容器,不需要端口映射
容器IP就是宿主机的IP
3.Bridge 网络模式
bridge网络模式的特点:
1.宿主机上需要单独的bridge网卡,如Docker默认创建的docker0。
2.容器之间、容器与主机之间的网络通信,是借助为每一个容器生成的一对veth pair虚拟网络设备对,进行通信的。一个在容器上,另一个在宿主机上。
3.每创建一个基于bridge网络的容器,都会自动在宿主机上创建一个veth虚拟网络设备。外部无法直接访问容器。需要建立端口映射才能访问。
4.容器借由veth虚拟设备通过如Docker0这种bridge网络设备进行通信。
5.每一容器具有单独的IP
6.bridge网络模式下宿主机与容器服务使用的端口可以重复
Docker 安装时会创建一个 命名为 docker0 的 linux bridge。如果不指定--network,创建的容器默认都会挂到 docker0 上。
brctl show
当前 docker0 上没有任何其他网络设备,创建容器看有什么变化。
docker run -it busybox
brctl show
一个新的网络接口 veth6f0112被挂到了 docker0 上, veth6f0112就是新创建容器的虚拟网卡。
容器的网络配置。
容器有一个网卡 eth0@if60, 为什么不是 veth6f01129
实际上 eth0@if60 和 veth6f01129 是一对 veth pair。
veth pair 是一种成对出现的特殊网络设备,可以把它们想象成由一根虚拟网线连接起来的一对网卡,网卡的一头(eth0@if60)在容器中,另一头( veth6f01129)挂在网桥 docker0 上,其效果就是将 eth0@if60 也挂在了 docker0 上。
docker run -it busybox
我们还看到 eth0@if60 已经配置了 IP 172.17.0.2
docker network inspect bridge 看一下 bridge 网络的配置信息
bridge 网络配置的 subnet 就是 172.17.0.0/16,并且网关是 172.17.0.1。这个网关就是 docker0
ifconfig docker0
当前容器网络拓扑结构
容器创建时,docker 会自动从 172.17.0.0/16 中分配一个 IP,这里 16 位的掩码保证有足够多的 IP 可以供容器使用。
除了 none, host, bridge 这三个自动创建的网络,用户也可以根据业务需要创建 user-defined 网络。
自定义容器网络
除了 none, host, bridge 这三个自动创建的网络,用户也可以根据业务需要创建 user-defined 网络。
Docker 提供三种 user-defined 网络驱动:bridge, overlay 和 macvlan。
overlay 和 macvlan 用于创建跨主机的网络
4.创建 bridge 网络
docker network create --driver bridge my_net
docker network ls
brctl show查看当前 host 的网络结构变化
新增了一个网桥 my_net 的短 id
docker network inspect my_net 查看 my_net 的配置信息
这里 172.18.0.0/16 是 Docker 自动分配的 IP 网段
brctl show
docker run -it --network my_net centos
ip a
5.可以自己指定 IP 网段10.24.0.0
只需在创建网段时指定 --subnet 和 --gateway 参数:
docker network create --driver bridge --subnet 10.24.23.0/16 --gateway 10.24.0.1 my_net2
docker network ls
brctl show
容器要使用新的网络,需要在启动时通过 --network 指定
docker run -it --network my_net2 centos
ip a容器分配到的 IP 为 10.24.0.2
容器的 IP 都是 docker 自动从 subnet 中分配,也可以指定一个静态 IP 通过--ip指定
docker run -it --network my_net2 --ip 10.24.23.100 centos
注意
只有使用 --subnet 创建的网络才能指定静态 IP。
my_net 创建时没有指定 --subnet,如果指定静态 IP 报错如下:
6.增加网卡 理解容器之间的连通性
docker network ls两个 busybox 容器都挂在 my_net2 上 能够互通
异网络 跨网络不同的网络如果加上 路由就可以通信
docker run -itd --network my_net2 centos
docker exec -it 910463badad30 /bin/sh
Ip a
docker run -it --network my_net centos
ip r查看 host 上的路由表
cat /proc/sys/net/ipv4/ip_forward看是否开启路由转发
iptables-save查看防火墙 路由规则
注意
iptables DROP 掉了网桥 docker0 br-6bcd98e3c34e br-1f0b3d7673750之间双向的流量。
容器my_net增加了一个网卡 eth1,分配了 my_net 的 IP 10.24.0.3
docker network connect my_net2 621a462438a621a462438 为my _ net 的短id
my_ net 查看
之前
之后
在 my_net ping my_net2
my _net2的网卡
7.容器访问外部世界
容器 访问 外部网络
1.容器访问外部世界
2.外部世界访问容器
在my_net容器中查看能否上网
ping www.baidu.com
注意
这里外网指的是容器网络以外的网络环境,并非特指 internet。
这里的关键就是 NAT 查看 docker host 上的 iptables 规则:
iptables -t nat -S
在 NAT 表中,有这么一条规则:
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
其含义是:
如果网桥 docker0 收到来自 172.17.0.0/16 网段的外出包,把它交给 MASQUERADE 处理。而 MASQUERADE 的处理方式是将包的源地址替换成 host 的地址发送出去,即做了一次网络地址转换(NAT)。
通过 tcpdump 查看地址是如何转换的。先查看 docker host 的路由表:
ip r
默认路由通过 ens33 发出去,所以我们要同时监控 ens33 和 docker0 上的 icmp(ping)数据包。
当 centos ping baidu.com 时,tcpdump 输出如下:
docker0 收到 centos 的 ping 包,源地址为容器 IP 172.17.0.2,这没问题,交给 MASQUERADE 处理。这时,在 ens33 上我们看到了变化:
ping 包的源地址变成了 ens33 的 IP 192.168.137.104
这就是 iptable NAT 规则处理的结果,从而保证数据包能够到达外网。过程
注释:
1.centos 发送 ping 包:172.17.0.2 > www.baidu.com。
2.docker0 收到包,发现是发送到外网的,交给 NAT 处理。
3.NAT 将源地址换成 ens33 的 IP:192.168.137.104 > www.baidu.com。
4.ping 包从ens33 发送出去,到达 www.baidu.com。
5.通过 NAT,docker 实现了容器对外网的访问。
8.外部世界访问容器
端口映射。
docker 可将容器对外提供服务的端口映射到 host 的某个端口,外网通过该端口访问容器。容器启动时通过-p参数映射端口:
容器启动后,可通过 docker ps 或者 docker port 查看到 host 映射的端口。
httpd 容器的 80 端口被映射到 host 32770 上,这样就可通过 <host ip>:<32770> 访问容器的 web 服务了。
除了映射动态端口,也可在 -p 中指定映射到 host 某个特定端口,例如可将 80 端口映射到 host 的 8080 端口:
docker run -d -p 8080:80 httpd
curl 192.168.10.10:8080
每一个映射的端口,host 都会启动一个 docker-proxy 进程来处理访问容器的流量:
以 0.0.0.0:32770->80/tcp 为例分析整个过程:
docker-proxy 监听 host 的 32770 端口。
当 curl 访问 10.0.2.15:32770 时,docker-proxy 转发给容器 172.17.0.2:80。
httpd 容器响应请求并返回结果。
overlay网络模式的特点:
1.overlay网络模式实现方案有很多种,在Docker自身集成了一种,基于VXLAN隧道技术实现
2.overlay网络主要用于实现跨主机容器之间的通信
macvlan网络模式的特点:
1.macvlan的主要特点就是通信直接基于mac地址进行转发
2.在macvlan中宿主机担任的角色是一台二层交换机,Docker会维护一张mac地址表,当宿主机收到数据包时,直接根据mac地址找到对应的容器
3.而在容器内部互相通信的时候,容器直接使用IP互通,所以每个容器对于外面的网络都是一台真实的网络设备
5.容器数据管理
宿主机要直接访问容器中的文件,但是由于容器中的文件没有持久化,且容器没有使用数据卷,那么当容器删除后,文件数据也会随之消失,其他容器也无法直接访问相互的文件。
数据卷存在于宿主机的文件系统中,独立于容器,和容器的生命周期是分离的。
数据卷可以是目录也可以是文件,容器可以利用数据卷与宿主机进行数据共享,实现了容器间的数据共享和交换。
容器启动初始化时,如果容器使用的镜像包含了数据,这些数据会拷贝到数据卷中。
容器对数据卷的修改是实时进行的。
数据卷的变化不会影响镜像的更新。数据卷是独立于联合文件系统,镜像是基于联合文件系统。镜像与数据卷之间不会有相互影响。
镜像 2. volume
bind mounts: 将宿主机上的一个文件或目录挂载到容器上
volumes:由Docker创建和管理。使用Docker volume命令管理
docker run/create -v
-v 宿主机文件或文件夹路径:容器中的文件或文件夹路径
挂载一个主机目录作为数据卷
使用-v标记也可以指定挂载一个本地的已有目录到容器中去作为数据卷(推荐方式)。
例如 docker host 上有目录 /root/htdocs
[root@host2 htdocs]# vi index.html
<html><body><h1>This is a file in host file system!</h1></body></html>
通过 -v 将其 mount 到 httpd 容器:
[root@host2 ~]# docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
79984086504f1be3ec1b3e259318ae20a517c6a28a4ec722b5bfd436b822ea31
-v 的格式为 <host path>:<container path>。/usr/local/apache2/htdocs 就是 apache server 存放静态文件的地方。
由于 /usr/local/apache2/htdocs 已经存在,原有数据会被隐藏起来,取而代之的是 host $HOME/htdocs/ 中的数据,这与 linux mount 命令的行为是一致的。
[root@host2 ~]# curl 127.0.0.1:80
<html><body><h1>This is a file in host file system!</h1></body></html>
curl 显示当前主页确实是 $HOME/htdocs/index.html 中的内容。更新一下,看是否能生效:
[root@host2 ~]# echo "update index page" >~/htdocs/index.html
[root@host2 ~]# curl 127.0.0.1:80
update index page
host 中的修改确实生效了,bind mount 可以让 host 与容器共享数据。这在管理上是非常方便的。
这个功能在进行测试的时候十分方便,比如用户可以将一些程序或数据放到本地目录中,然后在容器内运行和使用。另外,本地目录的路径必须是绝对路径,如果目录不存在,Docker会自动创建。
Docker挂载数据卷的默认权限是读写(rw),用户也可以通过ro指定为只读:
[root@host2 ~]# docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs:ro httpd
20ae3006a19d1bd5552a612e82d8474223356bff73aacfc6427c9ff88b0c9855
[root@host2 ~]# docker exec -it 20ae bash
root@20ae3006a19d:/usr/local/apache2# echo "do some changes" >htdocs/index.html
bash: htdocs/index.html: Read-only file system
加了:ro之后,容器内对所挂载数据卷内的数据就无法修改了。
挂载一个本地主机文件作为数据卷
-v标记也可以从主机挂载单个文件到容器中作为数据卷(不推荐)。
docker run -d -p 801:80 -v ~/htdocs/index.html:/usr/local/apache2/htdocs/new_index.html httpd
3a50a099cb83af27f9084ca4e9030788cba85a24d72f97e7833070e48ca5ff4a
curl 127.0.0.1:801
<html><body><h1>It works!</h1></body></html>
[root@host2 ~]# curl 127.0.0.1:801/new_index.html
update index page
使用 bind mount 单个文件的场景是:只需要向容器添加文件,不希望覆盖整个目录。在上面的例子中,我们将 html 文件加到 apache 中,同时也保留了容器原有的数据。
6.Docker compose
前面我们使用 Docker 的时候,定义 Dockerfile 文件,然后使用 docker build、docker run 等命令操作容器。然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知。
Docker Compose是一个能一次性定义和管理多个Docker容器的工具。
Compose中定义和启动的每一个容器都相当于一个服务(service)
Compose中能定义和启动多个服务,且它们之间通常具有协同关系
我们通常使用YAML文件来配置我们应用程序的服务
1.安装pip工具 epel-release
2.执行以下命令:pip install -U docker-compose
3.检验是否安装成功:docker-compose version
3.Docker Compose文件配置与注意事项
常见的配置项:
version:指定Docker Compose File版本号
services:定义多个服务并配置启动参数
volumes:声明或创建在多个服务中共同使用的数据卷对象
networks:定义在多个服务中共同使用的网络对象
configs:声明将在本服务中要使用的一些配置文件
secrets:声明将在本服务中要使用的一些秘钥、密码文件
x-***:自定义配置。主要用于复用相同的配置
Docker Compose File 的格式要求非常严格,一定需要注意的有
配置项的缩进使用空格
注意配置项冒号后要添加空格
编写完Docker Compose File后可以使用docker-compose config 检查文件是否出错
官网例子
docker-compose.yml文件是一个YAML文件,它定义了Docker容器在生产环境中的行为。
执行docker stack deploy需要给应用命名。这里,它被设置为getstartedlab
在使用docker stack deploy命令之前,我们需要先运行:
查看service:
要查看一个stack的所有任务,可以运行docker stack ps,后面跟着你的app名,如下例所示:
如果只列出系统上的所有容器,任务也会显示出来,不过这并不会被服务过滤
可以通过更改docker-compose中的replicas值来扩展(缩小)应用程序。保存更改,并重新运行docker stack deploy命令:
查看服务及容器情况:
7.简答& 实验
简答题
实现容器的底层技术有哪些?
容器网络如何实现自定义?
容器与外界通信原理是什么?
容器如何实现数据管理?
Docker compose是做什么用的?
实验题
1) 编写docker compose 的yaml文件,实现批量创建多个容器
2) 自定义创建容器网络,创建容器选择该网络,并验证网络之间的连通性
3) 实现将本地目录挂载到容器