[TOC]
0x01 Docker 数据管理 Data Management,在使用Docker时候必然会在容器内产生数据,或者需要将容器内的数据进行备份,甚至多个容器之间进行数据共享,这时数据管理变得尤为重要;
weiyigeek.top-数据管理
容器中管理数据的主要有两种方式:
数据卷:Data Volumns
数据卷容器:Data Volume Dontainers
数据管理共享的方式:
使用数据卷容器在容器和主机
容器和容器之间共享数据
1.数据卷 描述:是一个可供容器使用的数据目录,并且让文件系统提供很多有用的特性,数据卷的使用类似于Linux对目录或者文件进行mount操作;
数据卷特性:
数据库可以在容器之间共享和重用
数据卷修改后会立马生效
对数据卷的更新不会影响镜像
卷会一直存在,即使容器被删除
Q:如何在容器内创建一个数据卷? 1 2 3 4 5 6 7 8 9 10 $ sudo docker run -d -P 5000 --name web(新建容器) -v /webapp(容器目录) training/webapp(镜像) python app.py $docker cp 容器id或者name:/home/wwwroot/1.php /home/Lcy/ $docker cp config.php 容器id或者name:/home/wwwroot/
Q:如何挂载主机目录/文件作为数据卷? 1 2 3 4 5 6 7 $ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp:rw training/webapp python app.py $ sudo docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash
2.数据卷容器 描述:IF用户需要在容器之间共享一些持续的数据,最简单的方式就是使用数据卷容器(实际上就是一个普通容器); 使用数据卷容器可以让用户在容器之间自由地升级和移动数据卷;
Q: 如何创建一个数据卷容器? 首先创建一个数据卷容器dbdata并在其中创建一个数据卷挂载到/dbdata上;1 2 3 4 5 6 7 8 9 10 11 $ sudo docker run -it -v /dbdate --name dbdate ubuntu $ sudo docker run -it --volumes-from dbdate --name db1 ubuntu $ sudo docker run -it --volumes-from dbdate --name db2 ubuntu $ sudo docker run -d --name db2 --volumes-from db1 tarining/postgresql
Q: 如何删除容器及其数据卷? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $docker run --name web --rm -dit -v /opt:/opt/ centos /bin/bash5b3d35fe3305fb458e8b33f39d5fedfbd7d9cb1f6742bcf725cfbf2ecd0245fc $docker start -i 5b3[root@5b3d35fe3305 opt]$ echo 'docker' > containerDokcer.txt [root@zabbix opt]$ cat containerDokcer.txt docker $docker run --rm -it -v ~/.bash_history:/root/.bash_history centos /bin/bash$docker rm -vf web $docker ps -a
Q: 数据卷容器如何迁移数据? 描述: 可以利用数据卷容器对其中的数据卷进行备份、恢复以实现数据的迁移;1 2 3 4 5 6 7 $ sudo docker run --volumes-from dbdata -v $(pwd ):/backup --name worker ubuntu tar cvf /backup/backup.tar /dbdate $ sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash $ sudo docker run --volumes-from dbdata2 $(pwd ):/backup busybox tar xvf /backup/backup.tar
实践案例:
示例1.创建一个只有读取权限的数据卷到容器内部,此处利用–mount参数进行设置,实现启动一个挂载数据卷的容器,进行容器之间的资源共享;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 $docker volume create myvol $docker volume lslocal myvol$docker run -d -P \ --name web \ --mount source =my-vol,target=/webapp \ --mount type =bind ,source =$HOME /.bash_history,target=/root/.bash_history,readonly \ training/webapp \ sh $docker run -it --name web2 -v myvol:/webapp centos sh $sh -4.2asdasdasdasda: "Mounts" : [ { "Type" : "volume" , "Name" : "myvol" , "Source" : "/var/lib/docker/volumes/myvol/_data" , "Destination" : "/webapp" , "Driver" : "local" , "Mode" : "z" , "RW" : true , "Propagation" : "" } ], docker volume rm `docker volume ls -q`
示例2.利用数据卷容器来备份、恢复、迁移数据卷。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ sudo docker run --volumes-from dbdata -v $(pwd ):/backup ubuntu -C "tar cvf /backup/backup.tar /dbdata" / backup dbdata sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash $ sudo docker run --volumes-from dbdata2 -v $(pwd ):/backup busybox tar xvf /backup/backup.tar -rw-r--r-- 1 root root 5120 5月 24 15:02 dbdata.tar $ sudo docker run --volumes-from dbdata2 busybox /bin/ls /dbdata
补充说明: -v 参数指定数据持久化目录后添加的:Z
与:z
的区别 1 2 3 4 5 docker run -d --restart=always --name app -v /disk/webapp/war/:/usr/local /tomcat/webapps:z -p 4081:8080 -e JAVA_OPTS=-Dsome.property=value -e Xmx=1536m tomcat-base:6.0.85-jre8
总结说明:
推荐直接挂载文件目录到容器中,如果直接挂载一个文件到容器中在使用文本编辑工具时候可能会报错;
可以多次使用–volumes-from参数从来多个容器挂载多个数据卷;锁挂载的容器自身并不需要保持在运行状态
推荐使用数据卷和数据容器之外的物理备份存储系统,如RAID或者分布式系统如Ceph,GPFS,HDFS等
0x02 Docker 网络管理 描述: 大量互联网服务包括多个服务组件往往需要多个容器之间进行网络通信相互配合,Docker目前提供了映射容器端口与宿主主机和容器互联机制来为容器提网络服务;并且采用Linux系统知道的网络系统来实现对网络服务的支持使之能提供稳定支持以及快速的高性能转发;
1.容器网络原理 描述: 当 Docker 启动时会自动在主机上创建一个 docker0 虚拟网桥,实际上它是 Linux 的一个 bridge (网桥),可以理解为一个软件交换机,它会在挂载到它的网口之间进行转发。 同时,Docker 随机分配一个本地未占用的私有网段(在 RFC1918 中定义)中的一个地址给 docker0 接口
比如典型的 172.17.42.1,掩码为 255.255.0.0
Docker 就创建了在主机和所有容器之间一个虚拟共享网络 当创建一个 Docker 容器的时候,同时会创建了一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包), 这对接口
一端在容器内即 eth0;
另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT)
通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。
weiyigeek.top-Docker网络
例如, 当在一台未经过特殊网络配置的centos 或 ubuntu机器上安装完docker之后, 在宿主机上通过ifconfig命令可以看到多了一块名为docker0的网卡;不难想到docker0就不只是一个简单的网卡设备了而是一个网桥。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 $ifconfig docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255 $route -n172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0 $yum install bridge-utils$brctl showbridge name bridge id STP enabled interfaces br-63791a62ad5a 8000.024258a66d6e no veth4ce6e0e vethe5abf0f br-6cde78afe495 8000.02420a2496c6 no veth93e8dc0 vethfda7b14 docker0 8000.024216e63d3c no brctl addbr br0 ifconfig br0 18.18.0.1 echo 1 > /proc/sys/net/ipv4/ip_forward
weiyigeek.top-bridge模式图
在Docker在1.9版本中network子命令和跨主机网络支持,为了标准化网络的驱动开发步骤和支持多种网络驱动,Docker公司在libnetwork中使用了CNM(Container Network Model)定义了构建容器虚拟化网络的模型。libnetwork和Docker daemon及各个网络驱动的关系图: Docker daemon通过调用libnetwork对外提供的API完成网络的创建和管理等功能,libnetwrok中则使用了CNM来完成网络功能的提供;
weiyigeek.top-
CNM中主要有沙盒(sandbox)、端点(endpoint)、网络(network)3种组件:
(1)Sandbox:包含了一个容器网络栈的信息,实现对容器的接口、路由和DNS设置等进行管理;
(2)Endpoint:它可以加入一个沙盒和一个网络,且一个端点只可以属于一个网络并且只属于一个沙盒;
(3)Network:可以直接互相联通的端点(包含多个端点),网络的实现可以是Linux bridge、VLAN等
libnetwork共有5种内置驱动:bridge驱动、host驱动、overlay驱动、remote驱动、null驱动。
(1)bridge驱动: Docker默认设置驱动,它可以将创建出来的Docker容器连接到Docker网桥常规方法能满足容器基础需求,然后在复杂场景下使用又诸多限制(使用NAT转发)
(2)host驱动:它将不为Docker容器创建网络协议栈(不会创建独立的network namespace),即容器于宿主机共用一个network namespace并使用宿主机的网卡/IP端口等等信息,该驱动适用于对于容器集群规模不大的场景;
(3)overlay驱动: 采用IETE标准的VXLAN方式,并且是VXLAN中被普遍认为最适合大规模的云计算虚拟化环境的SDN controller模式,使用时候需要额外的配置存储服务(例如Consul、etcd和zookeeper)
(4)remote驱动: 该驱动并未做真正的网络服务实现而是调用了用户自行实现的网络驱动插件,使libnetwork实现了驱动的可插件化,更好地满足了用户的多种需求
(5)null驱动: 容器拥有自己的网络命名空间,但并不为Docker容器进行任何网络配置;容器除了network namespace自带的loopback网卡名,没有其他任何网卡、IP、路由等信息(需要用户对齐配置)
2.容器网络实践 (1)端口映射实现访问容器 通过-P或者-p来指定端口,
使用-P时候:会进行选择 49000 ~ 49900 端口随机分配映射;
使用-p时候:会让你您设置固定与容器映射的端口;
支持的格式:
hostPort:containerPort < 映射到本地指定端口以及容器端口
ip:hostPort:containerPort < 映射到本地指定地址以及本地指定端口和容器端口
ip::containerPort < 映射本地指定IP的任意端口和容器端口 (注意此处是::)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 $sudo docker run -d -P centos python app.py $docker ps -l $sudo docker logs -f [NAMES] $sudo docker run -d -p 5000:5000 centos python app.py $sudo docker run -d -p 127.0.0.1:5000:5000 centos python app.py $sudo docker run -d -p 127.0.0.1::5000/tcp centos python app.py $sudo docker port [NAMES] 5000
(2)实现容器间通信 容器的链接(Linking)系统是除了端口映射外的另一种可以与容器中应用进行交换的方式;它会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息;
Docker两种方式为容器公开连接信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 $sudo docker run -d --name db tranining/postgres$ sudo docker run -d -P --name web --link db:db training/webapp python app.py $ docker ps CONTAINER ID IMAGE COMMAND CREATED STAT US PORTS NAMES 349169744e49 training/postgres:latest su postgres -c '/usr About a minute ago Up About a minute 5432/tcp db, web/db' $sudo docker run --rm --name web1 --link db:db training/webapp envDB_NAME=/web2/db DB_PORT=tcp://172.17.0.5:5432 DB_PORT_5000_TCP=tcp://172.17.0.5:5432 DB_PORT_5000_TCP_PROTO=tcp DB_PORT_5000_TCP_PORT=5432 DB_PORT_5000_TCP_ADDR=172.17.0.5 $sudo docker run -it --rm --link db:db training/webapp /bin/bashcat /etc/hosts
实例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 $docker pull nginx$docker run -d -p 80:80 --name web nginx$docker container ls -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 16207d8f2291 nginx "nginx -g 'daemon of…" 19 seconds ago Up 18 seconds 0.0.0.0:80->80/tcp web $docker inspect web"Gateway" : "172.18.0.1" ,"IPAddress" : "172.18.0.2" ,"MacAddress" : "02:42:ac:12:00:02" ,$docker logs -f web218.x.x.xx - - [08/May/2019:15:00:11 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0" "-" [root@izwz9biz2m4sd3bb3k38pgz ~]$docker run -d --name web1 --link web:nginx_web alpine cat /etc/hosts ebe1df8c1fb00462b127d36201d558a9f62507c81faea1ce6c4bf4b5ea6075e3 [root@izwz9biz2m4sd3bb3k38pgz ~]$docker run -d --name web2 --link web:nginx_web alpine env baa9dfe5f64519eb5ccbd122fc191e0f40118a4ee28385a818f7ffe6e2e03639 [root@izwz9biz2m4sd3bb3k38pgz ~]$docker start -i web1 172.18.0.2 nginx_web 16207d8f2291 web 172.18.0.3 ebe1df8c1fb0 [root@izwz9biz2m4sd3bb3k38pgz ~]$docker start -i web2 PATH=/usr/local /sbin:/usr/local /bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=baa9dfe5f645 NGINX_WEB_PORT=tcp://172.18.0.2:80 NGINX_WEB_PORT_80_TCP=tcp://172.18.0.2:80 NGINX_WEB_PORT_80_TCP_ADDR=172.18.0.2 NGINX_WEB_PORT_80_TCP_PORT=80 NGINX_WEB_PORT_80_TCP_PROTO=tcp NGINX_WEB_NAME=/web2/nginx_web NGINX_WEB_ENV_NGINX_VERSION=1.15.12-1~stretch NGINX_WEB_ENV_NJS_VERSION=1.15.12.0.3.1-1~stretch
weiyigeek.top-访问容器映射出网站
(3)libnetwork库官方示例
libnetwork官方示例图:
weiyigeek.top-libnetwork
执行流程:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 $docker network lsNETWORK ID NAME DRIVER SCOPE f26c3ed5f7b0 bridge bridge local fd3572aceb38 host host local 01da6464c812 none null local $docker network create backend6cde78afe495a310bb27c5e1a50074b20e204bfa72e71bcaf6a4c37feb300b93 $docker network create frontend63791a62ad5a5fe4aeb5926616b2ea1d65b490bb9fb718824b7cb1c408ae50c1 $docker network create -d bridge test -net$docker run -itd --name c1 --net backend alpine729f2abef71ceaf831999d66264d05f78674d9cd2c235f84481a14b366698adb $docker run -itd --name c2 --net backend alpine26d47af2d39a1b00f767c60a68cd5f61f1cf5f48652cdcbcb0216968a3185f5e $docker run -itd --name c3 --net frontend alpine9cb94f7c66955ba5a95c90d08ce314da0e477f6eddbcea0329309ec36ca5a711 C1: 172.19.0.2 C2: 172.19.0.3 C3: "IPAddress" : "172.20.0.2" , 18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0 PING c2 (172.19.0.3): 56 data bytes 64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.065 ms 64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.050 ms / PING 172.20.0.2 (172.20.0.2): 56 data bytes $docker network connect frontend c2$docker exec -it c2 sh/ $ ip addr 20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:13:00:03 brd ff:ff:ff:ff:ff:ff inet 172.19.0.3/16 brd 172.19.255.255 scope global eth0 24: eth1@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:14:00:03 brd ff:ff:ff:ff:ff:ff inet 172.20.0.3/16 brd 172.20.255.255 scope global eth1 / $ ping c3 PING c3 (172.20.0.2): 56 data bytes 64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.100 ms
(4) 跨主机实现互通 描述: 此外我们还可以通过通过添加路由route的方式进行跨主机实现互通,但是通常情况下我们不会如此操作,只在特殊环境中使用测试。
比如:1 Docker1: 172.18.0.1/24 --Gateways-- 192.168.1.99
总结说明:
用户可以链接多个子容器到父容器中比如连接多个web到db容器上;
学习额外的机制比如SDN(软件定义网络)或者NFV(网络功能虚拟化)的相关技术
3.高级网络配置 描述: 容器互联 随着 Docker 网络的完善,强烈建议大家将容器加入自定义的 Docker 网络来连接多个容器,而不是使用 –link 参数
如何自定义配置容器的主机名和 DNS 呢? 答:Docker 会默认用主机上的 /etc/resolv.conf 来配置容器, 所以可以直接在宿主机上的resolv.conf文件中进行更改,也可以在/etc/docker/daemon.json 文件中增加DNS键值对是一个数组;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 docker network create -d bridge my-net $docker run -it --rm --name busybox1 --network my-net busybox sh$docker run -it --rm --name busybox1 --network my-net busybox sh/dev/mapper/cl-root on /etc/resolv.conf type xfs (rw,relatime,attr2,inode64,noquota) /dev/mapper/cl-root on /etc/hostname type xfs (rw,relatime,attr2,inode64,noquota) /dev/mapper/cl-root on /etc/hosts type xfs (rw,relatime,attr2,inode64,noquota) $docker start -i 81fash-4.2 nameserver 192.168.10.254 nameserver 61.128.128.68 nameserver 114.114.114.114
容器访问控制 容器的访问控制,主要通过 Linux 上的 iptables 防火墙来进行管理和实现. 容器访问外部网络,需要本地系统的转发支持。在Linux 系统中,检查转发是否打开。1 2 3 4 5 $sysctl net.ipv4.ip_forwardnet.ipv4.ip_forward = 1 $sysctl -w net.ipv4.ip_forward=1
容器之间访问需要两方面的支持:
容器的网络拓扑是否已经互联。默认情况下,所有容器都会被连接到 docker0 网桥上。
本地系统的防火墙软件 – iptables 是否允许通过。 动容器(docker run)时使用 –link=CONTAINER_NAME:ALIAS 选项,就会在宿主机上添加了 iptables 规则。1 2 3 4 5 6 $ sudo iptables -nL Chain FORWARD (policy ACCEPT) target prot opt source destination ACCEPT tcp -- 172.17.0.2 172.17.0.3 tcp spt:80 ACCEPT tcp -- 172.17.0.3 172.17.0.2 tcp dpt:80 DROP all -- 0.0.0.0/0 0.0.0.0/0
默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。
容器访问外部实现:容器所有到外部网络的连接,源地址都会被 NAT 成本地系统的 IP 地址
外部访问容器实现:可以在 docker run 时候通过 -p 或 -P 参数来启用。
不管用那种办法,其实也是在本地的 iptable 的 nat 表中添加相应的规则1 2 3 4 5 6 7 8 9 10 11 12 $sudo iptables -t nat -nLChain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.17.0.0/16 !172.17.0.0/16 chain DOCKER (2 references) target prot opt source destination DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
docker 网桥 Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。 Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了 MTU(接口允许接收的最大传输单元),通常是 1500 Bytes,或宿主主机网络路由上支持的默认值,值都可以在服务启动的时候进行配置。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $brctl showbridge name bridge id STP enabled interfaces docker0 8000.0242f0960e9f no veth4fe5b74 $ sudo docker run -i -t --rm base /bin/bash $ip addr show eth0$ip routedefault via 172.17.42.1 dev eth0 172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.3 1. 如果服务已经运行,那需要先停止服务,并删除旧的网桥。 $ sudo systemctl stop docker $ sudo ip link set dev docker0 down $ sudo brctl delbr docker0 $ sudo brctl addbr bridge0 $ sudo ip addr add 192.168.5.1/24 dev bridge0 $ sudo ip link set dev bridge0 up
注:brctl 命令在 Debian、Ubuntu /Centsos采用相同的包中可以使用 sudo apt-get install bridge-utils 来安装。
实践案例: 创建一个点到点连接,点到点链路不需要子网和子网掩码。 默认情况下,Docker 会将所有容器连接到由 docker0 提供的虚拟子网中,用户有时候需要两个容器之间可以直连通信,而不用通过主机网桥进行桥接。 解决办法很简单:创建一对 peer 接口,分别放到两个容器中,配置成点到点链路类型即可1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 $docker run -it --rm --net=none --name demo1 alpine sh39ca23ce4417 $docker run -it --rm --net=none --name demo2 alpine shd4b1311349c1 $docker inspect -f '{{.State.Pid}}' d4b6742 $docker inspect -f '{{.State.Pid}}' 39c6807 sudo mkdir -p /var/run/netns sudo ln -s /proc/6742/ns/net /var/run/netns/6742 sudo ln -s /proc/6807/ns/net /var/run/netns/6807 $ sudo ip link add A type veth peer name B $ sudo ip link set A netns 6742 $ sudo ip netns exec 6742 ip addr add 10.1.1.1/32 dev A $ sudo ip netns exec 6742 ip link set A up $ sudo ip netns exec 6742 ip route add 10.1.1.2/32 dev A $ sudo ip link set B netns 6807 $ sudo ip netns exec 6807 ip addr add 10.1.1.2/32 dev B $ sudo ip netns exec 6807 ip link set B up $ sudo ip netns exec 6807 ip route add 10.1.1.1/32 dev B 容器$ ip addr
weiyigeek.top-点到点通信
0x03 Registry 私有镜像仓库搭建实践 1.前言简述 描述: 镜像仓库主要是用来存储和分发镜像的,并对外提供一套 HTTP API V2。镜像仓库中的所有镜像,都是以数据块 (Blob) 的方式存储在文件系统中。 支持多种文件系统,主要包括filesystem,S3,Swift,OSS等。
docker 的 registry 项目参考地址:https://docs.docker.com/registry/
产生原因: Docker hub是公开的其他人也是可以下载并不安全因此还可以使用docker registry官方提供的私有仓库;但是我们默认在机器上搭建的registry私有仓库是不需要验证的,因此我们需要进行安全配置仓库并加入认证;
Docker Registry由三个部分组成:
index: 负责登录、负责认证、负责存储镜像信息和负责对外显示的外部实现.
registry: 负责存储镜像的内部实现.
registry client: 则是docker 客户端.
2.搭建使用 描述: registry 私有镜像仓库搭建流程如下所示。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 docker pull registry:2 mkdir -vp /opt/data/auth mkdir -vp /opt/data/registry docker run --entrypoint htpasswd httpd:2 -Bbn testuser testpassword > auth/htpasswd docker run -d -p 5000:5000 --name registry -v /opt/data/registry:/var/lib/registry registry:2 docker run -d -p 5000:5000 --restart=always --name docker-hub \ -v /opt/data/registry:/var/lib/registry \ -v /opt/data/auth:/auth \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \ registry tee /etc/docker/daemon.json <<EOF { "registry-mirror" : [ "https://registry.docker-cn.com" ], "insecure-registries" : [ "10.10.107.221:5000" ] } EOF vim /lib/systemd/system/docker.service [Service] EnvironmentFile=-/etc/docker/daemon.json systemctl daemon-reload systemctl restart docker docker run -d -p 5000:5000 --name docker-registry -v /opt/data/registry:/var/lib/registry registry $docker commit -m "alpine-sh" -a "weiyigeek" a63 10.10.107.221:5000/alpine-shsha256:b75ef26a9e1d92924914edcb841de8b7bdc0b336cea2c6cfbaaf6175e24472c6 $docker login 10.10.107.221:5000Username: testuser Password: WARNING! Your password will be stored unencrypted in /root/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/ Login Succeeded $docker push 10.10.107.221:5000/alpine-shThe push refers to repository [10.10.107.221:5000/alpine-sh] 2a499f806f16: Pushed f1b5933fe4b5: Pushed latest: digest: sha256:6d13420cb9ce74095e2a71f565fc8c15ba17b40933e14534fc65775025eedd18 size: 735 docker pull 10.10.107.221:5000/weiyige curl -XGET http://10.10.107.221:5000/v2/_catalog -u testuser:testpassword {"repositories" :["alpine-sh" ]}
weiyigeek.top-docker仓库
可以从下图看到设置账号密码认证后直接访问Registry API将受到限制
weiyigeek.top-regsitryLoginAuth
3.补充说明 (1) 对Registry镜像仓库与Harbor仓库特征说明 描述: 通过 Registry API
获得的两个镜像仓库中相同镜像的 manifest 信息的存储路径和内容完全相同
, 并且两个镜像仓库中相同镜像的 blob 信息的存储路径和内容完全相同
。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /var/lib/registry /data/harbor/registry/docker/registry/v2 $ cat repositories/release/cyclone-server/_manifests/tags/v0.5.0-beta.1/current/link sha256:6d47a9873783f7bf23773f0cf60c67cef295d451f56b8b79fe3a1ea217a4bf98 $ cat blobs/sha256/6d/6d47a9873783f7bf23773f0cf60c67cef295d451f56b8b79fe3a1ea217a4bf98/data $ du -s blobs/sha256/71/7118e0a5b59500ceeb4c9686c952cae5e8bfe3e64e5afaf956c7098854a2390e/data 7560 blobs/sha256/71/7118e0a5b59500ceeb4c9686c952cae5e8bfe3e64e5afaf956c7098854a2390e/data
(2) 为Registry私有镜像仓库配置auth认证与tls证书 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 docker run -d \ -p 443:443 \ --restart=always \ --name registry \ -v /app/registry/data:/var/lib/registry \ -v /app/registry/auth:/auth \ -v /app/registry/cert:/cert \ -e "REGISTRY_HTTP_ADDR=0.0.0.0:443" \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \ -e "REGISTRY_HTTP_TLS_CERTIFICATE=/cert/hub.weiyigeek.top.crt" \ -e "REGISTRY_HTTP_TLS_KEY=/cert/server.key" \ registry:2 $ docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}" CONTAINER ID NAMES PORTS c8657bd20936 registry 0.0.0.0:443->443/tcp, 5000/tcp
(3) 登陆远程仓库时报证书签名错误及其解决办法 1 2 3 4 5 6 7 8 9 10 11 12 13 ~$ docker login hub.weiyigeek.top Login did not succeed, error: Error response from daemon: Get https://hub.weiyigeek.top/v2/: x509: certificate signed by unknown authority Username: WeiyiGeek Password: ******** "insecure-registries" : ["192.168.12.111:5000" ,"hub.weiyigeek.top" ]mkdir -vp /etc/docker/certs.d/hub.weiyigeek.top cp -a /deployapp/harbor/harbor.pem /etc/docker/certs.d/hub.weiyigeek.top/harbor.crt
0x03 Docker-Compose 容器编排 描述:Docker Compose 是使用 Python 开发的一款基于 Docker 容器进行编排的工具,定义和运行多容器的应用可以一条命令启动多个容器, 从提到的Docker-Machine种可以将用户在其他平台快速安装Docker,而Swarm可以让Docker容器在集群种高效运转,而Compose则可以让用户在集群中部署分布式应用。
从功能上看跟 OpenStack 中的 Heat 十分类似,Compose 定位是 「定义和运行多个 Docker 容器的应用(Defining and running multi-container Docker applications)」,其前身是开源项目 Fig。 简单的说: Docker Compose 属于一个应用层的服务,用户可以定义哪一个容器组运行那些应用,它支持动态改变应用并在需要时扩展;
产生原因:由于单纯的使用Dockerfile只能设置一个Docker镜像且采用多阶段构建的时候entrypoint指令只能存在一个,为了解决这个问题引入了Docker Compose机制;它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project),免去我们需要多次执行docker run命令的烦恼;
其代码目前在:https://github.com/docker/compose
Docker Compose 优点:
安装与使用非常简单的
能够帮我们处理容器的依赖关系,在每个容器中会将容器的 IP 和服务的名称使用 hosts 的方式绑定,这样我们就能在容器中直接使用服务名称来接入对应的容器了
使用 docker-compose.yaml 配置的形式将你需要启动的容器管理起来。
使用Compose 基本上分为三步:
Dockerfile 定义应用的运行环境
docker-compose.yml 定义组成应用的各服务
docker-compose up 启动整个应用
Compose 中有两个重要的概念:
服务 (service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
项目 (project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。
应用场景:最常见的项目是 web 网站,该项目应该包含 web 应用和缓存。
一个简单的docker-compose.yml配置文件:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 version: "2" services: nginx: depends_on: - "php" image: "nginx:latest" volumes: - "$PWD /src/docker/conf:/etc/nginx/conf.d" - "$PWD :/home/q/system/m_look_360_cn" ports: - "8082:80" container_name: "m.look.360.cn-nginx" php: image: "lizheming/php-fpm-yaf" volumes: - "$PWD :/home/q/system/m_look_360_cn" container_name: "m.look.360.cn-php" server { listen 80; server_name dev.m.look.360.cn; charset utf-8; root /home/q/system/m_look_360_cn/public; index index.html index.htm index.php; error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } location ~ .php$ { fastcgi_pass php:9000; fastcgi_index index.php; } }
1.安装配置 Compose 支持 Linux、macOS、Windows 10 三大平台。
安装方法与流程:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $sudo pip install -U docker-compose$yum install -y docker-compose$sudo curl -L https://github.com/docker/compose/releases/download/1.17.1/docker-compose-`uname -s`-`uname -m` > /usr/local /bin/docker-compose$sudo chmod +x /usr/local /bin/docker-composesudo rm /usr/local /bin/docker-compose sudo pip uninstall docker-compose $docker -compose --versiondocker-compose version 1.18.0, build 8dd22a9
容器中执行:Compose 既然是一个 Python 应用,自然也可以直接用容器来执行它。1 2 3 4 5 6 7 8 9 10 11 12 13 14 $ curl -L https://github.com/docker/compose/releases/download/1.8.0/run.sh > /usr/local /bin/docker-compose $ chmod +x /usr/local /bin/docker-compose sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s) -$(uname -m) " -o /usr/local /bin/docker-compose [root@localhost ~] pip 9.0.3 from /usr/lib/python3.6/site-packages (python 3.6) [root@localhost ~] [root@localhost ~] docker-compose version 1.25.3, build unknown docker-py version: 4.1.0 CPython version: 3.6.8 OpenSSL version: OpenSSL 1.1.1c FIPS 28 May 2019
2.命令一览 docker-compose 命令来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或者容器。
1 2 3 4 5 docker-compose [options] [COMMAND] [ARGS...] docker-compose [COMMAND] --help 或者 docker-compose help [COMMAND]
命令选项:
-f, –file FILE 指定使用的 Compose 模板文件,默认为 docker-compose.yml可以多次指定。
-p, –project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名。
–x-networking 使用 Docker 的可拔插网络后端特性
–x-network-driver DRIVER 指定网络后端的驱动,默认为 bridge
–verbose 输出更多调试信息。
-v, –version 打印版本并退出。
命令使用说明: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 build config up / down exec help images kill logs port ps pull push run scale start pause unpause restart stop rm top version
常用命令详解: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 选项包括: --force-rm 删除构建过程中的临时容器。 --no-cache 构建镜像过程中不使用 cache(这将加长构建过程)。 --pull 始终尝试通过 pull 来获取更新版本的镜像。 选项: -d 后台运行容器。 --name NAME 为容器指定一个名字。 --entrypoint CMD 覆盖默认的容器启动指令。 -e KEY=VAL 设置环境变量值,可多次使用选项来设置多个环境变量。 -u, --user="" 指定运行容器的用户名或者 uid。 --no-deps 不自动启动关联的服务容器。 --rm 运行命令后自动删除容器,d 模式下将忽略该选项。 -p, --publish=[] 映射容器端口到本地主机。 --service-ports 配置服务端口并映射到本地主机。 -T 不分配伪 tty,意味着依赖 tty 的指令将无法运行。 例如: $docker -compose run ubuntu ping docker.com docker-compose up docker-compose up -d 选项: -d 在后台运行服务容器。 --no-color 不使用颜色来区分不同的服务的控制台输出。 --no-deps 不启动服务所链接的容器。 --force-recreate 强制重新创建容器,不能与 --no-recreate 同时使用。 --no-recreate 如果容器已经存在了,则不重新创建,不能与 --force-recreate 同时使用。 --no-build 不自动构建缺失的服务镜像。 -t, --timeout TIMEOUT 停止容器时候的超时(默认为 10 秒)。 选项: -f, --force 强制直接删除,包括非停止状态的容器。一般尽量不要使用该选项(使用前建议先stop) -v 删除容器所挂载的数据卷。 $docker -compose scale web=3 db=2
注意:
默认情况,如果服务容器已经存在,docker-compose up 将会尝试停止容器,然后重新创建(保持使用 volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml 文件的最新内容。
如果用户不希望容器被停止并重新创建,可以使用 docker-compose up –no-recreate。这样将只会启动处于停止状态的容器,而忽略已经运行的服务。
如果用户只想重新部署某个服务,可以使用 docker-compose up –no-deps -d <SERVICE_NAME> 来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。
使用 docker-compose scale一般的当指定数目多于该服务当前实际运行容器,将新创建并启动容器;反之将停止容器。
实际案例: 建议在空目录中建立Dockerfile与docker-compose.yml,并运行docker-compose运行的时候建议在Dockerfile与docker-compose.yml 当前目录下运行1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 $docker -compose config services: redis: image: redis:alpine web: build: context: /opt/app ports: - 80:8080/tcp version: '3.0' $docker -compose -p FlaskApp build Building web Step 1/5 : FROM python:3.6-alpine $docker -compose up -d Creating network "app_default" with the default driver Building web Step 1/5 : FROM python:3.6-alpine ---> 35bb01a3d284 Step 2/5 : ADD . /code $docker -compose images Container Repository Tag Image Id Size ---------------------------------------------------------- app_redis_1 redis alpine 72e76053ebb7 48.5 MB app_web_1 app_web latest e5024b7bdce1 86.1 MB $docker -compose ps Name Command State Ports --------------------------------------------------------------------------- app_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp app_web_1 python app.py Up 0.0.0.0:80->8080/tcp $docker -compose logs Attaching to app_redis_1, app_web_1 web_1 | * Debug mode: on web_1 | * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit) web_1 | * Restarting with stat web_1 | * Debugger is active! web_1 | * Debugger PIN: 324-716-279 $docker -compose exec web /bin/sh /code Dockerfile app.py docker-compose.yml /code root /code 2e10bc9c7618 /code $docker -compose stop Stopping app_redis_1 ... done Stopping app_web_1 ... done $docker -compose rm -v Going to remove app_redis_1, app_web_1 Are you sure? [yN] y Removing app_redis_1 ... done Removing app_web_1 ... done $docker -compose kill -s SIGINT
补充示例: 1 2 3 docker-compose down jenkins_server docker-compose up -d --build
3.模板文件 标准配置的docker-compose.yaml文件应该包含 version、services、networks 三大部分其中最关键的就是 services 和 networks 两个部分还有就是配置文件的格式
模板文件是使用 Compose 的核心,涉及到的指令关键字也比较多,以下面的案例为例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 version: '3' services: web: image: ubuntu/ubuntu:18.04 build:/path/to/build/dir build: context: ../ dockerfile: path/of/Dockerfile args: buildno: 1 cache_from: - alpine:latest - corp/web_app:3.14 container_name: app labels: - "com.example.author=weiyigeek" - "com.example.description=Accounting webapp" - "com.example.department=Finance" - "com.example.lrelease=rc3 for v1.0" depends_on: - db - redis redis: image: redis db: image: postgres logging: driver: syslog options: syslog-address: "tcp://192.168.0.42:123" max-size: "200k" max-file: "10" ports: - 8080 - "49100:22" - "127.0.0.1:8001:8001" security_opt: - label:user:USER - label:role:ROLE stop_signal: SIGUSR1 networks: - front-tier - back-tier network_mode: "bridge" dns: - 8.8.8.8 - 9.9.9.9 dns_search: - dc1.example.com - dc2.example.com redis: image: redis tmpfs: /run tmpfs: - /run - /tmp env_file: - ./common.env - ./apps/web.env - /opt/secrets.env environment: - RACK_ENV=development - SHOW=true - SESSION_SECRET - MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password secrets: - db_root_password - my_other_secret expose: - "6379" links: - web command : bundle exec thin -p 3000 entrypoint: /code/entrypoint.sh entrypoint: - php - -d - zend_extension=/usr/local /lib/php/extensions/no-debug-non-zts-20100525/xdebug.so - -d - memory_limit=-1 - vendor/bin/phpunit lb: image: dockercloud/haproxy ports: - 80:80 extra_hosts: - "somehost:162.242.195.82" - "otherhost:50.31.209.229" external_links: - redis_1 - project_db_1:mysql - project_db_1:postgresql links: - web cgroup_parent: cgroups_1 network_mode: "host" networks: - front-tier - back-tier volumes: - /var/run/docker.sock:/var/run/docker.sock - ~/configs:/etc/configs/:ro - datavolume:/var/lib/mysql - './nginx/log:/var/log/nginx:rw' volumes_from: - service_name - service_name:ro - container:container_name - container:container_name:rw cap_add: - ALL cap_drop: - NET_ADMIN - SYS_ADMIN devices: - "/dev/ttyUSB0:/dev/ttyUSB0" healthcheck: test : ["CMD" , "curl" , "-f" , "http://localhost" ] interval: 1m30s timeout: 10s retries: 3 pid: "host" sysctls: - net.core.somaxconn=32768 - net.ipv4.tcp_syncookies=0 - net.ipv4.ip_forward=1 ulimits: nproc: 65535 nofile: soft: 20000 hard: 40000 volumes: esdata1: driver: local datavolume: driver: local driver_opts: type : none device: $PWD /logs o: bind networks: front-tier: driver: bridge back-tier: driver: bridge aliases: - alias1 networks: mongocluster_default: external: true secrets: my_secret: file: ./my_secret.txt my_other_secret: external: true
Compose 模板文件支持动态读取主机的系统环境变量和当前目录下的 .env 文件中的变量。 环境变量文件中每一行必须符合格式,支持 # 开头的注释行。1 2 3 4 5 6 7 8 9 10 PROG_ENV=development MONGO_VERSION=3.6 version: "3" services: db: image: "mongo:${MONGO_VERSION} "
4.使用案例 使用案例1:docker-compose 配合Dockerfile构建容器,采用python的flask框架与redis1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 ├── app.py ├── docker-compose.yml └── Dockerfile from flask import Flask from redis import Redis app = Flask(__name__) redis = Redis(host='redis' , port=6379) @app.route('/' ) def hello(): count = redis.incr('hits' ) return 'Hello World! 该页面已被访问 {} 次。\n' .format(count) if __name__ == "__main__" : app.run(host="0.0.0.0" ,port=8080,debug=True) version: '3' services: web: build: . ports: - "80:8080" redis: image: "redis:alpine" FROM python:3.6-alpine ADD . /code WORKDIR /code RUN pip install redis flask RUN chown -R $USER :$USER . CMD ["python" , "app.py" ]
weiyigeek.top-
访问我们构建的服务显示:
weiyigeek.top-
使用案例2:采用docker-compose构建博客镜像1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 git clone https://github.com/WeiyiGeek/blog.git $nano init.sh#!/bin/bash npm config set unsafe-perm true npm config set registry https://registry.npmmirror.com npm install -g hexo-cli --save npm install --save hexo server version: "3.0" services: blog: image: "mhart/alpine-node:latest" container_name: blog labels: - "com.example.author=weiyigeek" - "com.example.description=my blog" - "com.example.department=IT" - "com.example.lrelease=v1.0" ports: - "80:4000" volumes: - "$PWD :/opt/blog/" working_dir: /opt/blog/ entrypoint: /opt/blog/init.sh
注意事项 :
如果你同时指定了 image 和 build 两个标签,那么 Compose 会构建镜像并且把镜像命名为 image 后面的那个名字。
1 2 3 4 5 6 7 8 9 10 11 build: ./dir image: webapp:tag build: context: . args: - buildno=1 - password=secret - version
YAML 的布尔值(true, false, yes, no, on, off)必须要使用引号引起来(单引号、双引号均可),否则会当成字符串解析。
如果env_file指定.env文件有变量名称 与 environment 指令冲突则以后者为准。
注意env_file标签的使用,是这里所说的环境变量是对宿主机的 Compose 而言的:
如果在配置文件中有 build 操作这些变量并不会进入构建过程中,
如果要在构建中使用变量还是首选前面刚讲的 arg 标签。
补充标签与docker run参数一致
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 configs deploy cpu_shares: 73 cpu_quota: 50000 cpuset: 0,1 user: postgresql working_dir: /code domainname: foo.com hostname: foo ipc: host mac_address: 02:42:ac:11:65:43 privileged: true restart: always read_only: true shm_size: 64M stdin_open: true tty: true mem_limit: 1000000000 memswap_limit: 2000000000
使用案例3:采用docker-compose构建 MySQL / Redis / Adminer
;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 version: '3.1' services: db8: image: mysql container_name: mysql8.x command : --default-authentication-plugin=mysql_native_password restart: always environment: MYSQL_ROOT_PASSWORD: www.weiyigeek.top MYSQL_DATABASE: test MYSQL_USER: test8 MYSQL_PASSWORD: weiyigeek.top volumes: - "/app/mysql8:/var/lib/mysql" ports: - 3306:3306 networks: - database-net db5: image: mysql:5.7.29 container_name: mysql5.x command : --default-authentication-plugin=mysql_native_password restart: always environment: MYSQL_ROOT_PASSWORD: www.weiyigeek.top MYSQL_DATABASE: test MYSQL_USER: test5 MYSQL_PASSWORD: weiyigeek.top volumes: - "/app/mysql5:/var/lib/mysql" ports: - 3305:3306 networks: - database-net redis: image: redis container_name: redis restart: always command : redis-server --requirepass weiyigeek.top volumes: - "/app/redis:/data" ports: - 6379:6379 adminer: image: adminer container_name: MySQLManager restart: always ports: - 8888:8080 networks: - database-net links: - db8:mysql8.x - db5:mysql5.7 depends_on: - db8 - db5 networks: mysql_database-net: external: true
Tips : 此时若还要docker容器间进行相互通讯需要进行配置防火墙信任 docker 的 ip 地址
,比如:firewall-cmd --zone=trusted --add-source=172.17.0.1/16 --permanent
,如果部署iptable报错请重启docker;
5.学习补充 1) Docker-compose 设置容器数据持久化的方式 描述: 我常常利用 docker-compose 进行容器的创建,它有两种设置方式都是可以持久化的;
Q: 如何查看docker的卷标?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 docker volume ls $ docker volume ls | grep mysql local vagrant_mysql$ docker volume inspect vagrant_mysql [ { "Name" : "vagrant_mysql" , "Driver" : "local" , "Mountpoint" : "/var/lib/docker/volumes/vagrant_mysql/_data" } ]