---------------第一部分-------------------
一.什么是docker
dockerfile里面一个run就是一层,容器层以下所有镜像层都是只读的,docker从上往下依次查找文件 ,容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
docker相当于一个进程,通过namespace进行隔离,cgroups进行资源限制,基于内核容器化功能,我们可以将应用的可执行文件,命令,脚本等文件系统打包,确保它们在任何环境中都能以相同的方式运行,解决环境受限问题
特点及优势:
①轻量级虚拟化:轻量高效,快速开机停止,节省系统资源
如:docker开启和虚拟机开启速度的对比
②一致性性:确保应用程序在不同的环境中(如开发、测试、生产)具有一致的运行表现。
举例:无论在本地还是云端,应用的运行环境都能保持相同,减少了因环境差异导致的问题。
③可移植性:可以轻松地将 Docker 容器从一个平台迁移到另一个平台
④高效的资源利用:多个 Docker 容器可以共享主机的操作系统内核,从而更有效地利用系统资 源。
⑤易于部署扩展:可以从仓库拉取其他程序员上传的镜像,降低了制作成本,只需要编写dockerfile就可以实现环境的构建,简单便捷
二.docker与虚拟化
三.工作流程及核心组件
1、一切都从Dockerfile开始。Dockerfile是镜像的源代码。
2、创建Dockerfile后,可以构建它以创建容器的镜像。
3、获得容器的镜像后,创建容器。同时你可以推送和拉取镜像。
4、运行管理容器
核心组件:
①镜像:特殊的文件系统,包含一个应用运行的所有环境及依赖
②仓库:存储镜像的地方,可以pull和push
③容器:镜像的一个运行实例,可以运行我们部署的服务,可以相当于一个简易版的linux环境
-----------------第二部分----------------
一.环境部署(rhel9)
法一:
一.配置软件仓库
Centos 7:
]# cd /etc/yum.repos.d
]# vim docker.repo
[docker]
name=docker-ce
baseurl=https://mirrors.tuna.tsinghua.edu.cn/dockerce/linux/centos/7/x86_64/stable/
gpgcheck=0
[centos]
name=extras
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/7/extras/x86_64
gpgcheck=0
rhel9:
]# cd /etc/yum.repos.d
]# vim docker.repo
[docker]
name=docker-ce
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/rhel/9/x86_64/stable/
gpgcheck=0
二.安装docker-ce
]# yum install -y docker-ce
]# systemctl enable --now docker
最好配置镜像加速器/etc/docker/daemon.json
{
"registry-mirrors": ["https://h6cmifsy.mirror.aliyuncs.com"]
}
法二:上传需要的包
yum install *.rpm
mount -t cgroup2
systemctl enable --now docker
cgroup用途
资源隔离:通过cgroup,可以将一组相关的进程隔离在一个独立的cgroup中,从而避免它们对系统其他组件的干扰,保证系统的稳定性和可靠性
资源限制:cgroup可以限制cgroup中进程对系统资源的使用,如CPU、内存、磁盘I/O等,确保不会因为某个进程的使用过度而导致系统性能下降或者崩溃
优先级调整:可以通过cgroup设置不同cgroup之间的资源调度优先级,确保高优先级cgroup获得更多的资源,提高系统的整体性能
容器化支持:cgroup是Docker等容器化技术的基础之一,可以借助cgroup对容器中运行的应用程序进行资源隔离和限制,保证容器之间的互相独立性
二.基本操作
1.搜索镜像
[root@Docker-node1 ~]# docker search nginx
2.拉取镜像
[root@Docker-node1 ~]# docker pull busybox
[root@Docker-node1 ~]# docker pull nginx:1.26-alpine
3.查看本地镜像
[root@Docker-node1 ~]# docker images
alpine 版本:nginx镜像的最小安装发型版本
4.查看镜像信息
[root@Docker-node1 ~]# docker image inspect nginx:1.26-alpine
5.保存镜像
[root@Docker-node1 ~]# docker image save nginx:latest -o nginx-latest.tar.gz
[root@Docker-node1 ~]# docker image save nginx:latest nginx:1.26-alpine -o nginx.tag.gz
保存所有镜像
[root@Docker-node1 ~]# docker save `docker images | awk 'NR>1{print $1":"$2}'` -o images.tar.gz
6.删除镜像
[root@Docker-node1 ~]# docker rmi nginx:latest
[root@Docker-node1 ~]# docker rmi `docker images | awk 'NR>1{print $1":"$2}'`
7.启动容器
[root@Docker-node1 ~]# docker run -d --name mario -p 80:8080 timinglee/mario
[root@Docker-node1 ~]# docker run -it --name centos7 centos:7
[root@3ba22e59734f /]# #进入到容器中,按<ctrl>+<d>退出并停止容器,#按<ctrl>+<pq>退出但
不停止容器
8.重新进入容器
[root@docker ~]# docker attach centos7
9.-d #后台运行
-i #交互式运行
-t #打开一个终端
--name #指定容器名称
-p #端口映射 -p 80:8080 把容器8080端口映射到本机80端口
--rm #容器停止自动删除容器
--network #指定容器使用的网络
10.查看容器运行信息
[root@Docker-node1 ~]# docker ps #查看当前运行容器
[root@Docker-node1 ~]# docker ps -a #查看所有容器
[root@Docker-node1 ~]# docker inspect busybox #查看容器运行的详细信息
11.停止和运行容器
[root@Docker-node1 ~]# docker stop busybox #停止容器
[root@Docker-node1 ~]# docker kill busybox #杀死容器,可以使用信号
[root@Docker-node1 ~]# docker start busybox #开启停止的容器
12.删除容器
[root@Docker-node1 ~]# docker rm centos7 #删除停止的容器
[root@Docker-node1 ~]# docker rm -f busybox #删除运行的容器
[root@Docker-node1 ~]# docker container prune -f #删除所有停止的容器
13.镜像加载
docker load -i xxxxxxxx.tar.gz
14.查看容器的内部日志
[root@Docker-node1 ~]# docker logs web
15.文件的传输
[root@Docker-node1 ~]# docker cp test2:/leefile /mnt #把容器中的文件复制到本机
[root@Docker-node1 ~]# docker cp /etc/fstab test2:/fstab #把本机文件复制到容器中
容器内容的提交:
三.docker镜像构建
3.1.镜像获取方式
##软件官方提供
##企业镜像用官方镜像+Dockerfile来生成制作
##docker pull 镜像
##docker load -i 本地镜像包
3.2.构建参数
3.2.1.FROM
base image
FROM busybox:version
3.2.2.maintainer
指定作者信息,邮箱等
MAINTAINER user@example.com
3.2.3.ENV/AGR
用于定义一个变量
ENV FILENAME test
3.2.4.EXPOSE
暴露端口
EXPOSE 80
3.2.5.VOLUME
申明数据卷,通常指数据挂载点 eg:VOLUME [“/var/www/html”]
若是做了持久化,docker里面的数据会保留在宿主机的目录
3.2.6.WORKDIR
切换工作目录
3.2.7.COPY
用于添加宿主机本地的文件、目录、压缩等资源到镜像里面去,不会解压任何压缩包,不会复制url
COPY file /file或COPY [“file”,”/”]
3.2.8.ADD
用于将宿主机上面的文件添加到容器中,会自动解压安装包
ADD test.tar /mnt 或者 eg:ADD http://ip/test.tar /mnt
3.2.9.RUN
Run是在构建时执行的命令,写到了层里面,不会再容器运行时执行,一般会是安装一些包依赖等
3.2.9.CMD
在容器构建时会执行的命令,比如安装了Nginx的包(run),然后可以在容器运行时自动开启命令,就可以用cmd执行开启,当在外部构建容器指令后面写了外部命令时,会覆盖内部指令
CMD echo $FILENAME
CMD [“/bin/sh”,”-c”,“echo $FILENAME”]
3.2.10.ENTRYPOINT
启动容器时执行的命令,当构建命令后面传参或者写了外部命令时,不会覆盖其后面的指令
FROM busybox
MAINTAINER lee@timinglee.org
ENV NAME lee
ENTRYPOINT echo $NAME
[root@Docker-node1 docker]# docker run -it --rm --name test example:v3 sh
lee
3.3.DockerFile构建Nginx镜像
nginx源码安装需要下载make,gcc,openssl-devel,pcre-devel等,我的基础镜像是Centos:7,没有这些依赖包,因此需要再Centos:7上面只能装镜像仓库,因此,选择的是利用apache搭建一个镜像站,使容器可以访问到镜像站,从而从本地下载依赖包。(注意,要在虚拟机右下方查看镜像是否加载过来)
3.3.1:基础镜像构建
使用Centos:7运行一个容器
[root@node2 ~]# docker run -d --name centos centos:7
[root@node2 ~]# docker inspect centos
"EndpointID": "72e633a54dd8260991d6eb453f3605a722418b065f
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
[root@node2 ~]#yum install httpd -y
[root@node2 ~]# vim /etc/httpd/conf/httpd.conf
修改端口为8888;因为80端口要预留出来创建Nginx镜像时暴露
更换本地镜像:
挂载:mount /dev/sr1 /var/www/html/rhel7.9/
http服务默认加载目录
可以在浏览器通过172.25.254.170:8888/rhel7.9查看服务是否搭建成功
[root@node2 ~]# systemctl strat httpd
提交:
[root@node2 ~]# docker commit -m "add repo" centos centos:repo
至此,centos:repo可以下载Nginx源码安装需要的依赖
3.3.2.编写Dockerfile文件
注意:CMD提交时在后台运行
[root@node2 docker]# docker build -t nginx:v1 .
3.3.3. 镜像优化
方法一:缩减镜像层
选择最精简的基础镜像
减少镜像的层数 (RUN)
清理镜像构建的中间产物及缓存
[root@node2 ~]#docker build -t nginx:v2 .
方法二:多阶段构建(最好./configure后面指定源码安装路径,方便多阶段构建时复制目录)
[root@node2 docker]# docker build -t nginx:v3 .
四.docker镜像仓库管理
4.1.docker hub的使用
4.1.1.pull/push原理
1.client向index发送请求并完成认证
2.index给客户端发送token和镜像位置
3.客户端连取仓库获取/上传镜像
4.仓库会向index核实客户端的身份
5.index回复确认信息
6.仓库根据请求把镜像传给客户端或者客户端把镜像push到仓库
4.2.搭建docker私有仓库
4.2.1.搭建简单的registry仓库
docker公司已经将registry开源,我们可以快速构建企业私有仓库
地址: https://docs.docker.com/registry/deploying/
1.下载registry镜像
[root@node1 ~]# docker load -i registry.tag.gz
[root@docker ~]# docker pull registry
2.查看加载或者拉取是否成功
[root@node1 ~]# docker images
3.查看创建容器时所映射的端口
[root@node1 docker]# docker history registry
4.运行一个名为registry的容器
[root@node1 docker]# docker run -d -p 5000:5000 --restart=always --name registry registry:latest
5.给busybox打标签
[root@node1 docker]# docker tag busybox:latest 172.25.254.160:5000/busybox:latest
6.上传busybox:latest,会报需要https认证的错
[root@node1 docker]# docker push 172.25.254.160:5000/busybox:latest
7.配置非加密端口
[root@node1 docker]# vim /etc/docker/daemon.json
{
"insecure-registries" : ["http://172.25.254.160:5000"]
}
[root@node1 docker]# systemctl restart docker
[root@node1 docker]# docker push 172.25.254.160:5000/busybox:latest
The push refers to repository [172.25.254.160:5000/busybox]
d51af96cf93e: Pushed
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b
8.查看镜像上传
[root@node1 docker]# curl 172.25.254.160:5000/v2/_catalog
{"repositories":["busybox"]}
未配置非加密端口:
配置非加密端口:
4.2.2.配置https加密传输
1.生成认证证书和认证key,会产生两个文件,注意域名需要写进hosts解析:
[root@docker ~]#openssl req -newkey rsa:4096 \
-nodes -sha256 -keyout certs/timinglee.org.key \
-addext "subjectAltName = DNS:reg.timinglee.org" \ #指定备用名称
-x509 -days 365 -out certs/timinglee.org.crt
2.启动registry仓库
[root@docker ~]#docker run -d -p 443:443 --restart=always --name registry \
> --name registry -v /opt/registry:/var/lib/registry \
> -v /root/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key registry
客户端没有key和证书:
客户端创建了证书:
3.docker客户端建立证书
[root@docker docker]# mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
[root@docker docker]# cp /root/certs/timinglee.org.crt
/etc/docker/certs.d/reg.timinglee.org/ca.crt
[root@docker docker]# systemctl restart docker
4.测试
[root@docker docker]# docker push reg.timinglee.org/busybox:latest
4.2.3.为仓库建立登录认证
#安装建立认证文件的工具包
[root@docker docker]# dnf install httpd-tools -y
#建立认证文件
[root@docker ~]# mkdir auth
[root@docker ~]# htpasswd -Bc auth/htpasswd lee
注:若是第二次创建用户去掉c,否则会覆盖之前创建好的用户验证
#添加认证到registry容器中
[root@docker ~]# docker run -d -p 443:443 --restart=always --name registry \
> --name registry -v /opt/registry:/var/lib/registry \
> -v /root/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key \
> -v /root/auth:/auth \
> -e "REGISTRY_AUTH=htpasswd" \
> -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
> -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
> registry
[root@docker ~]# curl -k https://reg.timinglee.org/v2/_catalog -u lee:lee
{"repositories":["busybox","nginx"]}
登陆测试
[root@docker ~]# docker login reg.timinglee.org
Username: timinglee
Password:
当仓库开启认证后必须登陆仓库才能进行镜像上传
登录仓库:
4.3.构建企业级私有仓库:harbor
下载软件包地址 https://github.com/goharbor/harbor/releases
1.基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理 的灵活性。
2. 镜像复制:支持在不同的 Harbor 实例之间复制镜像,方便在多个数据中心或环境中分发镜像。
3. 图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。 4. 审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。
5. 垃圾回收:可以清理不再使用的镜像,节省存储空间。
4.4.2.部署harbor
环境:172.25.254.200,安装docker,专门用来以后存放自己的镜像,那么首先我们需要CA证书的认证和key,以及用户认证,但是harbor默认登录用户admin,密码可以自己修改,所以只需要认证即可,可以把timinglee.org.crt和timinglee.org.key复制到对应位置即可,不需要再次生成认证
[root@docker ~]# tar zxf harbor-offline-installer-v2.5.4.tgz
[root@node1 certs]# mkdir /data/certs -p
[root@node1 certs]# scp -p ./* 172.25.254.200:/data/certs/
[root@docker ~]# cd harbor/
[root@docker harbor]# cp harbor.yml.tmpl harbor.yml
[root@docker harbor]# vim harbor.yml
hostname: reg.timinglee.org
certificate: /data/certs/timinglee.org.crt
private_key: /data/certs/timinglee.org.key
harbor_admin_password: lee
[root@docker harbor]# ./install.sh --help
[root@docker harbor]# ./install.sh --with-chartmuseum
#管理harbor的容器
[root@docker harbor]# docker compose stop
[root@docker harbor]# docker compose up -d
vim /etc/docker/daemon.json
4.4.3.上传镜像
[root@docker harbor]# docker login reg.timinglee.org (admin:Mnwl@0816)
[root@docker harbor]# docker tag busybox:latest reg.timinglee.org/timinglee/busybox:latest
[root@docker harbor]# docker push reg.timinglee.org/timinglee/busybox:latest
五.docker网络
企业9默认使用nftables,我们可以切换为iptables:
grubby --update -kernel ALL --args iptables=true
iptables -nL
#查看网络
docker network ls
bridge:桥接网络(docker桥接接口docker 0),相当于走网关
host:本机网络
none:没网络
5.1.原生网络:
原生bridge模式:(docker0相当于网关)
原生网络host:(直连)
原生网络none: (没有网络)
5.2.自定义网络:(存在DNS模块)
建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。
容器ip会根据容器创建顺序ip不同,ip会变,但是名称不变,因此通信需要名称来通信,但是原生bridge没有DNS解析,无法通信
docker引擎在分配ip时时根据容器启动顺序分配到,谁先启动谁用,是动态变更的
多容器互访用ip很显然不是很靠谱,那么多容器访问一般使用容器的名字访问更加稳定
docker原生网络是不支持dns解析的,自定义网络中内嵌了dns
[root@docker ~]# docker run -d --network my_net1 --name web nginx
[root@docker ~]# docker run -it --network my_net1 --name test busybox
/ # ping web
PING web (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.197 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.096 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.087 ms
注意:不同的自定义网络是不能通讯的
[root@docker ~]# nft list ruleset可以看到网络隔离策略
5.3.不同自定义网络的互通
两个容器不同的网络栈通过添加网卡实现通信
[root@docker ~]# docker run -d --name web1 --network my_net1 nginx
[root@docker ~]# docker run -it --name test --network my_net2 busybox
ping不通;
#在上面test容器中加入网络eth1
[root@docker ~]# docker network connect my_net1 test
两个容器使用同一个网络栈:主要应用于两个业务耦合度高这样使用同一个网络栈的同一个ip,这样,他们间的通信只需要走回环接口即可
[root@docker ~]# docker run -it --rm --network container:web1 centos:7
结果会显示这个容器和web1有同样的ip地址(eth0)
[root@efae66874371 /]# curl localhost
虽然新建的容器没有Nginx,但是他和web1使用同样的ip,也是可以使用Nginx部署服务的
5.4.joined (利用容器部署PHPmyadmin管理mysql)
#运行phpmysqladmin
[root@docker ~]# docker run -d --name mysqladmin --network my_net1 \
-e PMA_ARBITRARY=1 \ #在web页面中可以手动输入数据库地址和端口
-p 80:80 phpmyadmin:latest
#运行数据库
[root@docker ~]# docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD='lee' \ #设定数据库密码
--network container:mysqladmin \ #把数据库容器添加到phpmyadmin容器中
mysql:5.7
开启的phpmyadmin容器中是没有数据库的
这里填写的localhost:3306是因为mysql容器和phpmyadmin容器公用一个网络站
5.5.容器内外网的访问
5.5.1.容器访问外网(火墙)
内网访问外网:postrouting(iptables策略)
容器网络和docker 0 一个网段,可以通讯,docker0会通过内核路由功能连接到能上网的网卡上,和外部通讯。 在这个过程中主要是依靠iptables的策略,把172.17.0.0进行地址伪装(0.0.0.0),也就是SNAT的地址转换
外网访问内网:prerouting,具体实现时需要做端口映射
(iptables策略/docker-proxy 双保险)
①外网访问到eth0,然后进行DNAT转换((0.0.0.0-->172.17.0.2:80),再走docker 0这个网关,到达容器
DNAT 6 -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 to:172.17.0.2:80
②外网访问到能上网的网卡,然后进行docker-proxy对数据包进行内转,走网关再根据端口选择到达具体容器
133986 ? Sl 0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 - host-port 80 -container-ip 172.17.0.2 -container-port 80
0.0.0.0通常用来表示任意IP地址
docker-proxy和dnat在建立容器端口映射时会开启,谁传输速率高走谁
5.5.2.docker跨主机网络
在生产环境中,我们的容器不可能都在同一个系统中,所以需要容器具备跨主机通信的能力
跨主机网络解决方案
docker原生的overlay和macvlan
第三方的flannel、weave、calico
5.5.2.1.macvlan网络方式
linux内核提供的一种网卡虚拟化技术,容器接口直接与主机网卡相连,无需nat或者端口映射,性能极好,可以使用vlan子接口实现多个macvlan网络,但是macvlan是二层隔离的,可以在三层通过网关让macvlan网络联通起来
具体实现:
1.在两台docker主机上各添加一块网卡,打开网卡混杂模式:新增添的网卡要为仅主机模式
ip link set eth224 promisc on
ip link set up eth224
2. 添加macvlan网路
3.测试
开启1.1.1.100,可以通
停止1.1.1.200,ping不通
六.docker数据卷管理及优化
容器对数据进行管理有两种:数据卷管理和数据卷容器管理
什么是数据卷?
简单来讲,就是在本地主机中可以在容器之间进行共享和重用的文件或者文件夹,通常通过docker run -v进行数据卷挂载到对应容器目录空间,多文件进行读取,类似于mount挂载
使用数据卷目的:
Docker 数据卷是一个可供容器使用的特殊目录,它绕过了容器的文件系统,直接将数据存储在宿主机 上。
数据持久化:即使容器被删除或重新创建,数据卷中的数据仍然存在,不会丢失。
数据共享:多个容器可以同时挂载同一个数据卷,实现数据的共享和交互。
独立于容器生命周期:数据卷的生命周期独立于容器,不受容器的启动、停止和删除的影响
使用数据卷原因:
①docker分层文件系统 ---性能差,生命周期与容器相同
②docker数据卷
mount到主机中,绕开分层文件系统
和主机磁盘性能相同,容器删除后依然保留
仅限本地磁盘,不能随容器迁移
6.1.bind mount数据卷
是将主机上的目录或文件mount到容器里,使用直观高效,易于理解,-指定路径时,要是不存在,挂载时会自动在本机或者容器内部自创建
数据卷实现:
6.2.docker managed数据卷
bind mount必须指定host文件系统路径,限制了移植性
docker managed volume 不需要指定mount源,docker自动为容器创建数据卷目录
默认创建的数据卷目录都在 /var/lib/docker/volumes 中
如果挂载时指向容器内已有的目录,原有数据会被复制到volume中
6.2.1.默认数据卷
自己若不创建数据卷,数据会自动保存在/var/lib/docker/volumes/容器id/_data/
[root@node1 volumes]# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD='lee'
mysql:5.7
[root@node1 volumes]# ls -l /var/lib/docker/volumes
总用量 0
drwx-----x 3 root root 19 8月 20 16:34
ad74662b8d6bb6fdcc6e82925ae9942b94bac5f9da4bd52b0a14ac451ae9ef75
[root@node1 volumes]# touch
ad74662b8d6bb6fdcc6e82925ae9942b94bac5f9da4bd52b0a14ac451ae9ef75/_data/leefile
[root@node1 volumes]# docker exec -it mysql bash
bash-4.2# cd /var/lib/mysql
bash-4.2# ls
清理未使用的 Docker 数据卷
[root@docker ~]# docker volume prune
6.2.2.建立数据卷
1.建立数据卷
[root@node1 ~]# docker volume create mysql_v
[root@node1 ~]# ls -l /var/lib/docker/volumes/mysql_v/_data/
6.2.3.使用建立的数据卷
[root@node _data]# docker run -d --name web1 -p 80:80 -v mysql_v:/usr/share/nginx/html nginx
e76706848323d6c329c41c4140903f8cc441458daf1459d9016bd1ed0ab3360a
[root@node _data]# cd /var/lib/docker/volumes/mysql_v/_data
6.3.数据卷容器
什么是数据卷容器?
在多个容器间共享数据的一个容器,容器目录下的数据可以在多个容器间共享,类似于一个提供网络文件共享的NFS服务器
建立数据卷容器:
[root@docker ~]# docker run -d --name datavol \
-v /tmp/data1:/data1:rw \
-v /tmp/data2:/data2:ro \
-v /etc/resolv.conf:/etc/hosts busybox
使用数据卷容器:
[root@docker ~]# docker run -it --name test --rm --volumes-from datavol busybox
测试:实现数据共享
6.4.备份与迁移数据卷
数据备份:
数据恢复:
七.docker安全优化
评估Docker的安全性时,主要考虑以下几个方面:
Linux内核的命名空间机制提供的容器隔离安全
Linux控制组机制对容器资源的控制能力安全
Linux内核的能力机制所带来的操作权限安全
Docker程序(特别是服务端)本身的抗攻击性。
其他安全增强机制对容器安全性的影响
#在rhel9中默认使用cgroup-v2 但是cgroup-v2中不利于观察docker的资源限制情况,所以推荐使用 cgroup-v1
[root@docker ~]# grubby --update-kernel=/boot/vmlinuz-$(uname -r) \
--args="systemd.unified_cgroup_hierarchy=0
systemd.legacy_systemd_cgroup_controller"
7.1.命名空间的隔离安全
1.当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间,提供了 最基础也最直接的隔离,但是与虚拟机相比却不是那么彻底,容器只是运行在宿主机上的一种特殊的进程,多个主机还是使用同一个宿主机的内核,Linux 内核中,有很多资源和对象是不能被 Namespace 化的,比如:磁盘等等
[root@docker ~]# docker run -d --name web nginx
7.2.控制组资源控制安全
当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合,Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等 资源,使得容器内的资源压力不会影响到本地主机系统和其他容器
举例:内存资源并没有被隔离
7.3.内核能力机制带来的操作权限安全
大部分情况下,容器并不需要“真正的”root权限,容器只需要少数的能力即可。 默认情况下,Docker采用“白名单”机制,禁用“必需功能”之外的其他权限
--privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供 给容器必须的权限。此时Docker 提供了权限白名单的机制,使用--cap-add添加必要的权限
进入容器,你会发现我们没有权限更改ip啊什么的,因此加上--privileged=true参数,即可做多种操作,但是这直接更改的是你宿主机的设置,很不安全,因此设置白名单
capabilities手册地址:http://man7.org/linux/man-pages/man7/capabilities.7.html
限制容器只能更改网络
[root@docker ~]# docker run --rm -it --cap-add NET_ADMIN busybox
进入容器,会发现无法管理磁盘,即fdisk -l无效
7.4.Docker服务端防护
确保只有可信的用户才能访问到Docker服务,允许Docker 服务端在非root权限下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。 这些子进程只允许在特定范围内进行操作
7.5.Docker的安全加固
7.5.1.Docker的默认隔离性
在系统中运行容器,我们会发现资源并没有完全隔离开,虽然我们限制了容器的内容使用情况,但是查看到的信息依然是系统中内存的使用信息,并没有隔离开
7.5.2.解决默认性隔离
LXCFS 是一个为 LXC(Linux Containers)容器提供增强文件系统功能的工具。
主要功能
1. 资源可见性: LXCFS 可以使容器内的进程看到准确的 CPU、内存和磁盘 I/O 等资源使用信 息。在没有 LXCFS 时,容器内看到的资源信息可能不准确,这会影响到在容器内运行的应用程序对资源的评估和 管理。
2. 性能监控: 方便对容器内的资源使用情况进行监控和性能分析。通过提供准确的资源信息,管理员和开发 人员可以更好地了解容器化应用的性能瓶颈,并进行相应的优化。
#在rhel9中lxcfs是被包含在epel源中,我们可以直接下载安装包进行安装
[root@docker ~]# ls lxcfs
lxcfs-5.0.4-1.el9.x86_64.rpm lxc-libs-4.0.12-1.el9.x86_64.rpm lxc-templates4.0.12-1.el9.x86_64.rpm
[root@docker ~]# dnf install lxcfs/*.rpm
[root@docker ~]# lxcfs /var/lib/lxcfs &
[root@docker ~]# docker run -it -m 256m \
-v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
-v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \
-v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
-v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
-v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
-v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
ubuntu
八.Docker资源限制
cgroup是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。
对进程进行优先级设置、审计,以及将进程挂起和恢复等操作。
Linux Cgroups 给用户暴露出来的操作接口是文件系统,它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下
执行命令可以查看:mount -t cgroup
Docker资源限制怎么做的???
Docker使用的是安全隔离,而不是虚拟化里面的物理隔离,它和系统是公用资源的,系统对它的限制通过内核自带的cgroup机制,容器运行后,会在/sys/fs/cgroup里面对每一项资源都做了一个目录,这个目录下面,为每一个容器都创建了一个控制组(新目录),我们通过对目录文件里面记录的值来对Docker资源进行相应的限制
8.1.限制cpu使用
8.1.1.限制CPU的使用量
[root@docker ~]# docker run -it --rm --name test \
--cpu-period 100000 \ #设置 CPU 周期的长度
--cpu-quota 20000 ubuntu #设置容器在一个周期内可以使用的 CPU 时间
root@5797d76b20f5:/# dd if=/dev/zero of=/dev/null &
[1] 8
也可以手动修改资源限制组里面的文件的具体数值
8.1.2.限制cpu的优先级
注意:这里最好修改为只有一个核心:方便查看效果
#开启容器并限制资源
docker run -it --rm --cpu-shares 100 ubuntu #设定cpu优先级,最大为1024,值越大优先级越高
root@dc066aa1a1f0:/# dd if=/dev/zero of=/dev/null &
[1] 8
root@dc066aa1a1f0:/# top
若是开启一个不限制cpu的容器,那么限制的那个占比100/1024,差不多小于百分之十的使用量
8.2.限制内存的使用
#开启容器并限制容器使用内存大小
[root@docker system.slice]# docker run -d --name test --memory 200M --memory-swap
200M nginx
查看容器内存使用限制:200*1024*1024=209715200
#测试容器内存限制,在容器中我们测试内存限制效果不是很明显,可以利用工具模拟容器在内存中写入数据
#在系统中/dev/shm这个目录被挂在到内存中,基本占用总内存的一半
(需要下软件才会测试比较明显:下载好后可以使用cgexec命令)
root@docker cgroup]# docker run -d --name test --rm --memory 200M --memory-swap
200M nginx
[root@docker cgroup]# cgexec -g
memory:docker/f5017485d69b50cf2e294bf6c65fcd5e679002e25bd9b0eaf9149eee2e379eec
dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=150
记录了150+0 的读入
记录了150+0 的写出
157286400字节(157 MB,150 MiB)已复制,0.0543126 s,2.9 GB/s
[root@docker cgroup]# cgexec -g
memory:docker/f5017485d69b50cf2e294bf6c65fcd5e679002e25bd9b0eaf9149eee2e379eec
dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=200
已杀死
8.3.限制Docker的磁盘io
[root@docker ~]# docker run -it --rm \
--device-write-bps \ #指定容器使用磁盘io的速率
/dev/nvme0n1:30M \ #/dev/nvme0n1是指定系统的磁盘,30M即每秒30M数据
ubuntu
会发现磁盘io(写入磁盘的效率中,最后一个直接写入磁盘速度很慢)
九.容器编排工具
Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具
因为yaml文件对格式要求很高,因此可以提前对vim进行设置vim ~/.vimrc
先来体验一下Docker compose
vim docker-compose.yml
9.1.docker compose常用命令
docker-compose up (启动配置文件中定义的所有服务)
参数:-d (在后台启动服务)
-f (指定yaml文件)
例:[root@docker test]# docker compose up -d
[root@docker ~]# docker compose -f test/docker-compose.yml up -d
[root@docker test]# docker compose down 停止并删除
[root@docker test]# docker compose start
[root@docker test]# docker compose stop
[root@docker test]# docker compose restart
[root@docker test]# docker compose ps列出正在运行的服务
[root@docker test]# docker compose logs db
[root@docker test]# docker compose -f test.yml exec test sh
/ #
(注意:test是服务名)
[root@docker test]# docker compose -f test.yml pull
[root@docker test]# docker compose -f test.yml config验证查看解析后的 Compose文件内容
9.2.构建和重新构建
Dockerfile用于构建test1镜像
lee.Dockerfile用于构建test2镜像
vim docker-compose.yml
9.3. docker compose的yml文件
9.3.1.服务(services)
1.服务名称:每个服务在配置文件中都有一个唯一的名称,用于在命令行和其他部分引用该服务。
2.镜像:例如, image: nginx:latest 表示使用 nginx 镜像的最新版本
3.端口映射:"8080:80" 表示将主机的 8080 端口映射到容器内部的 80 端口。
4.环境变量:例如, VAR1: value1 设置环境变 量 VAR1 的值为 value1
5.存储卷: 将主机上的目录或文件挂载到容器中,以实现数据持久化或共享。
6.命令:覆盖容器启动时默认执行的命令,command: python app.py 指定容器启动时运行 python app.py 命令
9.3.2.网络(networks)
将服务连接到特定的网络,以便不同服务的容器可以相互通信
默认情况下docker compose 在执行时会自动建立网路
注意:这种情况是默认使用的是已有网络,不会建立新的外部网络
测试多网卡情况,会自己新建网卡
9.2.3.存储卷(volumes)
9.4.完成haproxy和nginx负载均衡架构实施
思路:在docker-compose.yml,需要构建三个容器,后端两台Nginx,连接内网,通过数据卷挂载在主机上更改数据卷里面的内容,进而同步到容器内,更改访问页,前端一台haproxy服务器,有内外和外网两个网卡,一个用于上网,一个用于与后端服务器连接,这个容器启动,需要配置文件的支持,因此需要提前编写好配置文件,通过数据卷挂载到容器内
环境准备:
1.准备haproxy的配置文件,并挂载到对应目录
没有配置文件模版怎么办??下载不安装
[root@node1 ~]# yum install haproxy -y --downloadonly --downloaddir=/mnt
加载镜像:
docker load -i haproxy-2.3.tar.gz
查看haproxy详细信息,确定最后容器启动时的命令执行目录
编写haproxy的配置文件:vim /var/lib/docker/volumes/conf/haproxy.cfg
vim docker-compose.yml
准备访问页面
测试: