docker--笔记(四)

Docker 持久化数据的方案:
基于本地文件系统的Volume: 可以在执行Docker create 或 Docker run 时,通过-v参数将主机的目录作为容器的数据卷。这部分功能便是基于本地文件系统的volume管理

基于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 ,查看网页显示变化

实战--部署一个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


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:


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/

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.whoami

Routing Mesh 的两种体现:
Internal --Container和Container之间的访问通过overlay网络(通过VIP虚拟IP)
Ingress --如果服务有绑定接口,则此服务可以通过任意swarm节点的响应接口访问

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
#

说明:
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 wordpress

实战部署投票应用:
>> sudo docker stack deploy example --compose-file=docker-compose.yml
>> sudo docker stack ls
>> sudo docker stack services example

# 离开节点
>> 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

猜你喜欢

转载自www.cnblogs.com/wgwblogs/p/11069575.html