Docker 是一个开源的应用容器引擎,主要利用 linux 内核 namespace 实现沙盒隔离,用cgroup 实现资源限制。
实验环境:rhel7.3
一.准备工作
1安装以下包:
yum install
container-selinux-2.21-1.el7.noarch.rpm
docker-ce-18.03.1.ce-1.el7.centos.x86_64.rpm
libsemanage-2.5-8.el7.x86_64.rpm
libsemanage-python-2.5-8.el7.x86_64.rpm
pigz-2.3.4-1.el7.x86_64.rpm
policycoreutils-2.5-17.1.el7.x86_64.rpm
policycoreutils-python-2.5-17.1.el7.x86_64.rpm
这里说一下yum源问题:https://www.docker.com/ 官网
https://mirrors.aliyun.com/centos/
www.pkgs.org
2.启动服务
systemctl start docker
ip addr会发现多了个桥接网络
二.镜像管理,镜像tar包另行下载
镜像用来创建容器,是容器的只读模板,默认可以从 docker hub 上下载。docker 的镜像是增量修改,每次创建新的镜像都会在父镜像上构建一个增量的层,基于 AUFS 技术。
docker search 查询镜像
docker pull 拉取镜像
docker push 推送镜像
镜像默认可以从 docker hub 上下载,这是 docker 官方的公共仓库,为我们免费提供了大量已经容器化的应用镜像,避免我们重复的去造轮子。但是官方并没有在国内部署服务器,如果你不走 vpn 的话真的是太慢了,报错和超时让人非常的郁闷。给大家介绍个可以快速下载镜像的好办法:www.daocloud.io 为我们提供了永久免费的加速器服务,相当于 docker hub 在国内的缓存服务器,我测试过真的是又快又爽。首先你需要在此网站上注册一个帐号,加速器需要和 Daocloud ID 绑定才能正常工作。注册后进入加速器页面,按照提示选择你的自有主机的系统类型,我使用的是 rhel7,直接选择了 centos 就可以。(rhel6 内核太旧不支持)
rhel7的镜像tar包,下载
https://dashboard.daocloud.io 百度daocloud.io就行
然后宿主机:(也可以是其他主机,下造后传给宿主机总之得能通网,按照提示,执行命令)
docker pull richxsl/rhel7:latest
三.容器的管理
yum install bash-*
##安装后如果是ssh链接的话退出重新链接,可以tab出相关命令
载入本地镜像docker load -i /PATH/x.tar
载入 ubuntu镜像tar包
docker load -i /root/ubuntu.tar
载入nginx镜像tar包
docker load -i /root/nginx.tar
查看当前载入的镜像
docker images
把刚才下载的镜像导出为tar包方便后边使用
docker save richxsl/rhel7 > rhel7.tar
镜像信息的查看:以nginx为例,
docker inspect nginx:latest
镜像历史版本的查看
docker history nginx:latest
启用运行(容器)镜像,以nginx为例
docker run -d nginx ##-d标识后台运行
docker ps -a ##查看进程信息,启用了80(http)端口和443(https)
yum install bridge-utils ##安装brctl命令
brctl show ##会发现docker0桥接到了veth67bcb26上
ipaddr 查看多出了个 veth67bcb26@if4
此时nginx容器使用的172.17.0.2而网关再docker0上172.17.0.1
iptables -t nat -nL
查看多了个DOCKER链,事实上,宿主机此时充当了路由的作用,
sysctl -a | grep ipv4.ip_forward
##内核路由功能已经开启
关闭容器的nginx
查看id
docker ps -a
docker stop $id ##id不一定要写全,开头一个能单独区分也可以,但良好的习惯是应该写全的
docker ps -a ##载此查看发现还在只是状态不是up了
docker rm $id ##删除,但并没有从载入的镜像库中删除,docker images 查看其实还在
docker images ##还在
删除镜像
docker rmi nginx:latest | 或者#id
赶紧载入回来,还要使用nginx
docker load -i nginx.tar
下边这条命令是后台运行nginx 端口影射80,命名为web,非必要,如果不给名字的话随机产生
docker run -d -p 80:80 --name web nginx
docker stats web ##查看web就是nginx状态
docker ps -a ##查看进程信息正在启用
docker inspect web ##查看nginx状态
此时客户端访问:172.25.51.1
docker inspect web
http://172.25.51.1/
这是服务的部署
下来看看gama2048:
docker load -i game2048.tar ##载入包
docker run -d -p 8888:80 --name game game2048:latest ##启动服务,这里端口映射8888,因为上边的nginx占用了80,避免端口冲突
docker inspect game ##查看下信息,发现ip自增1,后边加的服务都是这样的,依次自增
浏览器查看:
http://172.25.51.1:8888
系统的的构建以ubuntu为例
docker run -it --name vm-ubuntu ubuntu bash ##启用命名为vm-ubuntu
Shell行后查看ip
宿主机查看桥接网络
brctl show ##会发现docker0 分别桥接了三个interface,前两个是nginx和2048游戏的,最后一个自然是ubuntu系统的了172.17.0.4 (172.17.0.1是网关docker0)
测试:分别ping网关,dns114.114.114.114以及www.baidu.com,默认网络桥接模式是可以访问外网的,前提是宿主机对外联网
Ubuntu下时可以执行命令的,rhel7可能无法执行为正常现象
这是ubuntu
这是redhat7
呐,docker ps -a 查看对应的id
ctrl + p + q ##打入后台运行,以rhel7为例
docker attach redhat7 ##调回前台
Ctrl + z 退出
docker logs redhat7 ##相当于实时录屏在redhat7上的操作都会被查除,exec除外
docker container exec web ls /usr/share/nginx/html ##列出web(nginx)的发布页有哪些
docker container exec web ls /etc/nginx ##查看web的配置文件信息
在宿主机家目录中写一个网页添加到nginx的默认发布目录中,这个时候查看容器是否被修改,当然修改了
echo "hello,nginx" >test.html
echo "hello,nginx" >>test.html
docker container cp test.html web:/usr/share/nginx/html/
docker diff web
浏览器访问:
http://172.25.51.1/test.html
curl 172.25.51.1/test.html
docker container ps
docker ps
两者效果其实一样,前者将不vfen命令归类了
docker top web
docker container top web
docker container stats vm1 ##动态监控
docker container top vm1 ##静态数据监控
docker container prune ##删除所有关闭的容器
docker search nginx ##查看nginx(默认联网搜索)
配置docker加速器,自己申请 加速器默认下载到这里cd /etc/docker/
docker run -it --name vm1 ubuntu bash 创建容器
docker ps -a 查看容器状态
docker attach vm1 连接容器
docker top vm1 查看容器进程
docker logs vm1 查看容器指令输出 -f 参数可以实时查看
docker inspect vm1 查看容器详情
docker stats vm1 查看容器资源使用率
docker diff vm1 查看容器修改
docker run -d --name vm1 ubuntu bash -c "while true; do echo westos; sleep 1; done" 后台运行
docker stop vm1 停止容器
docker start vm1 启动容器
docker kill vm1 强制干掉容器
docker restart vm1 重启容器
docker pause/unpause vm1 暂停/恢复容器
docker rm vm1 删除容器
docker export vm1 > vm1.tar 导出容器
docker import vm1.tar image 导入容器为镜像 image
docker search 查询镜像
docker pull 拉取镜像
docker push 推送镜像
四.数据卷管理
docker run 在创建容器时使用 -v 参数可以挂载一个或多个数据卷到当前运行的容器中,-v的作用是将宿主机上的目录作为容器的数据卷挂载到容器中,使宿主机和容器之间可以共享一个目录。
挂载数据卷到新创建的容器上:docker run -it –name westos -v /tmp/data1:/data1 -v /tmp/data2:/data2 rhel7 /bin/bash
-v 参数可以重复使用,挂载多个数据卷到容器中,冒号前面的是宿主机的目录(本地目录
不存在 docker 会自动创建),冒号后面的是容器中的挂载目录。
注:docker commit 时卷的数据不会被保存。
默认挂载可以读写数据卷,也可以只读挂载:docker run -it –name westos2 -v /tmp/data2:/data2:ro rhel /bin/bash
实例:
先关闭nginx服务
docker stop web ##截图右半部分有省略
docker rm web ##移除nginx
docker ps -a ##查看所有进程,一定加-a,否则只显示在线的服务
docker run -d -p 80:80 –name web -v /tmp/html/:/usr/share/nginx/html/ nginx ##重新挂载nginx服务的默认发布目录到/tmp/html下,默认可以写的,如果忘记写了很可能报错80端口被拒,采过坑的
ls /tmp/html/ ##空的
echo "nginx mount-point is /tmp/html" >/tmp/html/index.html
echo "nginx mount-point page server/html" >/tmp/html/server.html
客户端测试:
curl 172.25.51.1
--->>nginx mount-point is /tmp/html
curl 172.25.51.1/server.html
--->>nginx mount-point page server/html
再回来查看nginx容器自身的数据
docker container exec web ls /usr/share/nginx/html/ ##查看
镜像数据卷挂载
docker run -it --name vm2 -v /tmp/data1:/data1 -v /tmp/data2:/data2 -v /etc/passwd:/passwd:ro ubuntu
运行ubuntu,把宿主机的/tmp/data1挂载到容器中的/data1,宿主机的/tmp/data2挂载到容器中的/data2,宿主机的/etc/passwd挂载到容器/paswwd,ro只读模式
Ctrl +c 退出后到宿主机查看
宿主机下在/tmp/data2中新建文件data2
容器同步了
docker create --name datavol -v /tmp/data:/data1 -v /tmp/data2:/data2 -v /etc/passwd:/passwd:ro ubuntu ##做虚拟封装,docker ps 查不到,默认为stop状态
docker run -it --volumes-from datavol --name v-m1 ubuntu ##可以拿虚拟封装直接启动
备份数据卷:
docker run --rm --volumes-from datavol -v /tmp/backup:/backup ubuntu tar cf /backup/data.tar /data2
五.网络管理
实验前清清(非必要)
docker kill `docker ps -aq` ##批量停止,比stop快
docker rm `docker ps -aq` ##批量删除
Docker 在启动时会创建一个虚拟网桥 docker0,默认地址为 172.17.42.1/16, 容器启动后都会被桥接到 docker0 上,并自动分配到一个 IP 地址。容器的四种网络模式:
bridge 桥接模式、host 模式、container 模式和 none 模式
启动容器时可以使用 –net 参数指定,默认是桥接模式
Bridge 桥接模式的实现步骤主要如下:
(1) Docker Daemon 利用 veth pair 技术,在宿主机上创建两个虚拟网络接口设备,假设为veth0 和 veth1。而 veth pair 技术的特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方。
(2) Docker Daemon 将 veth0 附加到 Docker Daemon 创建的 docker0 网桥上。保证宿主机的网络报文可以发往 veth0;
(3) Docker Daemon 将 veth1 添加到 Docker Container 所属的 namespace 下,并被改名为 eth0。如此一来,保证宿主机的网络报文若发往 veth0,则立即会被 eth0 接收,实现宿主机到Docker Container 网络的联通性;同时,也保证 Docker Container 单独使用 eth0,实现容器网络环境的隔离性。bridge 桥接模式下的 Docker Container 在使用时,并非为开发者包办了一切。最明显的是,该模式下 Docker Container 不具有一个公有 IP,即和宿主机的 eth0 不处于同一个网段。导致的结果是宿主机以外的世界不能直接和容器进行通信。虽然 NAT 模式经过中间处理实现了这一点,但是 NAT 模式仍然存在问题与不便,如:容器均需要在宿主机上竞争端口,容器内部服务的访问者需要使用服务发现获知服务的外部端口等。另外 NAT 模式由于是在三层网络上的实现手段,故肯定会影响网络的传输效率。
docker network ls ##显示网络信息
docker run -it --name vm1 ubuntu ##容器启动ubuntu
ip addr
打开新的shellssh链接宿主机
查看ip
ping www.baidu.com ,可以ping通,
Host 网络模式:
host 模式是 bridge 桥接模式很好的补充。采用 host 模式的 Docker Container,可以直接使用宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换。当然,有这样的方便,肯定会损失部分其他的特性,最明显的是 Docker Container 网络环境隔离性的弱化,即容器不再拥有隔离、独立的网络栈。另外,使用 host 模式的 Docker Container 虽然可以让容器内部的服务和传统情况无差别、无改造的使用,但是由于网络隔离性的弱化,该容器会与宿主机共享竞争网络栈的使用;另外,容器内部将不再拥有所有的端口资源,原因是部分端口资源已经被宿主机本身的服务占用,还有部分端口已经用以 bridge 网络模式容器的端口映射。
docker run -it --network host ubuntu
ip addr
None 网络模式:
网络环境为 none,即不为 Docker Container 任何的网络环境。一旦 Docker Container 采用了none 网络模式,那么容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。可以说 none 模式为 Docker Container 做了极少的网络设定,但是俗话说得好“少即是多”,在没有网络配置的情况下,作为 Docker 开发者,才能在这基础做其他无限多可能的网络定制开发。这也恰巧体现了 Docker 设计理念的开放。
在 none 网络模式下分配固定 ip:
netns 是在 linux 中提供网络虚拟化的一个项目,使用 netns 网络空间虚拟化可以在本地虚拟化出多个网络环境,目前 netns 在 lxc 容器中被用来为容器提供网络。使用 netns 创建的网络空间独立于当前系统的网络空间,其中的网络设备以及 iptables 规则等都是独立的,就好像进入了另外一个网络一样。
docker run -it --name vm2 --network none ubuntu
ip addr
打开新shell链接上server1
ip link add name veth0 type veth peer name veth1
brctl addif docker0 veth1
brctl show
ip link set up veth1
ip link set up veth0
docker inspect vm2 | grep Pid ##vm2哦,Pid,注意
cd /proc/1674/ns/
ln -s /proc/1674/ns/net /var/run/netns/1674
ip netns list
ip link set veth0 netns 1674
ip netns exec 1674 ip link set veth0 name eth0
ip netns exec 1674 ip addr add 172.17.0.10/24 dev eth0
ip netns exec 1674 ip link set up eth0
ip netns exec 1674 ip route add default via 172.17.0.1
docker attach vm2
ip addr
可以ping通宿主机,外网
查看路由表,自动添加nat策略
六.容器端口映射
docker run -p 8001:443 -it –name site1 nginx bash
docker run -it -P –name site2 nginx bash
大写 -P 参数表示宿主机随机分配端口
七.容器间互联:
–link 参数可以在不映射端口的前提下为两个容器间建立安全连接, –link 参数可以连接一个或多个容器到将要创建的容器。
–link 参数的格式为 –link name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。
清环境
docker kill `docker ps -aq`
docker rm `docker ps -aq`
添加nginx
docker run -d --name web -P nginx:latest
docker run -it --name vm1 ubuntu:latest
别急着退出,打开另一个shell(server1)
docker run -it --name vm2 --link vm1:web ubuntu
ping web
八.容器封装
docker kill `docker ps -aq`
docker rm `docker ps -aq`
Dockerfile 编写:
FROM rhel7:v1 指定基础镜像
MAINTAINER haitangyijiu@163.com 作者信息
ENV HOSTNAME server1 设置容器主机名
EXPOSE 80 暴露容器端口
RUN yum install -y httpd 镜像操作命令
CMD ["/usr/sbin/httpd","-D","FOREGROUND"] 镜像启动命令,默认只能启动一
条
docker run --name v1 -it rhel7 bash
cd /etc/yum.repos.d/
vi yum.repo
[yum]
name=rhel7.3
baseurl=http://172.25.51.250/rhel7.3
gpgcheck=0
rm -fr rhel7.repo
rpmdb --rebuilddb ##直接在容器里边执行,ctrl + p+q 到外边执行貌似也行,可以试试看,总之不能ctrl + d | z
docker commit v1 rhel7:v1 ##提交镜像v1
docker build -t rhel7:web /root/ 创建镜像 rhel7:web ##后边根的Dockerfile文件路径
然后运行web就是装了httpd服务的容器
docker run -d --name apache -v /tmp/web/html:/var/www/html rhel7:web
cd /tmp/web/html/
echo '<h1>www.westos.com</h1>' >index.html
curl 172.17.0.3
基础服务封装
vim /mnt/Dockerfile
FROM rhel7:v1
MAINTAINER haitangyijiu@163.com
ENV HOSTNAME server2
EXPOSE 22
RUN yum install -y openssh-server openssh-clients && ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:westos | chpasswd
CMD ["/usr/sbin/sshd","-D"]
docker build -t rhel7:v3 /mnt/
查看下地址
docker container start ssh
docker container attach ssh
echo root:westos | chpasswd
docker run -d --name ssh -p 2222:22 rhel7:v3
到此ok,客户机ssh宿主机2222端口,不是宿主机测试,
ssh -l root -p 2222 172.25.51.1
iptables -t nat -nL
多个容器服务的封装
docker run -it --name vm1 rhel7:v1
配置yum源
vi /etc/yum.repos.d/yum.repo
[yum]
name=rhel7.3
baseurl=http://172.25.51.250/rhel7.3
gpgcheck=0
[docker]
name=docker
baseurl=http://172.25.51.250/docker
gpgcheck=0
yum repolist 查看下
打开另一个shell或者ctrl q+p后台运行容器
[root@server1 ~]# vim Dockerfile
FROM rhel7:v1
MAINTAINER 930372286@qq.com
ENV HOSTNAME server3
EXPOSE 22 80
COPY docker.repo /etc/yum.repos.d/docker.repo
RUN yum install -y openssh-server openssh-clients httpd supervisor && ssh-keygen -q -t rsa -f /etc/ssh/ssh_host_rsa_key -N "" && ssh-keygen -q -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key -N "" && ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && echo root:westos | chpasswd
VOLUME ["/var/www/html"]
COPY supervisord.conf /etc/supervisord.conf
CMD ["/usr/bin/supervisord"]
[root@server1 ~]# vim supervisord.conf
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:httpd]
command=/usr/sbin/httpd
vim docker.repo
[docker]
name=docker
baseurl=http://172.25.51.250/docker
gpgcheck=0
[root@server1 ~]# docker build -t rhel7:v4 .
[root@server1 ~]# docker images ##查看下
[root@server1 ~]# docker history rhel7:v4
[root@server1 ~]# docker run -d --name apache -v /opt/web:/var/www/html rhel7:v4
测试:curl 172.17.0.3
ssh 172.17.0.3
九.docker私有仓库
[root@server1 ~]# docker load -i registry-2.3.1.tar
[root@server1 ~]# docker images
[root@server1 ~]# docker run -d --name registry -p 5000:5000 -v /opt/registry:/var/lib/registry registry:2.3.1 ##端口映射5000端口,后台运行
[root@server1 ~]# docker tag nginx localhost:5000/nginx:latest ##命名
[root@server1 ~]# docker push localhost:5000/nginx:latest ##推送
[root@server1 ~]# docker rmi localhost:5000/nginx:latest ##删除ocalhost:5000/nginx:latest
[root@server1 ~]# docker rmi nginx 删除nginx
[root@server1 ~]# docker pull localhost:5000/nginx:latest ##下载
[root@server1 ~]# docker tag localhost:5000/nginx:latest nginx ##重命名
[root@server1 ~]# docker rmi localhost:5000/nginx ##再次删除
仓库添加认证,证书自己的
解析
[root@server1 ~]# vim /etc/hosts
172.25.51.1 server1 westos.org
[root@server1 ~]# mkdir certs
[root@server1 ~]# cd certs/
[root@server1 certs]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout westos.org.key -x509 -days 365 -out westos.org.crt
此时会在当前目录生成证书和钥匙
清空上个实验的数据
[root@server1 certs]# rm -fr /opt/registry/*
[root@server1 ~]# docker stop 6c7736f7eea0
[root@server1 ~]# docker rm 6c7736f7eea0
[root@server1 ~]# docker run -d --name registry --restart=always -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/westos.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/westos.org.key -p 443:443 -v /opt/registry/:/var/lib/registry registry:2.3.1
[root@server1 ~]# docker ps -a ##查看下,确保Up状态
剩下的操作如下:
[root@server1 ~]# cd /etc/docker/
[root@server1 docker]# mkdir -p certs.d/westos.org
[root@server1 docker]# cd certs.d/westos.org/
[root@server1 westos.org]# cp ~/certs/westos.org.crt ca.crt
[root@server1 westos.org]# ls
[root@server1 westos.org]# docker tag ubuntu:latest westos.org/ubuntu
[root@server1 westos.org]# docker push westos.org/ubuntu ##推送
[root@server1 westos.org]# docker rmi westos.org/ubuntu:latest ##删除镜像
另开一台虚拟机server2安装启动docker
[root@server2 ~]# cd /etc/docker/
[root@server2 docker]# mkdir -p certs.d/westos.org
[root@server2 docker]# cd certs.d/westos.org/
[root@server2 westos.org]# scp 172.25.51.1:/etc/docker/certs.d/westos.org/ca.crt . ##将server1的/etc/docker/certs.d/westos.org/ca.crt 复制到server2的/etc/docker/certs.d/westos.org/下边
Server2拉取试试:注意解析问题,否则报错
[root@server2 ~]# docker images ##空的
[root@server2 ~]# docker pull westos.org/ubuntu ##拉取
[root@server2 ~]# curl --cacert /etc/docker/certs.d/westos.org/ca.crt https://westos.org/v2/_catalog ##查看信息
{"repositories":["ubuntu"]}
优化一下:不需要证书添加浏览器:
[root@server2 ~]# cd /etc/pki/ca-trust/source/anchors/
[root@server2 anchors]# ls
[root@server2 anchors]# cp /etc/docker/certs.d/westos.org/ca.crt /etc/pki/ca-trust/source/anchors/
[root@server2 anchors]# ls
ca.crt
[root@server2 anchors]# mv ca.crt westos.org.crt
[root@server2 anchors]# ls
westos.org.crt
[root@server2 anchors]# update-ca-trust ##更新信任证书
[root@server2 anchors]# curl https://westos.org/v2/_catalog
{"repositories":["ubuntu"]}
##curl验证
[root@server1 ~]# mkdir auth
[root@server1 ~]# cd auth/
[root@server1 auth]# docker run --entrypoint htpasswd registry:2.3.1 -Bbn admin westos >htpasswd ##添加人证名和密码,多个追加
[root@server1 auth]# cat htpasswd
admin:$2y$05$Js9sBiZYlzMLCV5HzyqRP.n1Y5KO/fd4XCoHC8ofNq1l/KsTPqgCC
清下环境,删除上个实验的镜像:
[root@server1 auth]# docker stop 184
[root@server1 auth]# docker rm 184
[root@server1 ~]# docker run -d --name registry --restart=always -v /root/certs:/certs -v /root/auth:/auth -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/westos.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/westos.org.key -e REGISTRY_AUTH=htpasswd -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -p 443:443 -v /opt/registry/:/var/lib/registry registry:2.3.16557d24432b8c2f5fe09ed9b5b46fec952d64d98c5e4435abca24bc3de459c89
[root@server1 auth]# pwd
/root/auth
测试:
[root@server2 ~]# curl -u admin:westos https://westos.org/v2/_catalog
{"repositories":["ubuntu"]}
[root@server2 ~]# docker login westos.org
Username: admin
Password: westos ##隐藏
Login Succeeded
登陆成功就可以pull拉取镜像了
[root@server2 ~]# docker pull westos.org/ubuntu
密码文件在家目录下
/root/.docker
十.cgroup管理
新开一个rhel6.5的虚拟机host4
[root@host4 ~]# yum install libcgroup.x86_64 -y ##安装这个,人生苦短,不要追问这是什么
[root@host4 ~]# /etc/init.d/cgconfig start ##安装完成后启动
这个时候cd /cgroup/ ,ls查看会有些目录文件
内存的控制
[root@host4 cgroup]# vim /etc/cgconfig.conf
27 group x1 {
28 memory {
29 memory.limit_in_bytes = 104857600;
30 }
31 }
[root@host4 cgroup]# /etc/init.d/cgconfig restart
实验:
cd /dev/shm/ 进入内存
dd if=/dev/zero of=bigfile bs=1M count=200 ##截取200M全在内存里
rm -fr bigfile
cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=200
这个时候会先内存大概用了100M其他由swap去存了
[root@host4 shm]# vim /etc/cgconfig.conf
27 group x1 {
28 memory {
29 memory.limit_in_bytes = 104857600;
30 memory.memsw.limit_in_bytes = 104857600; 内存和交换分区总共的限制
31 }
32 }
重启/etc/init.d/cgconfig restart
cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=200
会发现写不进去
限制用户lel
[root@host4 shm]# vim /etc/cgrules.conf
lel memory x1/
[root@host4 shm]# /etc/init.d/cgred restart
对于lel用户来说内存和swap只能用100M多了不行
[lel@host4 shm]$ dd if=/dev/zero of=bigfile bs=1M count=200
Killed
[lel@host4 shm]$ dd if=/dev/zero of=bigfile bs=1M count=50
50+0 records in
50+0 records out
52428800 bytes (52 MB) copied, 0.035936 s, 1.5 GB/s
cpu管理工具
[root@server1 x2]# cd /sys/devices/system/cpu/
[root@server1 cpu]# ls
cpu0 cpu1 cpufreq cpuidle kernel_max offline online possible present
[root@server1 cpu]# cd cpu1 ##cpu0是默认的,无法更改
[root@server1 cpu1]# ls
cache online crash_notes node0 topology
[root@server1 cpu1]# cat online ##显示cpu信息
1
[root@server1 cpu1]# echo 0 > online ##更改0挂掉,1上线
[root@server1 ~]# killall dd ##删除所有dd进程
cpu1再打开,top查看
blkio
[root@server1 blkio]# ll /dev/vda
brw-rw---- 1 root disk 252, 0 May 8 15:11 /dev/vda ##252,0 是vda的信息
[root@server1 blkio]# vim /etc/cgconfig.conf
group x3 {
blkio {
blkio.throttle.read_bps_device = "252:0 1000000"; ##限速1000k
}
}
[root@server1 ~]# yum install iotop -y ##查看速度的软件
[root@server1 ~]# cgexec -g blkio:x3 dd if=/dev/vda of=/dev/null & ##执行
[1] 1306
[root@server1 ~]# iotop ##查看
freezer
[root@server1 freezer]# vim /etc/cgconfig.conf
group x4 {
freezer {} ##冻结
}
[root@server1 freezer]# cd
[root@server1 ~]# /etc/init.d/cgconfig restart
Stopping cgconfig service: [ OK ]
Starting cgconfig service: [ OK ]
[root@server1 ~]# cd -
/cgroup/freezer
[root@server1 freezer]# cd x4/
[root@server1 x4]# cat tasks ##管理进程的文件
[root@server1 x4]# cgexec -g blkio:x3 dd if=/dev/vda of=/dev/null &
[1] 1336
[root@server1 x4]# echo 1336 > tasks ##导入(用的是速度查询的进程)
[root@server1 x4]# cat freezer.state ##运行状态
THAWED
[root@server1 x4]# echo FROZEN > freezer.state ##冻结状态
[root@server1 x4]# iotop
[root@server1 x4]# echo THAWED > freezer.state ##正常运行
[root@server1 x4]# iotop
十一.docker的安全
[root@server1 ~]#docker run -it --name vm1 ubuntu bash
root@6d24f44bd014:/# ip addr del 172.17.0.2/16 dev eth0
如下图,操作被禁止
放权docker run -it –privileged=true –name vm1 ubuntu bash
[root@server1 ~]# docker stop vm1
[root@server1 ~]# docker rm vm1
[root@server1 ~]# docker run -it --privileged=true --name vm1 ubuntu bash
root@ebd5e1aaa795:/# ip addr del 172.17.0.2/16 dev eth0
设置容器白名单:–cap-add
–privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时 Docker 提供了权限白名单的机制,使用–cap-add 添加必要的权限。
docker run -it --cap-add=NET_ADMIN --name vm1 ubuntu
bash
docker inspect -f {{.HostConfig.Privileged}} vm1
false
docker inspect -f {{.HostConfig.CapAdd}} vm1
{[NET_ADMIN]}
十二.docker+apache+nginx+haproxy实际上compose实现负载均衡,docker自身就可以负载均衡,最后一个实验说明
如果你没有母镜像需要先封装一个apache镜像,方法如下
docker run --name [name] -it rhel7 bash
cd /etc/yum.repos.d/
vim yum .repo
[yum]
name=rhel7.3
baseurl=http://172.25.10.250/rhel7.3
gpgcheck=0
rm -fr redhat.repo
ctrl p + q
rpmdb --rebuilddb
删除所有正在运行的容器
[root@server1 ~]# docker kill `docker ps -aq`
[root@server1 ~]# docker rm `docker ps -aq`
[root@server1 ~]# docker ps -a
这里需要一个二进制可执行命令,如下图
[root@server1 ~]# mv docker-compose-Linux-x86_64 /usr/local/bin/
[root@server1 ~]# ln -s /usr/local/bin/docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
[root@server1 ~]# chmod +x /usr/local/bin/docker-compose
配置文件
[root@server1 ~]# mkdir compose
[root@server1 ~]# cd compose/
[root@server1 compose]# vim docker-compose.yml
apache:
build: ./web
expose:
- 80
nginx:
image: nginx
expose:
- 80
haproxy:
image: haproxy
volumes:
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
links:
- apache
- nginx
ports:
- "80:80"
expose:
- "80"
[root@server1 compose]# mkdir web
[root@server1 compose]# cd web/
[root@server1 web]# pwd
/root/compose/web
[root@server1 web]# vim Dockerfile
FROM rhel7:v1 ##确保有rhel7:v1
MAINTAINER 1904168391@qq.com
ENV HOSTNAME apache
EXPOSE 80
RUN yum -y install httpd
COPY index.html /var/www/html/index.html
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
[root@server1 web]# echo "hello,world" >index.html
[root@server1 web]# ls
Dockerfile index.html
[root@server1 web]# cd ..
[root@server1 compose]# pwd
/root/compose
[root@server1 compose]# mkdir haproxy
[root@server1 compose]# cd haproxy/
[root@server1 haproxy]# vim haproxy.cfg
global
log 127.0.0.1 local0
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
stats uri /status
frontend balancer
bind 0.0.0.0:80
default_backend web_backends
backend web_backends
balance roundrobin
server web1 apache:80 check
server web2 nginx:80 check
[root@server1 compose]# mkdir web
[root@server1 compose]# cd web/
[root@server1 web]# pwd
/root/compose/web
[root@server1 web]# vim Dockerfile
[root@server1 web]#
[root@server1 compose]# docker-compose up ##注意工作目录在那,重要
报错了,docker仓库没有haproxy镜像会去外网找,而网不通,我们需要把haproxy.tar上传仓库
[root@server1 ~]# docker load -i haproxy.tar
再次执行
[root@server1 compose]# docker-compose up
Ctrl +c
[root@server1 compose]# docker-compose start
这个时候,浏览器可以查看了
http://172.25.51.1/status ##查看haproxy的状态
http://172.25.51.1/ ##apache和nginx轮询
或者curl 172.25.51.1
十四.swarm 高可用
准备两台7.3docker 开启,时间同步 server2,server3
load nginx镜像
leader 为server1
[root@server2 ~]# docker load -i nginx.tar
时间是一样的,不一样的话需要时间同步
[root@server1 ~]# docker swarm init ##初始化
复制图中黑色代码去server2和server3执行,另外注意,如果server1 eth0多个ip的话可能报错
Server2:
Server3:
Server1:
[root@server1 ~]# docker service create --name web --publish 80:80 --replicas 4 nginx
[root@server1 ~]# docker service ps web ##查看一下
这个时候浏览器不太明显,我们加个监控
[root@server1 ~]# docker load -i visualizer.tar
[root@server1 ~]# docker service create --name=viz --publish=8080:8080/tcp --constraint=node.role==manager --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock dockersamples/visualizer
实验效果是某一个坏了,转移其他
浏览器:
http://172.25.51.1:8080/
多开几个:
[root@server1 ~]# docker service scale web=9 ##9个
十五.flask框架,需要python环境
封装一个apache
更新httpd
封装一个apache
方法如下:
vim /mnt/Dockerfile
FROM rhel7:v1
MAINTAINER 1904168391@qq.com
ENV HOSTNAME apache
EXPOSE 80
RUN yum -y install httpd
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
docker build -t rhel7:v2 /mnt/
docker save rhel7:v2 >rhel7.tar
scp rhel7.tar root@172.25.51.2:~
scp rhel7.tar root@172.25.51.3:~
[root@server1 ~]# docker save rhel:v2 >/opt/rhel7.tar ##导出来分发server2和server3
scp rhel7.tar root@172.25.51.2:~
scp rhel7.tar root@172.25.51.3:~
[root@server1 compose]# docker service update --update-parallelism 2 --update-delay 2s --update-failure-action rollback --image rhel7:v2 web
##--update-parallelism 2 (同一时刻)更新的数量默认0,--update-delay 2s更新时间间隔默认0s,--update-failure-action rollback 更新失败从头再来,回滚,还有其他模式参考docker service update --help
[root@server1 ~]# docker load -i flask.tar
[root@server1 ~]# vim test.py
[root@server1 ~]# cat -n test.py
1 from flask import Flask
2
3 import os
4
5 app = Flask(__name__)
6
7 @app.route("/")
8
9 def env():
10 return os.environ["HOSTNAME"]
11
12 app.run(host="0.0.0.0")
[root@server1 ~]# docker run -d --name test -v /root/test.py:/test.py python:flask python /test.py
[root@server1 ~]# curl 172.17.0.6:5000 ##会显示主机id
当出现这个错误多半是test.py文件有错
May 11 08:51:56 server1 dockerd: time=”2018-05-11T08:51:56.064730380-04:00” level=error msg=”Error in responding to bulk sync from node 172.25.51.2: failed to send a TCP message during bulk sync: dial tcp 172.25.51.2:7946: getsockopt: no route to host”
关闭删除test容器
[root@server1 ~]# docker stop test
[root@server1 ~]# docker rm test
[root@server1 ~]# docker run -it --name test python:flask
Python 2.7.11 (default, Mar 24 2016, 09:47:20)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> ctrl + p +q
[root@server1 ~]# docker container cp test.py test:/ ##把/root/test.py复制到容器的根目录下
[root@server1 ~]# docker container exec test ls / ##非必要步骤,查看容器test根下是否有test.py肯定有的
[root@server1 ~]# docker container commit test python:demo ##提交test容器重命名
[root@server1 ~]# docker save python:demo > demo.tar ##导出容器test命名后的容器
[root@server1 ~]# scp demo.tar root@172.25.51.2:~ ##分发给server2
[root@server1 ~]# scp demo.tar root@172.25.51.3:~ ##分发给server3
[root@server1 ~]# docker load -i demo.tar
[root@server2 ~]# docker load -i demo.tar
[root@server3 ~]# docker load -i demo.tar
这个过程中可能存在存储不足或者没有这个文件/var/lib/docker/tmp/docker-import-376966965/repositories,清理下挂载的容器,du -sh /* 可用空间可能过少,鄙人把所有的都干掉了docker kill | rm`docker ps -aq`,当然剩下的高可用你也可以干掉(docker service rm [id] )
其他两个就不截图了
[root@server1 compose]# docker service create --replicas 3 --publish 80:5000 --name web python:demo python /test.py
实验:
[kiosk@foundation51 Desktop]$ for i in {1..6}; do curl -w "\n" 172.25.51.1; done
已经实现了负载均衡8eaf5ddfdc80 对应的172.25.51.1,efd6def70def 对应172.25.51.2, 3f7da2e20bfb 对应172.25.51.3
换种方式
[root@server1 ~]# docker service rm web ##删除上边实验的web
[root@server1 ~]# docker service rm viz
[root@server1 ~]# docker service ls ##空的
[root@server1 ~]# docker service create --name www -p 80:80 --replicas 3 nginx
[root@server1 ~]# docker service ls ##只有一个容器www
[root@server1 ~]# docker service ps www ###在三台主机上都有nginx
curl 172.25.51.1
访问都是nginx默认页,挂载让实验更明显些
在server1 root家目录下新建web
[root@server1 ~]# mkdir web
[root@server1 ~]# echo server1 > web/index.html
在server2 root家目录下新建web
[root@server2 ~]# mkdir web
[root@server2 ~]# echo server2 > web/index.html
在server3 root家目录下新建web
[root@server3 ~]# mkdir web
[root@server2 ~]# echo server3 > web/index.html
[root@server1 ~]# docker service update --mount-add type=bind,source=/root/web,target=/usr/share/nginx/html www ##更新,你也可以删除重建
实验测试:
curl 172.25.51.1