1.安装
阿里镜像源:http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
官网文档:https://docs.docker.com/
yum install yum-utils -yyum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repoyum install docker-ce -ysystemctl start dockersystemctl enable docker
2.配置镜像服务器
镜像概述:
• 一个分层存储的文件,不是一个单一的文件
• 一个软件的环境
• 一个镜像可以创建N个容器
• 一种标准化的交付
• 一个不包含Linux内核而又精简的Linux操作系统
Docker Hub是由Docker公司负责维护的公共镜像仓库,包含大量的容器镜像,Docker工具默认从这个公共镜像库下载镜像。 地址:https://hub.docker.com
vi /etc/docker/daemon.json{"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]}systemctl restart dockerdocker info | grep -A 1 RegistryRegistry Mirrors:https://b9pmyelo.mirror.aliyuncs.com/
3.docker 镜像管理
3.1镜像相关的命令
[root@server01_10.1.1.1 ~]#docker imageUsage: docker image COMMANDManage imagesCommands:build 构建镜像history 查看镜像的历史export 把容器导出为镜像文件,通常用于备份import 把文件还原为镜像inspect 查看镜像的详细信息load 导入本地镜像ls 列出当前所有的镜像prune 清除有问题的镜像,-a会把所有未关联容器的镜像清除pull 从镜像仓库拉取镜像push 把镜像推送到镜像仓库rm 删除镜像save 导出镜像到本地tag 设置镜像标签:如nginx:latestRun 'docker image COMMAND --help' for more information on a command.导出镜像到本地docker image save tomcat -o tomcat.tardocker image save tomcat > tomcat.tar导入本地镜像docker image load -i tomcat.tardocker image load < tomcat.tar把容器导出为镜像[root@server01_10.1.1.1 ~]#docker container export web > nginx.tar[root@server01_10.1.1.1 ~]#docker import nginx.tar nginx:test[root@server01_10.1.1.1 ~]#docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEnginx test dc7797015fe5 35 seconds ago 131MB
3.2 镜像存储技术
1)镜像存储核心技术:联合文件系统(union FS)
镜像怎么高效存储?难道像虚拟机那样一个容器对应一个独立的镜像文件?这样对于密集
型容器,磁盘占用率太大!
答:引入联合文件系统,将镜像多层文件联合挂载到容器文件系统
2)镜像存储核心技术:写时复制(COW)
了解联合文件系统后,我们知道,镜像是只读的,类似共享形式让多个容器使用,如果要在容器里修改文件,即镜像里的文件,那该怎么办呢?
答:引入写时复制(copy-on-write),需要修改文件操作时,会先从镜像里把要写的文件复制到自己的文件系统中进行修改。
4.docker容器管理
4.1 创建容器常用的命令
[root@server01_10.1.1.1 ~]#docker container run --helpUsage: docker container run [OPTIONS] IMAGE [COMMAND] [ARG...]Run a command in a new containerOptions:-a, --attach list-c, --cpu-shares int--cpus decimal 限制CPU的使用核数--cpuset-cpus string 限制容器使用特定的CPU核心,如(0-3, 0,1)--cpuset-mems string--cpu-shares CPU共享(相对权重)-d, --detach 后台运行-e, --env list 设置环境变量-h, --hostname string 指定容器的主机名-i, --interactive 交互式-l, --label list-m, --memory bytes 容器可以使用的最大内存量--memory-reservation bytes--memory-swap bytes 允许交换到磁盘的内存量--memory-swappiness int 容器使用SWAP分区交换的百分比--mount mount--name string--network network--network-alias list--no-healthcheck--oom-kill-disable--oom-score-adj int--pid string--pids-limit int--platform string--privileged-p, --publish list 把宿主机的端口映射给容器的业务端口-P, --publish-all-t, --tty 分配一个tty终端-u, --user string-v, --volume list-w, --workdir string--name 指定容器的名称--restart=always 容器开机自启启动容器docker run -d -e env=prod -p 88:80 --name=web01 -h web01 --restart=always nginx[root@server01_10.1.1.1 ~]#docker exec -it web01 bashroot@web01:/#限制资源的使用:docker container run -d -p 89:80 --name web02 -h web02 --restart=always-m="500M" --cpus="1" nginx内存限额: 允许容器最多使用500M内存和100M的Swap,并禁用 OOM Killer:docker run -d --name nginx03 --memory="500m" --memory-swap="600m" --oom-kill-disable nginxCPU限额: 允许容器最多使用一个半的CPU:docker run -d --name nginx04 --cpus="1.5" nginx允许容器最多使用50%的CPU:docker run -d --name nginx05 --cpus=".5" nginx
4.2 常用管理命令
[root@server01_10.1.1.1 ~]#docker container --helpUsage: docker container COMMANDManage containersCommands:attachcommitcp 拷贝文件/文件夹到容器creatediffexec 进入启动的容器/免交互执行命令exportinspectkilllogs 查看日志ls 查看当前启动的容器pauseport 查看容器端口映射情况prunerenamerestart 重启容器rm 删除容器runstart 启动容器stats 查看镜像的资源利用率stop 停止容器top 查看容器进程unpauseupdatewaitps-a 查看宿主机上的所有容器-q 列出所有的容器ID[root@server01_10.1.1.1 ~]#docker exec web01 lsbinbootdev[root@server01_10.1.1.1 ~]#docker cp 1.txt web:/[root@server01_10.1.1.1 ~]#docker cp web:/2 ./[root@server01_10.1.1.1 ~]#docker container port web0180/tcp -> 0.0.0.0:8880/tcp -> :::88[root@server01_10.1.1.1 ~]#docker container stats web01非实时性能情况[root@server01_10.1.1.1 ~]#docker container stats web01 --no-streamCONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS49ba8044717e web01 0.00% 2.738MiB / 1.934GiB 0.14% 2.81kB / 1.74kB 7.59MB / 4.1kB 2[root@server01_10.1.1.1 ~]#docker container ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES54168e27def0 nginx "/docker-entrypoint.…" 21 hours ago Up 22 minutes 0.0.0.0:89->80/tcp, :::89->80/tcp web0249ba8044717e nginx "/docker-entrypoint.…" 21 hours ago Up 22 minutes 0.0.0.0:88->80/tcp, :::88->80/tcp web0148bf69c38752 nginx "/docker-entrypoint.…" 21 hours ago Exited (255) 22 minutes ago 80/tcp cranky_jackson649d67251220 nginx "/docker-entrypoint.…" 21 hours ago Exited (255) 22 minutes ago 0.0.0.0:80->80/tcp, :::80->80/tcp nice_khoranafa16290fc52d nginx "/docker-entrypoint.…" 21 hours ago Exited (255) 22 minutes ago 80/tcp busy_brown# 清除未运行的容器[root@server01_10.1.1.1 ~]#docker container pruneWARNING! This will remove all stopped containers.Are you sure you want to continue? [y/N] yDeleted Containers:48bf69c38752868ef219ffa5293fcddbd72a290e81e957c030b1337818443e13649d67251220aa4b2bd657d4401675e8edda9f508e4d4764fc39d0ad51a4265cfa16290fc52d1b09c30dc296b3c30025c2f02de041a732848c25b97166bdc8a5# 清理所有的容器[root@server01_10.1.1.1 ~]#docker container rm -f `docker ps -a -q`
4.3 容器实现的核心技术
在容器化中,一台物理计算机可以运行多个不同操作系统,那就需要解决 “隔离性”,彼此感知不到对方存在,有问题互不影响。
Linux内核从2.4.19版本开始引入了namespace概念,其目的是将特定的全局系统资源通过抽象方法使得namespace中的进程看 起来拥有自己隔离的资源。Docker就是借助这个机制实现了容器资源隔离。
Linux的Namespace机制提供了6种不同命名空间:
• IPC:隔离进程间通信
• MOUNT:隔离文件系统挂载点
• NET:隔离网络协议栈
• PID:隔离进程号,进程命名空间是一个父子结构,子空间对父空间可见
• USER:隔离用户
• UTS:隔离主机名和域名
Docker利用namespace实现了容器之间资源隔离,但是namespace不能对容器资源限制,比如CPU、内存。如果某一个容器属于CPU密集型任务,那么会影响其他容器使用CPU,导致多个容器相互影响并且抢占资源。
如何对多个容器的资源使用进行限制就成了容器化的主要问题。
答:引入Control Groups(简称CGroups),限制容器资源
CGroups: 所有的任务就是运行在系统中的一个进程,而 CGroups 以某种标准将一组进程为目标进行资源分配和控制。
例如CPU、内存、带宽等,并且可以动态配置。
CGroups主要功能:
• 限制进程组使用的资源数量( Resource limitation ):可以为进程组设定资源使用上限,例如内存
• 进程组优先级控制( Prioritization ):可以为进程组分配特定CPU、磁盘IO吞吐量
• 记录进程组使用的资源数量( Accounting ):例如使用记录某个进程组使用的CPU时间
• 进程组控制( Control ):可以将进程组挂起和恢复
ls /sys/fs/cgroup/ -l 查看cgroups可控制的资源:
• blkio :对快设备的IO进行限制。
• cpu:限制CPU时间片的分配,与cpuacct挂载同一目录。
• cpuacct :生成cgroup中的任务占用CPU资源的报告,与cpu挂载同一目录。
• cpuset :给cgroup中的任务分配独立的CPU(多核处理器)和内存节点。
• devices :允许或者拒绝 cgroup 中的任务访问设备。
• freezer :暂停/恢复 cgroup 中的任务。
• hugetlb :限制使用的内存页数量。
• memory :对cgroup 中任务的可用内存进行限制,并自动生成资源占用报告。
• net_cls :使用等级识别符(classid)标记网络数据包,这让 Linux 流量控制程序(tc)可以识别来自特定从cgroup 任务的数据包,并进行网络限制。
• net_prio:允许基于cgroup设置网络流量的优先级。
• perf_event:允许使用perf工具来监控cgroup。
• pids:限制任务的数量。
容器实际资源限制位置: /sys/fs/cgroup/<资源名>/docker/<容器ID>
5.docker核心组件
Docker Daemon:Docker守护进程,负责与Docker Clinet交互,并管理镜像、容器。
Containerd:是一个简单的守护进程,向上给Docker Daemon提供接口,向下通过containerd-shim结合runC管理容器。
runC:一个命令行工具,它根据OCI标准来创建和运行容器。

