一、Docker是什么
1、简介
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux机器或Windows机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
物理机必须要内核3.8以上才能支持docker
2、特点
-
服务彼此之间相互独立(服务之间的解耦)
-
服务可以灵活迁移(Docker引擎 docker-ce)
耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。
解耦就是用数学方法将两种运动分离开来处理问题,常用解耦方法就是忽略或简化对所研究问题影响较小的一种运动,只分析主要的运动。(便于管理,防止数据过多的积累在一个文件中)
3、与虚拟机的区别
虚拟机容量占用大,容器不需要装系统,占用容量小
虚拟机安全,容器不安全(共享内核资源),攻击一个内核,其他全部瘫痪,可隔开,做资源控制
特性 | 虚拟机 | 容器 |
---|---|---|
隔离级别 | 操作系统级 | 进程级 |
系统策略 | Hypervisor | CGroups |
系统资源 | 5~15% | 0~5% |
启动时间 | 分钟级 | 秒级 |
镜像存储 | GB-TB | KB-MB |
群集规模 | 上百 | 上万 |
高可用策略 | 备份、容灾、迁移 | 弹性、负载、动态 |
二、Docker三要素
●镜像:一个面向Docker容器引擎的只读模板
●容器:从镜像创建的运行实例
●仓库:集中保存镜像的地方;分公有和私有仓库
三、Docker基础命令
1、docker容器和本地互传文件
本地向docker容器传送文件
docker cp 本机保存文件的全路径 container_id:docker容器内的文件全路径
docker cp index.jsp 容器id:/usr/local/tomcat/webapps/ROOT
docker容器向本机传送文件
docker cp container_id:docker容器内的文件全路径 本机保存文件的全路径
docker cp [4a2f08d2c1f8:/data1/configure.txt](http://4a2f08d2c1f8/data1/configure.txt) E:\PHP\configure.txt
2、镜像操作
●查看docker版本:docker version
●搜索nginx镜像(公有仓库):docker search nginx
●下载nginx镜像:docker pull nginx;下载后存放在/var/lib/docker
●查看镜像列表
docker images #查看下载镜像信息列表 docker inspect nginx:latest #获取镜像详细信息
展示信息说明:
-
REPOSITORY:镜像所在的仓库名称
-
TAG:镜像标签
-
IMAGE ID:镜像ID
-
CREATED:镜像的创建日期(不是获取该镜像的日期)
-
SIZE:镜像大小 这些镜像都是存储在Docker宿主机的/var/lib/docker目录下
●为镜像添加新标签
docker tag nginx:latest nginx:web
●两种方式删除镜像
注意:删除某一个镜像时,只要有容器在使用某一个镜像,必须先删除容器,才能删除镜像。
(1)删除单个镜像
docker rmi IMAGE_NAME_OR_ID
其中,IMAGE_NAME_OR_ID
是要删除的镜像的名称或ID。例如,要删除名为my_image
的镜像,可以运行以下命令:
docker rmi my_image
(2)删除镜像id
注意:只有当镜像id对应标签仅剩一个时,才能使用镜像id的方式进行删除;否则出现如下报错
或者也可以在最后加上-f选项,一次性删除【强制性删除】
docker rmi -f IMAGE_NAME_OR_ID docker rmi -f my_image
(3)一次性删除所有镜像
docker rmi -f $(docker images -aq)
请注意,删除所有镜像将不可逆转,并且将删除系统中所有镜像,包括中间镜像。
●保存导出镜像并命名为nginx,存到/opt目录下
docker save -o /opt/nginx.tar nginx:latest
●载入镜像
docker load < /opt/nginx
docker load -i 镜像保存文件位置
3、容器操作
●创建容器
docker create -it nginx:latest /bin/bash
-
-i:让容器的标准输入保持打开
-
-t:让Docker分配一个伪终端
●查看容器运行状态
docker ps -a -a:列出所有的容器,包括未运行的容器
Created:已创建; Up:运行中
●启动执行命令查看系统根目录
一般启动容器流程:
(1)docker pull centos --下载镜像
(2)docker create -it centos:latest /bin/bash
(3)docker start d4a99affa677
通过run命令启动:(先去查找现有的镜像中有没有,没有先下载,再启动)
docker run centos:latest /usr/bin/bash -c ls /
执行完成会关闭,状态是Exited(容器可以做一次性的处理,处理完就释放资源,做到了最小成本控制)
容器持续在后台执行(通过执行死循环)
docker run -d centos:latest /bin/bash -c "while true;do echo hello;done"
使用 docker logs 容器id 命令,可以查看容器内的标准输出
●终止容器运行
docker stop 0401f589d5ed(CONTAINER ID)
●进入容器(该容器一定要在Up状态)
docker exec -it 0f0ba9207b21 /bin/bash
●导出容器
docker export cc4a8b1d428c > /opt/nginx_bak
●导入容器(会生成镜像,而不会创建容器)
cat /opt/nginx_bak | docker import - nginx:bak
●删除容器(容器必须为停止状态)
docker stop e885c37fb2eb
docker rm e885c37fb2eb
●批量删除容器
docker ps -a | awk '{print "docker rm "$1}' | bash
docker ps -a | sed -n '2,$p' | awk '{print "docker rm "$1}' | bash
四、Docker镜像的构建
1、Docker镜像的分层
自下而上制作镜像
1.from 后面跟基础镜像
2.add脚本
3.挂载共享空间 数据卷
4.CMD命令执行脚本
2、基于已有镜像容器创建
1、docker create -it 原镜像名 /bin/bash
2、docker commit -m "new" -a "chen" 已有容器id 新镜像名:标签
-m:说明信息
-a:作者信息
-p:生成过程中停止容器的运行
docker images | grep 标签
3、基于本地模板创建
1.导入本地镜像debian-7.0-x86-minimal.tar.gz
2.cat debian-7.0-x86-minimal.tar.gz | docker import - 镜像名:标签
3.docker images | grep 标签
4、基于Dockerfile创建
●Dockerfile是由一组指令组成的文件
●Dockerfile结构四部分
基础镜像信息
维护者信息
镜像操作指令
容器启动时执行指令
●Dockerfile每行支持一条指令,每条指令可携带多个参数,支持使用以“#”号开头的注释
●Dockerfile操作指令
指令 | 含义 |
---|---|
FROM 镜像 | 指定新镜像所基于的镜像,第一条指令必须为FROM指令,每创建一个镜像就需要一条FROM指令。 |
MAINTAINER 名字 | 说明新镜像的维护人信息 |
RUN命令 | 在所基于的镜像上执行命令,并提交到新的镜像中 |
CMD [“要运行的程序”,“参数1”,“参数2”] | 指令启动容器时要运行的命令或者脚本,Dockerfile只能有一条CMD命令,如果指定多条则只能最后一条被执行 |
EXPOSE 端口号 | 指定新镜像加载到Docker时要开启的端口(EXPOSE暴露的是容器内部端口,需要再映射到一个外部端口上) |
ENV 环境变量 变量值 | 设置一个环境变量的值,会被后面的RUN使用 |
ADD 源文件/目录 目标文件/目录 | 将源文件复制到目标文件(与COPY的区别是将本地tar文件解压到镜像中) |
COPY 源文件/目录 目标文件/目录 | 将本地主机上的文件/目录复制到目标地点,源文件/目录要与Dockerfile在相同的目录中 |
VOLUME [“目录”] | 在容器中创建一个挂载点(VOLUME是宿主机中的某一个目录挂载到容器中) |
USER 用户名/UID | 指定运行容器时的用户 |
WORKDIR 路径 | 为后续的RUN、CMD、ENTRYPOINT指定工作目录(WORKDIR类似于cd,但是只切换目录一次,后续的RUN命令就可以写相对路径了) |
ONBUILD 命令 | 指定所生成的镜像作为一个基础镜像时所要运行的命令 |
HEALTHCHECK | 健康检查 |
CMD指令可以指定容器启动时默认执行的命令,但它可以被docker run命令的参数覆盖掉。
ENTRYPOINT 指令和CMD类似,它也是用户指定容器启动时要执行的命令,但如果dockerfile中也有CMD指令,CMD中的参数会被附加到ENTRYPOINT指令的后面。 如果这时docker run命令带了参数,这个参数会覆盖掉CMD指令的参数,并也会附加到ENTRYPOINT 指令的后面。
这样当容器启动后,会执行ENTRYPOINT 指令的参数部分。
可以看出,相对来说ENTRYPOINT指令优先级更高。
对于目录而言,COPY 和 ADD 命令具有相同的特点:只复制目录中的内容而不包含目录自身
CMD和ENTRYPOINT的区别
CMD指令可以指定容器启动时默认执行的命令,但它可以被docker run命令的参数覆盖掉。
ENTRYPOINT 指令和CMD类似,它也是用户指定容器启动时要执行的命令,但如果dockerfile中也有CMD指令,CMD中的参数会被附加到ENTRYPOINT指令的后面。 如果这时docker run命令带了参数,这个参数会覆盖掉CMD指令的参数,并也会附加到ENTRYPOINT 指令的后面。
这样当容器启动后,会执行ENTRYPOINT 指令的参数部分。
可以看出,相对来说ENTRYPOINT指令优先级更高。
优先级:ENTRYPOINT>CMD>docker run
Dockerfile文件生成apache镜像实例:
1.vim Dockerfile (Dockerfile名字不可更改)
#新镜像基于的基础镜像(基础镜像未下载会先下载)
FROM centos:7
#维护镜像的用户信息
MAINTAINER This is chen
#镜像操作指令安装apache软件
RUN yum -y update
RUN yum -y install httpd
#开启80端口
EXPOSE 80
#复制网址首页文件
ADD index.html /var/www/html/index.html
#将执行脚本复制到镜像中
ADD run.sh /run.sh
RUN chmod 755 /run.sh
#启动容器时执行脚本
CMD ["/run.sh"]
此处注意一个细节:每加载一步会生成一个临时的容器,加载完后会删除
2.vim run.sh #和Dockerfile文件位于相同目录下
#!/bin/bash
rm -rf /run/httpd/* #删除进程文件
exec /usr/sbin/apachectl -D FOREGROUND #启动apache
3.vim index.html #编辑首页文件
<h1>this is web</h1>
4.生成镜像
docker build -t httpd:test . (注意别忘了末尾有".")
5.新镜像运行容器
docker run -d -p 1216:80 httpd:test
-p:映射到宿主机指定端口
-P:映射到宿主机随机端口
6.测试容器是否成功运行
五、Docker的四种网络模式
https://blog.csdn.net/lilygg/article/details/88616218
1、实现原理
Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。
2、网络详解
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f9ad4320a5f2 bridge bridge local
894917639bf3 host host local
39da54945dad none null local
#安装docker时,它会自动创建三个网络,bridge(创建容器默认连接到该网络)、none和host
Docker网络模式 | 配置 | 说明 |
---|---|---|
host模式 | –net=host | 容器和宿主机共享Network namespace。 |
container模式 | –net=container:NAME_or_ID | 容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。 |
none模式 | –net=none | 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。 |
bridge模式 | –net=bridge | (默认为该模式) |
1)、host模式
容器将不会获得一个独立的Network Namespace(网络命令空间),而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口,(也就是说如果容器是个web,那直接访问宿主机:端口,不需要做NAT转换,跟在宿主机跑web一样。容器中除了网络,其他都还是隔离的。)
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。
2)、Container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信.
3)、none模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。该模式关闭了容器的网络功能
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
4)、bridge模式
此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及iptables nat表配置与宿主机通信
##当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
bridge模式是docker的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。
3、自定义网络如何配置
#创建容器时默认使用的是桥接模式,但是使用bridge不支持为容器指定IP
[root@localhost ~]# docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:7 /bin/bash
20dc45293929f81013a60391bef2626f581a8d3d4f29b8a87ac8b1f9b585ab2a
docker: Error response from daemon: user specified IP address is supported on user defined networks only. #提示想要为容器指定IP只能在用户自定义的网络中才行
#配置自定义固定IP
[root@localhost ~]# docker network create --subnet=172.31.0.0/24 test
#创建自定义网络test
[root@localhost ~]# docker run -itd --name web1 --net test --ip 172.31.0.10 centos:7 /bin/bash
六、Docker数据管理
1、为什么要进行数据管理操作
●方便查看容器内产生的数据
●多容器间实现数据共享
例如:需要给多个容器中的网站站点上传网页内容时,可以高效的部署网页。
2、两种管理方式
●数据卷
数据卷是容器和宿主之间的数据共享
●数据卷容器
数据卷容器是容器和容器之间的数据共享
3、数据卷操作实例
1.将宿主机目录中的/var/www挂载到容器中的/data1中(如果目录不存在都会自动创建)
docker run -v /var/[www:/data1](http://www/data1) --name web1 -it centos:7 /bin/bash
2.在容器中/data1目录下创建文件进行测试
[root@bb58030283e7 /]# cd /data1/
[root@bb58030283e7 data1]# touch 123.txt
3.回到宿主机/var/www查看
[root@node1 ~]# cd /var/www/
[root@node1 www]# ls
123.txt
4、数据卷容器操作实例
1.创建数据卷容器web10
docker run --name web10 -v /data1 -v /data2 -it centos:7 /bin/bash
2.新容器web100挂载数据卷容器web10
docker run -it --volumes-from web10 --name web100 centos:7 /bin/bash
(web100容器会自动关联web10容器中的数据卷)
3.在新容器web100的/data1中创建文件进行测试
[root@2ad42960c2aa data1]# cd /data1/
[root@2ad42960c2aa data1]# ls
[root@2ad42960c2aa data1]# touch 1.txt
4.回到数据卷容器web10的/data1中查看
[root@b10f5d5ae9d5 /]# cd data1/
[root@b10f5d5ae9d5 data1]# ls
1.txt
5、私有仓库建立步骤
1、下载registry镜像
2、客户端设置daemon.json文件,指定私有仓库位置;
"insecure-registries": ["14.0.0.10:5000"],
3、生成registry容器,开放5000端口
docker run -d -p 5000:5000 -v /[registry:/data/registry](http://registry/data/registry) registry
4、给要上传的镜像打上标签
5、上传镜像
6、获取私有仓库列表查看是否上传成功
7、测试私有仓库下载镜像
#–privileged 让容器内的root拥有真正的root权限。否则,container内的root只是外部的一个普通用户权限。
[root@localhost systemctl]# docker run --privileged -it -v /sys/fs/[cgroup:/sys/fs/cgroup:ro](http://cgroup/sys/fs/cgroup:ro)
七、Docker Compose容器编排
1、Docker Compose简介
●一个定义及运行多个Docker容器的工具
●Docker Compose非常适合组合使用多个容器进行开发的场景
3.2Docker Compose文件格式及编写注意事项
●YAML是一种标记语言很直观的数据序列化格式
●文件格式及编写注意事项
不支持制表符tab键缩进,需要使用空格缩进
通常开头缩进2个空格
字符后缩进1个空格,如冒号、逗号、横杆
用#号注释
如果包含特殊字符用单引号引起来
布尔值必须用引号括起来
2、Compose命令说明
●基本的使用格式
docker-compose [options] [COMMAND] [ARGS]
●docker-compose选项
--verbose 输出更多调试信息
--version 打印版本并退出
-f,--file FILE 使用特定的compose模板文件,默认为docker-compose.yml
-p,--project-name NAME 指定项目名称,默认使用目录名称
3、compose部署
#以docker-ce为基础
上传docker-compose命令包到/usr/local/bin目录下
chmod +x /usr/local/bin/docker-compose
#在/root目录下创建compose_tomcat目录
[root@localhost ~]# mkdir compose_tomcat/
docker-compose.yml配置文件详解:
https://www.jianshu.com/p/2217cfed29d7
一份标准配置文件应该包含 version、services、networks 三大部分,其中最关键的就是 services 和 networks 两个部分
[root@localhost compose_tomcat]# vim docker-compose.yml
version: '3'
services:
tomcat:
hostname: tomcat
build: #基于一份 Dockerfile创建容器
context: ./tomcat
dockerfile: Dockerfile
ports:
- 8080:8080
networks:
- tomcat
volumes:
- ./[wwwroot:/usr/local/tomcat/webapps/ROOT](http://wwwroot/usr/local/tomcat/webapps/ROOT) #注意tomcat站点位置
nginx:
hostname: nginx
build:
context: ./nginx
dockerfile: Dockerfile
ports:
- 1216:80
- 1226:443
networks:
- nginx
volumes:
- ./[nginxroot:/usr/local/nginx/html](http://nginxroot/usr/local/nginx/html)
networks:
tomcat:
nginx:
[root@localhost compose_tomcat]# docker-compose -f docker-compose.yml up -d
八、Harbor私有仓库
Harbor私有仓库部署与管理
Harbor的每个组件都是以Docker容器的形式构建的,使用docker-compose来对它进行部署
Docker harbor有可视化的web管理界面,可以方便管理Docker镜像,又提供了多个项目的镜像权限管理及控制功能
使用 Docker 命令在本地通过 127.0.0.1 来登录和推送镜像
默认情况下,Register 服务器在端口 80 上侦听。
//登录
docker login -u admin -p Harbor12345 [http://127.0.0.1](http://127.0.0.1/)
//下载镜像进行测试 下载镜像进行测试
docker pull nginx
//镜像打标签 (网页上也会有提示、模板)
docker tag nginx 127.0.0.1/myimages/nginx:v1
//上传镜像到 上传镜像到 Harbor
docker push 127.0.0.1/myimages/nginx:v1
使用Harbor仓库时遇到的故障:
以上操作都是在 Harbor 服务器本地操作。如果其他客户端上传镜像到 Harbor,就会报
如下错误。
出现这问题的原因 Docker Registry 交互默认使用的是 HTTPS,但是搭建私有镜像默认使用的是 HTTP 服务,所以与私有镜像交互时出现以下错误。
[root@localhost ~]# docker login -u admin -p Harbor12345 [http://14.0.0.20](http://14.0.0.20/)
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Error response from daemon: Get https://14.0.0.20/v2/: dial tcp 14.0.0.20:443: connect: connection refused
如何解决:
[root@client ~]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry 14.0.0.20 -- containerd=/run/containerd/containerd.sock
[root@client ~]# systemctl daemon-reload
[root@client ~]# systemctl restart docker
要更改 Harbor 的配置文件时,请先停止现有的 Harbor 实例并更新 Harbor.cfg;然后运行 prepare 脚本来填充配置;最后重新创建并启动 Harbor 的实例。
1.停止现有的 Harbor 实例
docker-compose down -v
[root@localhost harbor]# pwd
/usr/local/harbor
[root@localhost harbor]# ls
common docker-compose.yml harbor.v1.2.2.tar.gz NOTICE
docker-compose.clair.yml harbor_1_1_0_template install.sh prepare
docker-compose.notary.yml harbor.cfg LICENSE upgrade
2.更新 Harbor.cfg
[root@localhost harbor]# vim Harbor.cfg
3.运行 prepare 脚本来填充配置
[root@localhost harbor]# ./prepare
4.重新创建并启动 Harbor 的实例
如果出现如下报错: docker-compose up -d
九、Docker consul容器服务更新与发现
1、consul的介绍
由HashiCorp公司使用go语言开发的一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件(开源)。
主要特点:
服务发现及配置;
支持健康检查,并且运行HTTP、GTPC和DNS协议调用API存储键值对;
采用Raft算法,保证服务的高可用
支持安全服务通信;
支持多数据中心;
2、consul agent
consul通过agent来运行的,agent分为server 和client两种类型,这两种类型基本上没有什么区别,server agent是将服务的消息存储,一般来说为了防止单点故障推荐使用3到5个来构建集群架构。
而client agent主要用于注销服务、健康检查及转发server agent的查询等,相当于一个代理,因此它必须要在集群的每台主机上运行。
一种服务或软件工具的产生必然有其使用场景和其优势,否则哪有其立足之地?
3、consul使用的场景
-
Docker 容器的注册与配置共享
-
Coreos 实例的注册与配置共享
-
SaaS 应用的配置共享、服务发现和健康检查。
-
vitess 集群
-
与 confd 服务集成,动态生成 nginx 和 haproxy 配置文件
4、Docker Consul容器服务更新与发现原理
1. Consul Cluster由部署和运行了Consul Agent的节点组成。 在Cluster中有两种角色:Server和 Client。
2. Server和Client的角色和Consul Cluster上运行的应用服务无关, 是基于Consul层面的一种角色划分.
3. Consul Server: 用于维护Consul Cluster的状态信息, 实现数据一致性, 响应RPC请求。官方建议是: 至少要运行3个或者3个以上的Consul Server。 多个server之中需要选举一个leader, 这个选举过程Consul基于Raft协议实现. 多个Server节点上的Consul数据信息保持强一致性。 在局域网内与本地客户端通讯,通过广域网与其他数据中心通讯。Consul Client: 只维护自身的状态, 并将HTTP和DNS接口请求转发给服务端。
4. Consul 支持多数据中心, 多个数据中心要求每个数据中心都要安装一组Consul cluster,多个数据中心间基于gossip protocol协议来通讯, 使用Raft算法实现一致性
5、工作流程:
当后面容器增加时,registrator注册容器中的服务—》通知consul server更新—》consul template模板进行更新,自动修改nginx.conf中的upstream参数
Registrator监控新建的Docker容器,并且检查判定这些容器提供的服务。从我们的目的出发,任何监听在某个端口的程序都是服务。Registrator在容器内发现的任务服务,都将被添加到一个服务注册端,比如Consul或etcd
准备template nginx模板文件,参数以变量形式写入
在consul服务器节点上操作
[root@localhost consul]# vim /root/consul/nginx.ctmpl
upstream http-server {
{{range service "nginx"}}
server {{.Address}}:{{.Port}};
{{end}}
}
consul-template是一个守护进程,用于实时查询consul集群信息,并更新文件系统上任意数量的指定模板,生成配置文件。更新完成后,可以选择运行shell命令执行更新操作,重新加载nginx。这种强大的抽象功能和查询语言模板可以使consul-template特别适合动态的创建配置文件。例如:创建nginx反向代理。
十、资源分配
1、为什么要做资源分配?
容器和虚拟机的区别:
虚拟机不需要做,因为虚拟机在创建的时候已经做了资源分配(配额),(虚拟CPU,虚拟内存,虚拟磁盘等)
而容器共享内核资源,所以需要做Cgroup,可以按照往年监控的数据,查看cpu等资源的耗用情况来进行分配
2、Cgroup资源配置方法
Docker是通过Cgroup来控制容器使用的资源配额,包括CPU、内存、磁盘i/o三大方面,基本覆盖了常见的资源配额和使用量控制。
Cgroup是Control Groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组所使用的物理资源(如CPU、内存、磁盘IO等)的机制,被docker等很多项目用于实现进程资源控制。Cgroup本身是提供将进程进行分组化管理的功能和接口的基础结构,I/O或内存的分配控制等具体的资源管理功能。这些具体的资源管理功能称为Cgroup子系统,有以下几大子系统实现:
blkio:设置限制每个块设备的输入输出控制。例如:磁盘,usb等
CPU:使用调度程序为cgroup任务提供CPU的访问。
cpuacct:产生cgroup任务的CPU资源报告。
cpuset:如果是多核心的cpu,这个子系统会为cgroup任务分配单独的CPU和内存。
devices:允许或拒绝cgroup任务对设备的访问。
freezer:暂停和恢复cgroup任务。
memory:设置每个cgroup的内存限制以及产生内存资源报告。
net_cls:标记每个网络包以供cgroup方便使用。
ns:命名空间子系统。
perf_event:增加了对每个group的监测跟踪的能力,可以监测属于某个特定的group的所有线程以及运行在特定CPU上的线程。
3、CPU周期限制
Docker提供了–cpu-period、–cpu-quota两个参数控制容器可以分配到的CPU时钟周期。
–cpu-period是用来指定容器对CPU的使用要在多长时间内做一次重新分配。
–cpu-quota是用来指定在这个周期内,最多可以有多少时间来跑这个容器。
与–cpu-shares不同的是,这种配置是指定一个绝对值,容器对CPU资源的使用绝对不会超过配置的值。
cpu-period和cpu-quota的单位为微秒(μs)。cpu-period的最小值为1000微秒,最大值为1秒,默认值为0.1秒(100000μs)
cpu-quota的值默认为-1,表示不做控制。cpu-period和cpu-quota参数一般联合使用。
例如:容器进程需要每1秒使用单个cpu的0.2秒时间,可以将cpu-period设置为1000000即1秒,cpu-quota设置为200000(0.2秒)。
在多核情况下,如果允许容器进程完全占用两个cpu,则可以将cpu-period设置为100000即0.1秒,cpu-quota设置为200000即0.2秒
[root@localhost ~]# docker run -itd --cpu-period 100000 --cpu-quota 200000 centos:stress
[root@localhost ~]# docker exec -it 16b6689aabc6 /bin/bash
[root@16b6689aabc6 /]# cd /sys/fs/cgroup/
[root@16b6689aabc6 cgroup]# ls
blkio cpuacct freezer net_cls perf_event
cpu cpuset hugetlb net_cls,net_prio pids
cpu,cpuacct devices memory net_prio systemd
[root@16b6689aabc6 cgroup]# cd cpu
[root@16b6689aabc6 cpu]# ls
cgroup.clone_children cpu.rt_period_us cpuacct.usage
cgroup.event_control cpu.rt_runtime_us cpuacct.usage_percpu
cgroup.procs cpu.shares notify_on_release
cpu.cfs_period_us cpu.stat tasks
cpu.cfs_quota_us cpuacct.stat
[root@16b6689aabc6 cpu]# cat cpu.cfs_period_us
100000
[root@16b6689aabc6 cpu]# cat cpu.cfs_quota_us
200000
4、CPU Core控制
对多核CPU的服务器,Docker还可以控制容器运行使用哪些CPU内核,即使用–cpuset-cpus参数。这对具有多CPU的服务器尤其有用,可以对需要高性能计算的容器进行性能最优的配置。
[root@localhost ~]# docker run -itd --name cpu1 --cpuset-cpus 1-2 centos:stress
#执行以上命令表示创建的容器只能用1、2两个cpu。最终生成的cgroup的cpu内核配置如下:
[root@localhost ~]# docker exec -it 75be98d74dcc /bin/bash
top - 07:34:23 up 45 min, 0 users, load average: 0.00, 0.01, 0.04
[root@75be98d74dcc /]# cat /sys/fs/cgroup/cpuset/cpuset.cpus #cpuset:cpu集合
1-2
[root@75be98d74dcc /]# stress -c 5 & #让容器产生5个子函数进程,并在后台运行
[root@75be98d74dcc /]# top #使用top命令查看cpu工作情况(top进去后按1,显示每个cpu的工作情况)
#通过下面指令可以看到容器中进程与cpu内核的绑定关系
[root@localhost ~]# docker exec 75be98d74dcc taskset -c -p 1 #-p 1 表示容器中第一个进程pid为1被绑定到cpu1和2上
pid 1's current affinity list: 1,2
十一、Docker-TLS加密通讯
1、使用TLS加密通讯原因
为了防止链路劫持、会话劫持等问题导致Docker通信时被中间人攻击,c/s两端应该通过加密方式通讯。
2、基础知识
1.对称密钥,例如DES、3DES、AES,长度不同,长度越长安全越高,解密速度越慢。
2.非对称密钥,分为公钥和私钥,例如RSA 公钥:所有人可知(锁),私钥(钥匙)个人身份信息,不可抵赖。
3.封装在证书中:个人信息,密钥,有效期
4.ca:证书颁发机构 ca证书
密钥key–》身份签名(csr)–》服务器/客户端(结合)制作证书pem
证书pem发送给客户端,客户端通过证书验证才能访问容器
3、TLS加密通讯部署过程:
1.修改服务器主机名为server,并添加到本地解析文件
[root@localhost ~]# hostnamectl set-hostname server
[root@localhost ~]# su
[root@server ~]# vim /etc/hosts
127.0.0.1 server
2.创建ca密钥(ca-key.pem)
[root@server ~]# openssl genrsa -aes256 -out ca-key.pem 4096 #256为密钥长度;4096为字节数
Generating RSA private key, 4096 bit long modulus
.......++
...............++
e is 65537 (0x10001)
Enter pass phrase for ca-key.pem: #输入密码123123(自定义)
Verifying - Enter pass phrase for ca-key.pem: #确认密码123123
3.创建ca根证书文件(ca.pem)
[root@server ~]# openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -subj "/CN=*" -out ca.pem #req:签名;x509:国际标准;sha256:指定哈希256位加密算法;subj:项目名称
Enter pass phrase for ca-key.pem: #输入123123
4.创建服务器私钥
[root@server ~]# openssl genrsa -out server-key.pem 4096 #genrsa:非对称密钥
Generating RSA private key, 4096 bit long modulus
.....................................................................................++
..............................................................++
e is 65537 (0x10001)
[root@server ~]# ls
anaconda-ks.cfg ca.pem server-key.pem 公共 视频 文档 音乐
ca-key.pem initial-setup-ks.cfg stress 模板 图片 下载 桌面
5.签名私钥
[root@server ~]# openssl req -subj "/CN=*" -sha256 -new -key server-key.pem -out server.csr
6.使用ca证书与私钥证书签名
[root@server ~]# openssl x509 -req -days 1000 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
Signature ok
subject=/CN=*
Getting CA Private Key
Enter pass phrase for ca-key.pem: #输入123123
[root@server ~]# ls
anaconda-ks.cfg ca.srl server.csr 公共 图片 音乐
ca-key.pem initial-setup-ks.cfg server-key.pem 模板 文档 桌面
ca.pem server-cert.pem stress 视频 下载
7.生成客户端密钥
[root@server ~]# openssl genrsa -out key.pem 4096
Generating RSA private key, 4096 bit long modulus
....................................++
.......................................................................++
e is 65537 (0x10001)
8.签名客户端
[root@server ~]# openssl req -subj "/CN=client" -new -key key.pem -out client.csr
9.创建配置文件
[root@server ~]# echo extendedKeyUsage=clientAuth > extfile.cnf
10.签名证书,输入123123,需要(签名客户端,ca证书,ca密钥)
[root@server ~]# openssl x509 -req -days 1000 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
Signature ok
subject=/CN=client
Getting CA Private Key
Enter pass phrase for ca-key.pem:
---------------------------------------------------------------------------------------------------------------------------------
11.删除多余文件
[root@server ~]# rm -rf ca.srl client.csr extfile.cnf server.csr
12.修改docker服务文件文件
[root@server ~]# vim /lib/systemd/system/docker.service
[root@server ~]# mkdir /tls
[root@server ~]# mv ca.pem /tls
[root@server ~]# mv server-cert.pem /tls
[root@server ~]# mv server-key.pem /tls/
[root@server ~]# mv cert.pem /tls/
[root@server ~]# mv key.pem /tls/
[root@server ~]# ls /tls/
ca.pem cert.pem key.pem server-cert.pem server-key.pem
13.重载进程,重启docker服务
[root@server ~]# systemctl daemon-reload
[root@server ~]# systemctl restart docker
14.将/tls目录下的ca.pem、cert.pem、key.pem三个文件复制给客户端
[root@server tls]# scp ca.pem [root@14.0.0.30](mailto:root@14.0.0.30):/etc/docker/
[root@server tls]# scp cert.pem [root@14.0.0.30](mailto:root@14.0.0.30):/etc/docker/
[root@server tls]# scp key.pem [root@14.0.0.30](mailto:root@14.0.0.30):/etc/docker/
15.到客户端14.0.0.30进行测试
[root@localhost docker]# vim /etc/hosts
加入:14.0.0.20 server
[root@localhost ~]# cd /etc/docker/ #注意要切换到服务端传证书文件的目录下
[root@localhost docker]# docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H [tcp://server:2376](tcp://server:2376) ps -a #测试成功,成功访问服务端容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
327038e98aa4 centos:stress "stress -c 1" About an hour ago Exited (137) About an hour ago cpu4
4eb80db7a397 centos:stress "stress -c 1" About an hour ago Exited (137) About an hour ago cpu3