Docker 持久化数据的方案:
基于本地文件系统的Volume: 能够在执行Docker create 或 Docker run 时,经过-v参数将主机的目录做为容器的数据卷。这部分功能即是基于本地文件系统的volume管理html
基于plugin的volume,支持第三方的存储方案,好比NAS,aws
volume类型:
受管理的data Volume,由docker后台自动建立
绑定挂载的Volume,具体挂载位置能够由用户指定。
数据持久化:
方法一:Data Volume
以mysql为例:
>> sudo docker run -d --name mysql1 -e MYSQL_ROOT_PASSWORD=root mysql:5.7
>> sudo docker run -d --name mysql1 -e
mysql #去掉密码
>> sudo docker volume ls
>> sudo docker volume inspect + VOLUMENAME
>> sudo docker run -d -v mysql:/var/lib/mysql --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql # -v 给volume name重命名
>> sudo docker exec -it mysql1 /bin/bash
# mysql -uroot -p
# show databases;
# create database docker;
>> sudo docker stop mysql1
>> sudo docker rm mysql1
>> sudo docker volume ls
>> sudo docker run -d -v mysql:/var/lib/mysql --name mysql2 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
>> sudo docker exec -it mysql2 /bin/bash
# mysql -uroot -p
# show databases; # 发现docker这个数据库还在
方法二:Bind Mouting
docker run -v 本地目录:容器目录
>> sudo docker run -d -p 80:80 -v $(pwd):/usr/share/nginx/html --name web wgw/nginxt
>> sudo docker exec -it web /bin/bash
# ls
# cd /usr/share/nginx/html
# touch test.txt
# exit
>> ls # 发现当期目录也有了test.txt,说明当前目录和容器中的/usr/share/nginx/html是同步的
实战:
Dokcer + bind mount
>> sudo docker build -t wgw/flask-skeleton .
>> sudo docker run -d -p 80:5000 -v $(pwd):/skeleton --name falsk wgw/flask-skeleton
# 实时修改本地的home.html ,查看网页显示变化node
实战--部署一个wordpress:
>> sudo docker run -d --name mysql -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=wordpress mysql
>> sudo docker run -d -e WORDPRESS_DB_HOST=mysql:3306 -e WORDPRESS_DB_PASSWORD=root --link mysql -p 8888:80 wordpress python
Docker compose究竟是什么?
Docker Compose "批处理"
Docker Compose 是一个工具
这个工具能够经过一个yml文件定义多容器的docker应用
经过一条命令就能够根据yml文件的定义去建立或者管理多个容器
安装docker compose:
https://docs.docker.com/compose/install/
docker-compose.yml:
三大概念:
services:
一个service表明一个container,这个container能够从dockerhub的image来建立,
或者能够从本地的Dockerfile build出来的image建立
service的启动相似docker run,咱们能够给其指定network和volume,因此能够给service指定network和volume的引用
networks:mysql
volumes:
>> docker-compose up # 将咱们yml文件中定义的容器所有运行起来
>> docker-compose -f docker-compose.yml up -d
>> docker-compose ps
>> docker-compose images
>> docker-compose exec +yml文件中定义的service bash
>> docker-compose down # 中止并删除
水平扩展与负载均衡:
>> docker-compose up -d
>> docker-compose ps
>> docker-compose up --scale web=3 # 启动3个web容器
容器编排:Swarm mode
问题引入:
怎么去管理这么多容器?
怎么能方便的横向扩展?
若是容器down了,怎么能自动恢复?
如何去更新容器而不影响业务?
如何去监控追踪这些容器?
怎么去调度容器的建立?
怎么保护隐私数据?
swarm是一种集群的架构:
service和replicas
建立一个3节点的swarm集群:
三种方法:
方法一:
vagrant + virtuabox
>> sudo docker swarm init --advertise-addr=192.168.50.2 # swarm
# 拷贝docker swarm join ... 到其余节点上node2,node3
>> sudo docker node ls #显示当前swarm的节点
方法二:
docker machine + virtualbox
~ docker-machine create node1
~ docker-machine create node2
~ docker-machine create node2
方法三:
play with docker https://labs.play-with-docker.com/nginx
service建立维护和水平扩展:
# node1
>> sudo docker service create --name demo busybox sh -c "while true;do sleep 3600;done"
>> sudo docker service ls # 其中replicated代表能够水平扩展
ID NAME MODE REPLICAS IMAGE PORTS
8c41wr8l7u4r demo replicated 1/1 busybox:latest
>> sudo docker service demo ps
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE
xowievbqgav8 demo.1 busybox:latest wgw2 Running Running 3 minutes ago
>> sudo docker service scale demo=5 # 水平扩展为5个
>> sudo docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
8c41wr8l7u4r demo replicated 5/5 busybox:latest
>> sudo docker service ps demo # 发现这5个service分布在不一样的节点上
# 在node2或node3上强制删除一个service
>> sudo docker ps
>> sudo docker rm -f "19d46aefc5ab"
# node1
>> sudo docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
8c41wr8l7u4r demo replicated 4/5 busybox:latest
>> sudo docker service ls # 再执行一遍,发现有变回了5个,说明scale不只保证了水平扩展,并且保证了必定数目的扩展是有效的,
# 从而保证了系统的有效与稳定
ID NAME MODE REPLICAS IMAGE PORTS
8c41wr8l7u4r demo replicated 5/5 busybox:latest
>> sudo service rm demo # 删除service,看到很快的删除,其实真正删除是要必定的过程
实战————在swarm集群中经过service部署wordpress:
>> sudo docker network create -d overlay demo # 实现多机通讯
>> sudo docker network ls
# 建立mysql的服务
# sudo docker service create --name mysql-server --network demo --env MYSQL_ROOT_PASSWORD=root123 --env MYSQL_DATABASE=wordpress --mount(docker中是-v) type=volume,source(存储的本地址)=mysql-data,destination(容器中的位置)=/var/lib/mysql mysql:5.7
>>sudo docker service create --name mysql-server --network demo --env MYSQL_ROOT_PASSWORD=root123Abc? --env MYSQL_DATABASE=wordpress --mount type=volume,source=mysql-data,destination=/var/lib/mysql mysql:5.7
>> sudo docker service ls
>> sudo docker service ps mysql # 查看mysql服务运行在哪一个节点上
# 建立wordpress service
>> sudo docker service create --name wordpress --network demo -p 80:80 --env WORDPRESS_DB_PASSWORD=root123Abc? --env WORDPRESS_DB_HOST=mysql-server wordpress
集群服务间通讯之RoutingMesh:
DNS服务发现:
以wordpress多机部署为例:
咱们的mysql和wordpress分别位于不一样的节点上,他们之间经过service name 进行通讯,由于swarm有一个内置的DNS服务发现的功能,咱们经过service建立一个service时,若是他识别到了一个overlay的网络上面,咱们就会为链接到这个overlay网络上面的全部的service添加一条DNS记录,咱们经过DNS记录就能知道他的ip地址,而后咱们就能够访问这个服务了,可是,service中的DNS记录中的service name 对应的ip并非实际的ip,而是有一个虚拟IP叫作vip,由于咱们的service的ip是不稳定的(好比因为x当掉了,service从新分配时分配到了另外一个节点),而service name - vip与真实ip的对应关系是用lvs来解决的
>> sudo docker service create --name whoami -p 8000:8000 --network demo
-d jwilder/whoami
>> sudo docker service create --name client -d --network demo busybox sh -c "while true;do sleep 3600; done"
>> sudo docker exec -it 38e sh # client
~ ping whoami # 能够ping通,可是他Ping的是10.0.0.35这个ip,并非whoami的真实ip
问题:
若是将whoami横向扩展成2个,ping的时候他的ip会不会变?
>> sudo docker service scale whoami=2
>> sudo docker service ps whoami
>> sudo docker exec -it 38e sh # client
~ ping whoami # 能够ping通,可是他的ip并无发生变化,他真正ping的是一个vip--虚拟ip
~ nslookup whoami # sudo yum install bind-utils,没有的话能够安装,用来查询dns
Server: 127.0.0.11 # DNS服务器地址
Address: 127.0.0.11:53
Name: whoami
Address: 10.0.0.35
~ nslookup tasks.whoamigit
Routing Mesh 的两种体现:
Internal --Container和Container之间的访问经过overlay网络(经过VIP虚拟IP)
Ingress --若是服务有绑定接口,则此服务能够经过任意swarm节点的响应接口访问github
RoutingMesh之Ingress负载均衡:
Ingress Network:
1.外部访问的负载均衡
2.服务端口被暴露到各个swarm节点
3.内部经过IPVS进行负载均衡
当咱们去任何一台swarm节点上去访问端口服务的时候,他会把咱们的服务经过本地的本节点的ipvs把个人这个服务load balance 到真正具备service的swarm节点上,再把response返回给咱们
>> sudo iptables -nL -t nat # 能够看到咱们本地的一些转发规则
Chain DOCKER-INGRESS (2 references)
target prot opt source destination
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8000 to:172.18.0.2:8000
RETURN all -- 0.0.0.0/0 0.0.0.0/0
>> ip a
...
docker_gwbridge: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:c4:2e:14:07 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global docker_gwbridge
valid_lft forever preferred_lft forever
inet6 fe80::42:c4ff:fe2e:1407/64 scope link
valid_lft forever preferred_lft forever
...
>> brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242cdeade99 no
docker_gwbridge 8000.0242c42e1407 no veth403a876
veth76ab65a
>>sudo docker network inspect docker_gwbridge
"Containers": {
"38e4791dc1df72c9511527f08ce234498ae609cd1a085f5e8363555994627f89": {
"Name": "gateway_d485c6e2abcb",
"EndpointID": "72861c680ba4ded23a008d40e6fa107aa015b9a3.0.76a369f734aefd824cbde",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"ingress-sbox": {
"Name": "gateway_ingress-sbox",
"EndpointID": "266905d9d33abea66e0df42ae28c68781aef72e9afcca2122a44688b0af9f59f",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
>>sudo ls /var/run/docker/netns
1-guy2oiuzz0 1-ll8amb5yay d485c6e2abcb ingress_sbox lb_guy2oiuzz
>> sudo yum install ipvsadm # 这是一个LVS管理的工具
>>nsenter --net=/var/run/docker/netns/ingress_sbox # 进入到ingress_sbox
# ip a # 看到ip变成了172.18.0.2,咱们已经不是在本地的network namespace了
# iptables -nL -t mangle # 能够看到他去往8000端口的他给作了一个mark set,其实就是作了一个负载均衡
target prot opt source destination
MARK tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8000 MARK set 0x10a
# ipvsadm -l
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
FWM 266 rr
-> 10.255.0.10:0 Masq 1 0 0 # 这个就是咱们的whoami 的service containal的地址
-> 10.255.0.11:0 Masq 1 0 0
# web
说明:
Ingress Network的数据包走向详情:
127.0.0.1:8000 ===> {HOST1:docker_gwbridge ===> Ingress-sbox[iptables MANGLE table PREROUTING MARK:Published-PORT->ingress-sbox] -> <fw-mark-id>][IPVS Match<fw-mark-id>->Masq{RR across container-IPs}](他实际上是一个network namespace)===>Ingress Network[ingress-overlay-bridge]}==
vxlan tunner with vni ===>{HOST2:Ingress Network[ingress-overlay-bridge]===>[container-sbox] and [Ingress-sbox]====>default_gwbridge==>Ingress-sbox[iptables MANGLE table PREROUTING MARK:Published-PORT->ingress-sbox]}
DockerStack部署wordpress:
# 建立一个名字为wordpress的stack
>> sudo docker stack deploy wordpress --compose-file=docker-compose.yml
>> sudo docker stack ls
NAME SERVICES ORCHESTRATOR
wordpress 2 Swarm
>> sudo docker stack ps wordpress
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
p5hoplu3al3e wordpress_mysql.zg3vus7jnzjl3vl3uealg580h mysql:5.7 wgw2 Running Running about a minute ago
bdxdyuovmgil wordpress_web.1 wordpress:latest wgw6 Running Preparing about a minute ago
qv2p70q0e0xa wordpress_web.2 wordpress:latest wgw2 Running Preparing about a minute ago
tync4d3u4sld wordpress_web.3 wordpress:latest wgw3 Running Running about a minute ago
>> sudo docker stack services wordpress
ID NAME MODE REPLICAS IMAGE PORTS
aw6py2ckn4k8 wordpress_web replicated 1/3 wordpress:latest *:8080->80/tcp
u4ksl9mmtbax wordpress_mysql global 1/1 mysql:5.7
>> sudo docker stack rm wordpresssql
实战部署投票应用:
>> sudo docker stack deploy example --compose-file=docker-compose.yml
>> sudo docker stack ls
>> sudo docker stack services exampledocker
# 离开节点
>> sudo docker swarm leave
# manager离开节点
>> sudo docker swarm leave --force
DockerSecret的管理和使用:
Docker Secrets Managment:
什么是secret?
1.用户名密码
2.SSH KEY
3.TLS认证
4.任何不想让别人看到的数据
Secrets Managment:
1.存在swarm manager节点Raft database里
2.secret能够assign给一个service,这个service就能看到这个sercret
3.在container内部secret看起来像文件,可是其实是在内存中
方法一:经过文件建立
>> sudo vim password
# admin123
>> sudo docker secret create my-password(名字) password(上面建立的文件) # 建立完以后删除password文件
>> sudo rm -rf password
>> sudo docker secret ls # 就能够看到咱们这个节点上有哪些secret
方法二:经过标准输入
>> echo "admin123" | docker secret create my-password2 -
# 删除secret
>> sudo docker secret rm my-password2
service如何去使用secret?
>> sudo docker service create --name client --secret my-password busybox sh -c "while true;do sleep 3600;done" # 这样的话咱们的service就能够看到my-password
>> sudo docker service ls
>> sudo docker service ps client
>> sudo docker ps
>> sudo docker exec -it 04c7f7bb13a9 sh
# cd /run/secrets/
# ls
~my-password
# cat my-password # 就能够看到咱们的密码原文
~admin123
>> sudo docker service create --name db --secret my-password -e MYSQL_ROOT_PASSWORD_FILE=/run/secrets/my-password mysql:5.7
>> sudo docker exec -it 6dc34 sh
# ls /run/secrets
~my-password
# cat my-password
# mysql -uroot -p
Dockersecret 在Stack中的使用:
https://github.com/phantom0925/dockerstack-wordpress/blob/master/wordpress/docker-compose.yml
Service更新:
如何在service正在运行中进行更新:
>> sudo docker network ls
>> sudo docker service create --name web --publish 8080:5000 --network demo xiaopeng163/python-flask-demo:1.0
# 要更新又要不中断
# 第一步:scale
manager节点
>> sudo docker service scale web=2
>> sudo docker service ps web
>> curl 127.0.0.1:8080
node2节点
>> sh -c "while true;do curl 127.0.0.1:8080&&sleep 1;done"
manager节点 >> sudo docker service update --image xiaopeng163/python-flask-demo:2.0 web