6.容器数据持久化
Docker提供2种方式将数据从宿主机挂载到容器中:
• volumes:Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)。
• bind mounts:将宿主机上的任意位置的文件或者目录挂载到容器中。
• tempfs:挂载存储在主机系统的内存中,使用少,忽略。
1)bind mounts:
[root@server01_10.1.1.1 ~]#mkdir /opt/web_root[root@server01_10.1.1.1 ~]#docker container run -d -p 80:80 --cpus="0.5" --memory="500M" \--name web -h web01 \-v /opt/web_root/:/usr/share/nginx/html/ --restart=always nginx[root@server01_10.1.1.1 ~]#docker run -d --name web02 -h web02 -p 82:80 --restart=always \--mount type=bind,src=/opt/web_root/,dst=/usr/share/nginx/html/ nginx:latest
注意:文件以宿主机的目录内容为准,宿主机的目录文件会覆盖容器中的目录
2)volumes(最佳实践)
1、创建docker volume create nginx-voldocker volume ls2、数据保存的目录[root@server01_10.1.1.1 ~]#docker volume inspect nginx-vol[{"CreatedAt": "2021-07-01T05:00:22+08:00","Driver": "local","Labels": {},"Mountpoint": "/var/lib/docker/volumes/nginx-vol/_data","Name": "nginx-vol","Options": {},"Scope": "local"}][root@server01_10.1.1.1 ~]#ls /var/lib/docker/volumes/nginx-vol/_data50x.html index.html3、挂载的两种方式:[root@server01_10.1.1.1 ~]#docker container run -d -p 80:80 --cpus="0.5" \--memory="500M" --name web -h web01 \-v nginx-vol:/usr/share/nginx/html --restart=always nginx[root@server01_10.1.1.1 ~]#docker run -d --name web03 -h web03 \--restart=always --cpus=".5" -m="300M" -p 83:80 --oom-kill-disable \--mount src=nginx-vol,dst=/usr/share/nginx/html nginx:latest4、清除数据docker volume rm nginx-vol
7.容器的网络
7.1 四种网络模式
•bridge
–net=bridge 默认网络,Docker启动后创建一个docker0网桥,默认创建的容器也是添加到这个网桥中。 也可以自定义网络,相比默认的具备内部DNS发现,可以通过容器名容器之间网络通信。
• host
–net=host 容器不会获得一个独立的network namespace,而是与宿主机共用一个。这就意味着容器不会有自己的网卡信息,而是使用宿主机的。容器除了网络,其他都是隔离的。
• none
–net=none 获取独立的network namespace,但不为容器进行任何网络配置,需要我们手动配置。
• container
–net=container:Name/ID 与指定的容器使用同一个network namespace,具有同样的网络配置信息,两个容器除了网络,其他都还是隔离的
7.2 网络相关的命令
[root@server01_10.1.1.1 ~]#docker network --helpUsage: docker network COMMANDManage networksCommands:connectcreate 自定义创建网络disconnectinspect 查看指定网络的详细信息lsprunermRun 'docker network COMMAND --help' for more information on a command.默认已经存在的三种网络[root@server01_10.1.1.1 ~]#docker network lsNETWORK ID NAME DRIVER SCOPE6a02669f7636 bridge bridge local6c1929d89476 host host localaf42e22298d6 none null local查看网络模式的详细信息[root@server01_10.1.1.1 ~]#docker network inspect bridge查看桥接到docker0的网卡[root@server01_10.1.1.1 ~]#yum install bridge-utils -y[root@server01_10.1.1.1 ~]#brctl show docker0bridge name bridge id STP enabled interfacesdocker0 8000.0242c35381a1 no veth714e1c8创建网桥(NAT)[root@server01_10.1.1.1 ~]#docker network create teste9d76daaa7e233275cdfe8220645fe88db563c27cbf235d0af430233ec7d0115查看新建网桥(NAT)[root@server01_10.1.1.1 ~]#docker network ls | tail -1e9d76daaa7e2 test bridge local创建容器时指定网络[root@server01_10.1.1.1 ~]#docker run -d -p 90:80 --name web02 --network=test -h web01 nginx:latest84e364a3a81f2c3df951cabacfaac0525da309817d89b68bc2221adc5f81411f查看容器分配的IP地址[root@server01_10.1.1.1 ~]#docker inspect web02 | grep "IPAddress" | tail -1"IPAddress": "172.18.0.2",
默认网桥docker0存在问题:创建两个容器,分别测试ping IP地址和主机名,默认IP地址可通,主机名无法解析。
[root@server01_10.1.1.1 ~]#docker run -it --name bb2 busybox:latest sh/ # ping 172.17.0.3PING 172.17.0.3 (172.17.0.3): 56 data bytes64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.130 ms[root@server01_10.1.1.1 ~]#docker run -it --name bb1 busybox:latest sh/ # ping 172.17.0.2PING 172.17.0.2 (172.17.0.2): 56 data bytes64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.068 ms
解决方案:自定义网桥,也是NAT出来的。
[root@server01_10.1.1.1 ~]#docker run -it --name bb3 --network=test busybox:latest sh/ # ping bb4PING bb4 (172.18.0.3): 56 data bytes64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.051 ms^C--- bb4 ping statistics ---1 packets transmitted, 1 packets received, 0% packet lossround-trip min/avg/max = 0.051/0.051/0.051 ms[root@server01_10.1.1.1 ~]#docker run -it --name bb4 --network=test busybox:latest sh/ # ping bb3PING bb3 (172.18.0.2): 56 data bytes64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.032 ms64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.062 ms
host网络模式:与主机公用一个网络命名空间,根据路由转发数据。
[root@server01_10.1.1.1 ~]#docker run -it --name bb5 --network=host busybox:latest sh/ # ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope hostvalid_lft forever preferred_lft forever2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000link/ether 00:0c:29:d8:50:a4 brd ff:ff:ff:ff:ff:ffinet 10.1.1.1/24 brd 10.1.1.255 scope global noprefixroute eth0valid_lft forever preferred_lft foreverinet6 fe80::cba3:e8f9:8970:8bd9/64 scope link noprefixroutevalid_lft forever preferred_lft forever3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueuelink/ether 02:42:c3:53:81:a1 brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:c3ff:fe53:81a1/64 scope linkvalid_lft forever preferred_lft forever42: br-e9d76daaa7e2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueuelink/ether 02:42:bc:f8:01:da brd ff:ff:ff:ff:ff:ffinet 172.18.0.1/16 brd 172.18.255.255 scope global br-e9d76daaa7e2valid_lft forever preferred_lft foreverinet6 fe80::42:bcff:fef8:1da/64 scope linkvalid_lft forever preferred_lft forever/ # route -nKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface0.0.0.0 10.1.1.254 0.0.0.0 UG 100 0 0 eth010.1.1.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-e9d76daaa7e2可以ping通172.17.0.0/16和172.18.0.0/16中的容器IP地址。
container:即公用一个网络(IP相同)
[root@server01_10.1.1.1 ~]#docker run -it --name bb1 busybox:latest sh/ # ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever61: eth0@if62: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever[root@server01_10.1.1.1 ~]#docker run -it --name=bb2 --net=container:bb1 busybox:latest sh/ # ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever61: eth0@if62: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueuelink/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever
网桥模式的逻辑图:
veth pair:成对出现的一种虚拟网络设备,数据从一端进,从另 一端出。 用于解决网络命名空间之间隔离。
docker0:网桥是一个二层网络设备,通过网桥可以将Linux支持 的不同的端口连接起来,并实现类似交换机那样的多对多的通信。

[root@server01_10.1.1.1 ~]#iptables -t nat -vnL DOCKERChain DOCKER (2 references)pkts bytes target prot opt in out source destination0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/02 104 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:89 to:172.17.0.2:802 104 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:88 to:172.17.0.3:802 104 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.4:80[root@server01_10.1.1.1 ~]# iptables -t nat -vnL POSTROUTINGChain POSTROUTING (policy ACCEPT 2 packets, 104 bytes)pkts bytes target prot opt in out source destination0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/00 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:800 0 MASQUERADE tcp -- * * 172.17.0.3 172.17.0.3 tcp dpt:800 0 MASQUERADE tcp -- * * 172.17.0.4 172.17.0.4 tcp dpt:80
7.3 容器多主机通信
Flannel是CoreOS维护的一个网络组件,在每个主机上运行守护进程负责维护本地路由转发,Flannel使用ETCD来存储容器网络
与主机之前的关系。
其他主流容器跨主机网络方案:
• Weave
• Calico
• OpenvSwitc
1、找一个节点安装etcd并配置
[root@server2 ~]# yum install etcd -y[root@server2 ~]#sed -i 's/localhost/10.1.1.2/g' /etc/etcd/etcd.conf[root@server2 ~]#egrep -v "^#|^$" /etc/etcd/etcd.conf# etcd的数据目录ETCD_DATA_DIR="/var/lib/etcd/default.etcd"# 客户端连接etcd的地址ETCD_LISTEN_CLIENT_URLS="http://10.1.1.2:2379"# etcd节点名称ETCD_NAME="default"# etcd通告地址ETCD_ADVERTISE_CLIENT_URLS="http://10.1.1.2:2379"
2、所有节点安装flanneld
[root@server01_10.1.1.1 ~]#yum install flannel -y[root@server01_10.1.1.1 ~]#sed -i 's/127.0.0.1/10.1.1.2/g' /etc/sysconfig/flanneld[root@server01_10.1.1.1 ~]#egrep -v "^$|^#" /etc/sysconfig/flanneldFLANNEL_ETCD_ENDPOINTS="http://10.1.1.2:2379"FLANNEL_ETCD_PREFIX="/atomic.io/network"
3、向etcd写入子网
[root@server2 ~]#etcdctl --endpoints="http://10.1.1.2:2379" \set /atomic.io/network/config '{ "Network": "172.17.0.0/16", "Backend": {"Type": "vxlan"}} '[root@server2 ~]#etcdctl --endpoints="http://10.1.1.2:2379" \get /atomic.io/network/config '{ "Network": "172.17.0.0/16", "Backend": {"Type": "vxlan"}} '{ "Network": "172.17.0.0/16", "Backend": {"Type": "vxlan"}}
4、配置Docker使用flannel生成的网络信息
# flannel启动后会为docker生成一个默认的配置文件,可在此配置文件中指定子网[root@server2 ~]#cat /var/run/flannel/dockerDOCKER_OPT_BIP="--bip=172.17.50.1/24"DOCKER_OPT_IPMASQ="--ip-masq=true"DOCKER_OPT_MTU="--mtu=1450"DOCKER_NETWORK_OPTIONS=" --bip=172.17.50.1/24 --ip-masq=true --mtu=1450"# 配置docker启动服务,关联flannel网络[root@server2 ~]#vi /usr/lib/systemd/system/docker.serviceEnvironmentFile=/var/run/flannel/dockerExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock $DOCKER_NETWORK_OPTIONS[root@server2 ~]#systemctl daemon-reload[root@server2 ~]#systemctl restart docker[root@server2 ~]#ps -ef | grep dockerroot 18946 1 0 03:11 ? 00:00:00 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=172.17.50.1/24 --ip-masq=true --mtu=1450放通测试访问策略[root@server01_10.1.1.1 ~]#iptables -P FORWARD ACCEPT重启服务[root@server01_10.1.1.1 ~]#systemctl restart flanneld.service[root@server01_10.1.1.1 ~]#systemctl restart docker分别在2台服务器上启动服务,测试。[root@server2 ~]#docker run -it --name web31 busybox/ # ip a/ # ping 172.17.32.2PING 172.17.32.2 (172.17.32.2): 56 data bytes64 bytes from 172.17.32.2: seq=0 ttl=62 time=1.089 m
8. Dockerfile
8.1 Dockerfile常见命令
Docker通过Dockerfile自动构建镜像,Dockerfile 是一个包含用于组建镜像的文本文件,由一条一条 的指令组成。
FROM 构建新镜像是基于哪个镜像
LABEL 标签
RUN 构建镜像时运行的Shell命令
COPY 拷贝文件或目录到镜像中
ADD 解压压缩包并拷贝
ENV 设置环境变量
USER 为RUN、CMD和ENTRYPOINT执行命令指定运行用户
EXPOSE 声明容器运行的服务端口
WORKDIR 为RUN、CMD、ENTRYPOINT、COPY和ADD设置工作目录
CMD 运行容器时默认执行,如果有多个CMD指令,最后一个生效
ENTRYPOINT 如果与CMD一起用,CMD将作为ENTRYPOINT的默认参数,如果如果有多个
ENTRYPOINT指令,最后一个生效
docker build 命令:
Usage: docker build [OPTIONS] PATH | URL | - [flags] Options:-t, 指定镜像名称--tag list 镜像名称 -f, --file string # 指定Dockerfile文件位置-f 指定Dockerfile的文件名
示例1:
[root@server01_10.1.1.1 ~/dockerfile]#cat DockerfileFROM centos:7LABEL nginx testRUN yum install -y wget curlCOPY a /optADD b.tar.gz /optENV ABC=123EXPOSE 80WORKDIR /usr/localCMD ["sleep","3600000"]# 构建[root@server01_10.1.1.1 ~/dockerfile]#docker build -t test:latest .[root@server01_10.1.1.1 ~/dockerfile]#docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEtest latest 44b38f43df8d 21 seconds ago 328MB# 启动容器[root@server01_10.1.1.1 ~/dockerfile]#docker run -d test9959299cffdfd70e29fc77fa82e03f63c3b490c4959aaa3e8ead9eb9a834aa6b[root@server01_10.1.1.1 ~/dockerfile]#docker container lsCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES9959299cffdf test "sleep 3600000" 6 seconds ago Up 5 seconds 80/tcp exciting_villani# 查看拷贝和解压到容器中的文件[root@server01_10.1.1.1 ~/dockerfile]#docker exec -it 9959299cffdf bash[root@9959299cffdf local]# ls /opt/a b[root@9959299cffdf local]# echo $ABC123
CMD用法:
• CMD [“executable”,“param1”,“param2”] :exec形式(首选)
[root@server01_10.1.1.1 ~/dockerfile]#cat run.sh#!/bin/bashecho $1 $2sleep 36000[root@server01_10.1.1.1 ~/dockerfile]#chmod +x run.sh[root@server01_10.1.1.1 ~/dockerfile]#cat DockerfileFROM centos:7LABEL test echo helloCOPY run.sh /usr/bin #需放在可执行的路径下CMD ["run.sh","hello",world][root@server01_10.1.1.1 ~/dockerfile]#docker build -t hello .[root@server01_10.1.1.1 ~/dockerfile]#docker container lsCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESdb400e1dba6b hello "run.sh hello world" 4 seconds ago Up 4 seconds elegant_perlman[root@server01_10.1.1.1 ~/dockerfile]#docker logs db400e1dba6bhello world
[root@server01_10.1.1.1 ~/dockerfile]#cat DockerfileFROM centos:7LABEL test echo helloCOPY run.sh /usr/binENV param1=helloENV param2=worldCMD ["sh","-c","/usr/bin/run.sh $param1 $param2"][root@server01_10.1.1.1 ~/dockerfile]#docker logs hellohello world
在启动容器是可以覆盖Dockerflie中指定的命令:
[root@server01_10.1.1.1 ~/dockerfile]#docker run -d --name h1 hello run.sh hello test03ce3f16bc04a9469fb060f9dfa1bc6cda15850de67578ee0da787c1b221b24f[root@server01_10.1.1.1 ~/dockerfile]#docker logs h1hello test
• CMD [“param1”,“param2”] :作为ENTRYPOINT的默认参数
[root@server01_10.1.1.1 ~/dockerfile]#cat DockerfileFROM centos:7LABEL test echo helloCOPY run.sh /usr/bin/ENV param1=helloENV param2=entrypointENTRYPOINT ["/usr/bin/run.sh"]CMD ["hello","entrypoint_cmd"][root@server01_10.1.1.1 ~/dockerfile]#docker logs t1hello entrypoint_cmd
• CMD command param1 param2 :Shell形式ENTRYPOINT用法:
[root@server01_10.1.1.1 ~/dockerfile]#cat DockerfileFROM centos:7LABEL test echo helloCOPY run.sh /usr/binENV param1=helloENV param2=worldCMD sh /usr/bin/run.sh $param1 $param2[root@server01_10.1.1.1 ~/dockerfile]#docker logs h1hello world
• ENTRYPOINT [“executable”, “param1”, “param2”]
• ENTRYPOINT command param1 param2
[root@server01_10.1.1.1 ~/dockerfile]#cat DockerfileFROM centos:7LABEL test echo helloCOPY run.sh /usr/binENV param1=helloENV param2=entrypointENTRYPOINT ["run.sh","hello","world"][root@server01_10.1.1.1 ~/dockerfile]#docker run -d --name h1 hello47d52bc622119e03f04d6fa8a86198624937ae69319e2187f5d6d10185bef3a7[root@server01_10.1.1.1 ~/dockerfile]#docker logs h1hello world[root@server01_10.1.1.1 ~/dockerfile]#cat DockerfileFROM centos:7LABEL test echo helloCOPY run.sh /usr/binENV param1=helloENV param2=entrypointENTRYPOINT /usr/bin/run.sh $param1 $param2[root@server01_10.1.1.1 ~/dockerfile]#docker run -d --name h1 hello49a725f973b48445ab595079061e255778f0ee5f233ffdfc8df9a6da70cc04a9[root@server01_10.1.1.1 ~/dockerfile]#docker logs h1hello entrypoint# 同样在启用容器的时候覆盖原来的变量[root@server01_10.1.1.1 ~/dockerfile]#docker run -d --name t2 en1 hello t20112273f999503ca4f6bf4eade5869b3eb836bbabf88367e18c7ecf5b179f875[root@server01_10.1.1.1 ~/dockerfile]#docker logs t2hello t2
CMD与ENTRYPOINT区别:
1. CMD和ENTRYPOINT指令都可以用来定义运行容器时所使用的默认命令
2. Dockerfile至少指定一个CMD或ENTRYPOINT
3. CMD可以用作ENTRYPOINT默认参数,或者用作容器的默认命令
4. docker run指定
5. 如果是可执行文件,希望运行时传参,应该使用ENTRYPOIN
示例1:
[root@server01_10.1.1.1 ~/dockerfile]#cat DockerfileFROM centos:7RUN yum install epel-release -y && \yum install nginx -yCMD ["nginx","-g","daemon off;"][root@server01_10.1.1.1 ~/dockerfile]#docker build -t nginx:v1 -f Dockerfile .
示例2:源码安装nginx
FROM centos:7LABEL nginx testRUN yum install -y gcc gcc-c++ make \openssl-devel pcre-devel gd-devel \iproute net-tools telnet wget curl && \yum clean all && \rm -rf /var/cache/yum/*ADD nginx-1.15.5.tar.gz /RUN cd nginx-1.15.5 && \./configure --prefix=/usr/local/nginx \--with-http_ssl_module \--with-http_stub_status_module && \make -j 4 && make install && \mkdir /usr/local/nginx/conf/vhost && \cd / && rm -rf nginx* && \ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtimeENV PATH $PATH:/usr/local/nginx/sbinCOPY nginx.conf /usr/local/nginx/conf/nginx.confWORKDIR /usr/local/nginxEXPOSE 80CMD ["nginx", "-g", "daemon off;"]
示例3:源码安装php
FROM centos:7MAINTAINER php testRUN yum install epel-release -y && \yum install -y gcc gcc-c++ make gd-devel libxml2-devel \libcurl-devel libjpeg-devel libpng-devel openssl-devel \libmcrypt-devel libxslt-devel libtidy-devel autoconf \iproute net-tools telnet wget curl && \yum clean all && \rm -rf /var/cache/yum/*ADD php-5.6.36.tar.gz /RUN cd php-5.6.36 && \./configure --prefix=/usr/local/php \--with-config-file-path=/usr/local/php/etc \--enable-fpm --enable-opcache \--with-mysql --with-mysqli --with-pdo-mysql \--with-openssl --with-zlib --with-curl --with-gd \--with-jpeg-dir --with-png-dir --with-freetype-dir \--enable-mbstring --with-mcrypt --enable-hash && \make -j 4 && make install && \cp php.ini-production /usr/local/php/etc/php.ini && \cp sapi/fpm/php-fpm.conf /usr/local/php/etc/php-fpm.conf && \sed -i "90a \daemonize = no" /usr/local/php/etc/php-fpm.conf && \mkdir /usr/local/php/log && \cd / && rm -rf php* && \ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtimeENV PATH $PATH:/usr/local/php/sbinCOPY php.ini /usr/local/php/etc/COPY php-fpm.conf /usr/local/php/etc/WORKDIR /usr/local/phpEXPOSE 9000CMD ["php-fpm"]
示例4:搭建php项目
1、自定义网络 docker network create lnmp2、创建Mysql容器 docker run -d \ --name lnmp_mysql \ --net lnmp \ --mount src=mysql-vol,dst=/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=wordpress mysql:5.7 --character-set-server=utf83、创建PHP容器 docker run -d --name lnmp_php --net lnmp \ --mount src=wwwroot,dst=/wwwroot php:v14、创建Nginx容器 docker run -d --name lnmp_nginx --net lnmp -p 88:80 --mount src=wwwroot,dst=/wwwroot \ --mount type=bind,src=$PWD/php.conf,dst=/usr/local/nginx/conf/vhost/php.conf nginx:v15、以wordpress博客为例 https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz
示例5:制作tomcat镜像
FROM centos:7 MAINTAINER www.ctnrs.comENV VERSION=8.5.43RUN yum install java-1.8.0-openjdk wget curl unzip iproute net-tools -y && \ yum clean all && \ rm -rf /var/cache/yum/*ADD apache-tomcat-${VERSION}.tar.gz /usr/local/ RUN mv /usr/local/apache-tomcat-${VERSION} /usr/local/tomcat && \ sed -i '1a JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"' /usr/local/tomcat/bin/catalina.sh && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtimeENV PATH $PATH:/usr/local/tomcat/binWORKDIR /usr/local/tomcatEXPOSE 8080CMD ["catalina.sh", "run"]
示例6:制作jar包运行环境
FROM java:8-jdk-alpine LABEL maintainer www.ctnrs.comENV JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF8 -Duser.timezone=GMT+08"RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \ apk add -U tzdata && \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtimeCOPY hello.jar /EXPOSE 8888CMD ["/bin/sh", "-c", "java -jar $JAVA_OPTS /hello.jar"]
制作镜像的最佳实践
• 减少镜像层:一次RUN指令形成新的一层,尽量Shell命令都写在一行,减少镜像层。
• 优化镜像大小:一次RUN形成新的一层,如果没有在同一层删除,无论文件是否最后删除,
都会带到下一层,所以要在每一层清理对应的残留数据,减小镜像大小。
• 减少网络传输时间:例如软件包、mvn仓库等
• 多阶段构建:代码编译、部署在一个Dockerfile完成,只会保留部署阶段产生数据。
• 选择最小的基础镜像:例如alpine
9.镜像仓库harbor
9.1 HTTP部署
Harbor是由VMWare公司开源的容器镜像仓库。事实上,Harbor是在Docker Registry上进行了相应的企业级扩展, 从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于角色的访问控制 ,AD/LDAP集成以及 审计日志等,足以满足基本企业需求。
官方:https://goharbor.io/
Github:https://github.com/goharbor/harbor
1)先安装docker和ocker-compose
安装docker过程略
Composehttps://github.com/docker/compose/releases
[root@server2 ~]#mv docker-compose-Linux-x86_64 /usr/bin/docker-compose[root@server2 ~]#chmod +x /usr/bin/docker-compose
2、部署Harbor HTTP
tar zxvf harbor-offline-installer-v2.0.0.tgz #cd harbor# cp harbor.yml.tmpl harbor.yml# vi harbor.ymlhostname: 10.1.1.2https: # 先注释https相关配置harbor_admin_password: Harbor12345# ./prepare# ./install.sh[root@server2 ~/harbor]#docker-compose psName Command State Ports--------------------------------------------------------------------------------------------------------harbor-core /harbor/entrypoint.sh Up (healthy)harbor-db /docker-entrypoint.sh 96 13 Up (healthy)harbor-jobservice /harbor/entrypoint.sh Up (healthy)harbor-log /bin/sh -c /usr/local/bin/ ... Up (healthy) 127.0.0.1:1514->10514/tcpharbor-portal nginx -g daemon off; Up (healthy)nginx nginx -g daemon off; Up (healthy) 0.0.0.0:80->8080/tcp,:::80->8080/tcpredis redis-server /etc/redis.conf Up (healthy)registry /home/harbor/entrypoint.sh Up (healthy)registryctl /home/harbor/start.sh Up (healthy)如关机后未启动:[root@server2 ~/harbor]#docker-compose up -d
3)推送镜像
vi /etc/docker/daemon.json{"insecure-registries":["10.1.1.2"]}[root@server01_10.1.1.1 ~]#cat /etc/docker/daemon.json{"insecure-registries":["10.1.1.2"],"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]}# systemctl restart docker2、打标签[root@server01_10.1.1.1 ~]#docker tag nginx:latest 10.1.1.2/library/nginx:latest[root@server01_10.1.1.1 ~]#docker image lsREPOSITORY TAG IMAGE ID CREATED SIZEnginx v1 aadf62fab555 22 hours ago 400MBtomcat latest b0bf9a4a7c93 5 days ago 667MB10.1.1.2/library/nginx latest 4f380adfc10f 8 days ago 133MB3、登录镜像仓库[root@server01_10.1.1.1 ~]#docker login 10.1.1.2Username: adminPassword:WARNING! Your password will be stored unencrypted in /root/.docker/config.json.Configure a credential helper to remove this warning. Seehttps://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded3、上传[root@server01_10.1.1.1 ~]#docker push 10.1.1.2/library/nginx:latestThe push refers to repository [10.1.1.2/library/nginx]c6d74dcb7fe7: Pushedb50a193ebf2e: Pushed165eb6c3c0d3: Pushedcf388fcf3527: Pushed2418679ca01f: Pushed764055ebc9a7: Pushedlatest: digest: sha256:2f1cd90e00fe2c991e18272bb35d6a8258eeb27785d121aa4cc1ae4235167cfd size: 15704、下载[root@server01_10.1.1.1 ~]#docker pull 10.1.1.2/library/nginx:latestlatest: Pulling from library/nginxDigest: sha256:2f1cd90e00fe2c991e18272bb35d6a8258eeb27785d121aa4cc1ae4235167cfdStatus: Downloaded newer image for 10.1.1.2/library/nginx:latest10.1.1.2/library/nginx:latest
9.2 HTTPS部署
1)生成证书
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64chmod +x cfssl*mv cfssl_linux-amd64 /usr/bin/cfsslmv cfssljson_linux-amd64 /usr/bin/cfssljsonmv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo[root@server2 /usr/local/ssl]#cat certs.shcat > ca-config.json <<EOF{"signing": {"default": {"expiry": "87600h"},"profiles": {"kubernetes": {"expiry": "87600h","usages": ["signing","key encipherment","server auth","client auth"]}}}}EOFcat > ca-csr.json <<EOF{"CN": "kubernetes","key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "Beijing","ST": "Beijing"}]}EOFcfssl gencert -initca ca-csr.json | cfssljson -bare ca -cat > cwd.harbor.com-csr.json <<EOF{"CN": "cwd.harbor.com","hosts": [],"key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","L": "BeiJing","ST": "BeiJing"}]}EOFcfssl gencert -ca=ca.pem -ca-key=ca-key.pem \-config=ca-config.json -profile=kubernetes cwd.harbor.com-csr.json | cfssljson -bare cwd.harbor.com[root@server2 /usr/local/harbor]#cat harbor.ymlhttp:# port for http, default is 80. If https enabled, this port will redirect to https portport: 80# https related confighttps:# https port for harbor, default is 443port: 443# The path of cert and key files for nginxcertificate: /usr/local/ssl/cwd.harbor.com.pemprivate_key: /usr/local/ssl/cwd.harbor.com-key.pem
对于windows主机,直接信任该证书即可登录。但是docker客户端并非通过网页登录,该如何添加信任?
# docker 主机默认读取证书所在的目录[root@server01_10.1.1.1 ~]#mkdir -p /etc/docker/certs.d/cwd.harbor.com# 把证书拷贝到该目录下[root@server2 /usr/local/ssl]#scp cwd.harbor.com.pem root@10.1.1.1:/etc/docker/certs.d/cwd.harbor.com# 重命名该证书[root@server01_10.1.1.1 /etc/docker/certs.d/cwd.harbor.com]#mv cwd.harbor.com.pem{,.crt}# 配置hosts[root@server01_10.1.1.1 ~]#tail -1 /etc/hosts10.1.1.2 cwd.harbor.com# 登录[root@server01_10.1.1.1 ~]#docker login cwd.harbor.comUsername: adminPassword:WARNING! Your password will be stored unencrypted in /root/.docker/config.json.Configure a credential helper to remove this warning. Seehttps://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded
9.3 Harbor高可用方案

10.Docker图形化管理工具Portainer
1)安装
docker run -d \-p 8000:8000 \-p 9000:9000 \--name=portainer \--restart=always \-v /var/run/docker.sock:/var/run/docker.sock \-v portainer_data:/data \portainer/portainer
2)登录
http://10.1.1.1:9000/#/init/admin
3)管理其他主机上的容器
管理其他Docker主机,需要开启Docker API:
# vi /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
# systemctl restart docke

11.Docker-compose
12.Docker监控
cAdvisor (Container Advisor) :用于收集正在运行的容器资源使用和性能信息。 https://github.com/google/cadvisor
Prometheus(普罗米修斯):容器监控系统。
https://prometheus.io
https://github.com/prometheus
Grafana:是一个开源的度量分析和可视化系统。
https://grafana.com/grafana
docker 部署cAdvisor
docker run -d --volume=/:/rootfs:ro --volume=/var/run:/var/run:ro --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --volume=/dev/disk/:/dev/disk:ro --publish=8080:8080 --detach=true --name=cadvisor google/cadvisor:latest
Docker部署Prometheus
docker run -d -v /etc/localtime:/etc/localtime --name=prometheus -p 9090:9090 prom/prometheus
在Prometheus中添加cAdvisor节点
[root@server01_10.1.1.1 ~]#docker exec -it prometheus sh/prometheus $ vi /etc/prometheus/prometheus.ymlscrape_configs:- job_name: 'docker'static_configs:- targets: ['10.1.1.1:8080']# 重启容器生效[root@server01_10.1.1.1 ~]#docker restart prometheus
查看添加的节点信息
Docker部署Grafana
docker run -d --name=grafana -p 3000:3000 grafana/grafana
打开浏览器登录:http://10.1.1.1:3000/login
默认账号密码均为:admin
添加数据源:


导入仪表盘
输入仪表盘编号
导入
添加监控多个docker主机:


保存后仪表盘出现docker主机的选择框,此时需要更改监控项中的查询项:
