目录
九、利用docker编排完成haproxy和nginx负载均衡架构
1、只下载haproxy,找出haproxy的配置文件,编辑配置文件
准备工作:
搭建本地网络源:
cd /etc/yum.repos.d/ vim docker-ce.repo
一、基础操作
#拉取镜像
[root@decker-node1 ~]# docker pull nginx:1.26-alpine
#查看本地镜像
[root@decker-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 5ef79149e0ec 12 days ago 188MB
busybox latest 65ad0d468eb1 15 months ago 4.26MB
timinglee/game2048 latest 19299002fdbe 7 years ago 55.5MB
timinglee/mario latest 9a35a9e43e8c 8 years ago 198MB
#查看镜像(nginx)
[root@decker-node1 ~]# docker image inspect nginx
#保存镜像
[root@decker-node1 ~]# docker image save nginx:latest -o nginx-latest.tar.gz
[root@Docker-node1 ~]# docker ps #查看当前运行容器
[root@Docker-node1 ~]# docker ps -a #查看所有容器
[root@Docker-node1 ~]# docker inspect busybox #查看容器运行的详细信息
[root@Docker-node1 ~]# docker stop busybox #停止容器
[root@Docker-node1 ~]# docker kill busybox #杀死容器,可以使用信号
[root@Docker-node1 ~]# docker start busybox #开启停止的容器
[root@docker-node1 ~]# docker load -i game2048.tar.gz
[root@docker-node1 ~]# docker load -i mario.tar.gz
[root@docker-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
timinglee/game2048 latest 19299002fdbe 7 years ago 55.5MB
timinglee/mario latest 9a35a9e43e8c 8 years ago 198MB
[root@docker-node1 ~]# docker run -d --rm --name game1 -p 80:8080 timinglee/mario
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
475d1ada9324 timinglee/mario "python3 -m http.ser…" 2 minutes ago Up 2 minutes 0.0.0.0:80->8080/tcp, :::80->8080/tcp game1
[root@docker-node1 ~]# docker rm -f game1
game1
[root@docker-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
二、构建镜像
1、参数示例及使用方法
FROM指定 base 镜像 eg : FROM busybox:versionCOPY复制文件 eg : COPY file /file 或者 COPY [“file”,”/”]MAINTAINER 指定作者信息,比如邮箱 eg : MAINTAINER user@example.com在最新版的 docker 中用 LABEL KEY="VALUE" 代替ADD功能和 copy 相似,指定压缩文件或 url eg: ADD test.tar /mnt 或者 eg : ADDhttp://ip/test.tar /mntENV指定环境变量 eg : ENV FILENAME testEXPOSE暴漏容器端口 eg : EXPOSE 80VOLUME申明数据卷,通常指数据挂载点 eg : VOLUME [“/var/www/html”]WORKDIR切换路径 eg : WORKDIR /mntRUN在容器中运行的指令 eg: touch fileCMD在启动容器时自动运行动作可以被覆盖 eg : CMD echo $FILENAME 会调用shell 解析 eg : CMD [“/bin/sh”,”-c”,“echo $FILENAME”] 不调用 shell 解析ENTRYPOINT和 CMD 功能和用法类似,但动作不可被覆盖
[root@decker-node1 ~]# cd docker/
[root@decker-node1 docker]# touch dockerfile
[root@decker-node1 docker]# vim dockerfile
volume:
docker inspect test #查看挂载点、宿主机的目录
2、Docker构建实例
删除没有挂在成功的镜像:
[root@decker-node1 docker]# docker rmi `docker images | awk '/none/{print $2}'`
[root@decker-node1 docker]# docker rmi 04f578596280 931faa592f44
加载centos7镜像:
[root@decker-node1 docker]# docker load -i centos-7.tar.gz
编写构建文件:
开始构建:
root@decker-node1 docker]# docker build -t nginx:v1 .
构建时出现报错:yum时候出现问题->原因是centos镜像的问题
dnf install httpd -y
#配置文件的端口改为8888
systemctl restart httpd
新加cdroom:
挂载本地软件仓库sr1:
开启centos7容器:
[root@decker-node1 ~]# docker run -it --name centos centos:7
配置该容器的本地软件仓库:
将配置好的容器提交镜像(centos的repo版本)
[root@decker-node1 ~]# docker commit -m "add repo" centos centos:repo
修改构建文件:
继续构建nginx镜像:
[root@decker-node1 docker]# docker build -t busybox:v1 .
可以看到nginx:vi版本有356MB,可以进行优化减少大小。
3、镜像优化示例
缩减镜像层:
[root@decker-node1 docker]# vim dockerfile
可以看出nginx:v1版本变小了(292MB):
多阶段构建:
可以看出nginx:v2版本变小(210MB):
使用最精简镜像
加载nginx1.23镜像和最小精简镜像:
[root@decker-node1 docker]# docker load -i nginx-1.23.tar.gz
[root@decker-node1 docker]# docker load -i debian11.tar.gz
编辑构建文件:
可以看到nginx:v3版本只有34.5MB:
三、docker镜像仓库管理
1、docker hub
2、搭建私有仓库
(1)、搭建简单无加密私有仓库
下载镜像:
[root@decker-node1 ~]# docker load -i registry.tag.gz
开启容器:
[root@decker-node1 ~]# docker run -d -p 5000:5000 --restart=always registry
给要上传的镜像添加标签:
[root@decker-node1 ~]# docker tag nginx:v2 172.25.254.100:5000/nginx:v2
配置非加密端口:
daemon.json是 Docker 的配置文件,通常位于/etc/docker/目录下(不同系统可能有所不同)。
以下是一个示例的daemon.json文件内容及解释:
json
复制
{
"registry-mirrors": ["https://your-custom-mirror.com"],
"insecure-registries": ["your-insecure-registry:port"],
"max-concurrent-downloads": 10,
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
解释:
"registry-mirrors": 指定 Docker 镜像加速地址,可以提高拉取镜像的速度。
"insecure-registries": 指定不安全的私有镜像仓库地址,如果你的私有仓库没有使用 HTTPS,需要将其添加到这个列表中。
"max-concurrent-downloads": 设置同时下载的最大层数,可根据系统资源和网络情况调整。
"log-driver": 设置日志驱动,这里设置为json-file表示以 JSON 格式的文件记录日志。
"log-opts": 日志相关的选项,这里设置了单个日志文件最大为10m,最多保留3个日志文件。
你可以根据自己的需求对daemon.json进行配置。修改后,通常需要重启 Docker 服务使配置生效。
[root@decker-node1 ~]# vim /etc/docker/daemon.json
[root@decker-node1 ~]# systemctl restart docker
上传:
[root@decker-node1 ~]# docker push 172.25.254.100:5000/nginx:v2
查看镜像上传:
[root@decker-node1 docker]# curl 172.25.254.100:5000/v2/_catalog
(2)、搭建加密的私有仓库
生成认证证书和key
#删除配置文件的非加密配置
[root@decker-node1 ~]# vim /etc/docker/daemon.json
[root@decker-node1 ~]# systemctl restart docker
mk[root@decker-node1 ~]# mkdir certs
#添加解析
[root@decker-node1 ~]# vim /etc/hosts
172.25.254.100 decker-node1 reg.gaoyingjie.org
#生成key和证书
[root@decker-node1 ~]# openssl req -newkey rsa:4096 \
> -nodes -sha256 -keyout certs/gaoyingjie.org.key \
> -addext "subjectAltName = DNS:reg.gaoyingjie.org" \
> -x509 -days 365 -out certs/gaoyingjie.org.crt
让docker读取证书:
[root@decker-node1 ~]# mkdir /etc/docker/certs.d/reg.gaoyingjie.org/ -p
[root@decker-node1 ~]# cp /root/certs/gaoyingjie.org.crt /etc/docker/certs.d/reg.gaoyingjie.org/ca.crt
[root@decker-node1 ~]# systemctl restart docker
开启registry容器:
[root@decker-node1 ~]# 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/gaoyingjie.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/gaoyingjie.org.key registry:latest
#-v: 挂载目录,容器下有该目录
添加tag标签:
[root@decker-node1 docker]# docker tag busybox:latest reg.gaoyingjie.org/busybox:latest
上传:
[root@decker-node1 docker]# docker push reg.gaoyingjie.org/busybox:latest
查看上传的镜像:
[root@decker-node1 docker]# curl -k https://reg.gaoyingjie.org/v2/_catalog
(3)、搭建用户认证的私有仓库
解释:需要用户输入密码才能的上传到搭建的私有仓库。
创建认证文件(使用md5加密):
[root@decker-node1 ~]# mkdir auth
[root@decker-node1 ~]# htpasswd -Bc auth/htpasswd gaoyingjie #-B:最强加密方式
New password:
Re-type new password:
Adding password for user gaoyingjie
[root@decker-node1 ~]# 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/gaoyingjie.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/gaoyingjie.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@decker-node1 ~]# docker login reg.gaoyingjie.org
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores
Login Succeeded
上传镜像:
[root@decker-node1 ~]# docker push reg.gaoyingjie.org/busybox:latest
查看上传的镜像:
curl -k https://172.25.254.100/v2/ catalog -ugaoyingjie:gaoyingjie
若未登录私有仓库:则显示上传失败。
3、构建企业级私有仓库-harbor
在第2步的基础上部署harbor
[root@docker ~]# tar zxf harbor-offline-installer-v2.5.4.tgz
[root@docker ~]# ls
anaconda-ks.cfg certs harbor-offline-installer-v2.5.4.tgz
auth harbor
[root@docker ~]# cd harbor/
[root@docker harbor]# cp harbor.yml.tmpl harbor.yml
[root@docker harbor]# vim harbor.yml
生成证书和key:
[root@docker-harbor harbor]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/gaoyingjie.org.key -addext "subjectAltName = DNS:reg.gaoyingjie.org" -x509 -days 365 -out certs/gaoyingjie.org.crt
将证书和key放入配置文件里指定目录:
[root@decker-node1 harbor]# mkdir /data
[root@decker-node1 harbor]# cp -r /root/certs/ /data/
[root@decker-node1 harbor]# ls /data/
certs
#让docker读取证书
[root@docker-harbor certs]# cp /root/certs/gaoyingjie.org.crt /etc/docker/certs.d/reg.gaoyingjie.org/ca.crt
安装harbor:
[root@decker-node1 harbor]# ./install.sh --with-chartmuseum
启动harbor:
[root@decker-node1 harbor]# docker compose stop
[root@decker-node1 harbor]# docker compose up -d
本地解析:
登录harbor:浏览器输入reg.gaoyingjie.org(仓库名,也就是hostname)
新建项目:
上传镜像到仓库新建项目newtest:
#登录harbor私有仓库
#先将之前的退出,如果没登陆过则不用
[root@decker-node1 harbor]# docker logout reg.gaoyingjie.org
Removing login credentials for reg.gaoyingjie.org
#登录
[root@decker-node1 harbor]# docker login reg.gaoyingjie.org
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credential-stores
Login Succeeded
添加标签:
[root@decker-node1 harbor]# docker tag nginx:v3 reg.gaoyingjie.org/newtest/nginx:v3
上传镜像:
[root@decker-node1 harbor]# docker push reg.gaoyingjie.org/newtest/nginx:v3
可以看到已上传nginx
小tip:
#一键加载镜像 #所有的镜像文件在/root/images下 [root@docker-harbor images]# for i in `ls /root/images`; do docker load -i $i; done #一键清除所有容器(慎重) [root@docker-harbor harbor]# docker container prune -f #一键添加标签 [root@docker-harbor ~]# docker images | awk 'NR>1{system("docker tag "$1":"$2" reg.gaoyingjie.org/library/"$1":"$2)}' #一键push [root@docker-harbor ~]# docker images | awk '/reg.gaoyingjie.org/{system("docker push "$1":"$2)}' #一键删除某些镜像 [root@k8s-master ~]# docker images | awk '/reg.timinglee.org/{system("docker rmi "$1":"$2)}'
四、docker的网络
修改防火墙策略
[root@decker-node1 ~]# grubby --update-kernel ALL --args iptables=true
[root@decker-node1 ~]# reboot
1、dacker的原生网络
(1)、bridge
(2)、host
(3)、none
2、docker的自定义网络
自定义桥接:原生的桥接模式是没有dns模块,所以要用自定义桥接,可以用容器名称通信。
容器的开启顺序不同会导致ip不同,会导致容器之间通讯出现问题。
[root@docker-node1 ~]# docker network create mynet1 -d bridge
7e2fe742ddd7221d316d60276be1078e28f09ae1b2b6ca1ec79f8df5ca31ceda
[root@docker-node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ad53e07c3e80 bridge bridge local
12e886188af6 host host local
7e2fe742ddd7 mynet1 bridge local
cf8dda13f1cb none null local
[root@docker-node1 ~]# docker run -it --name test1 --network mynet1 busybox
[root@docker-node1 ~]# docker run -it --name test2 --network mynet1 busybox
#删除网络
[root@docker-node1 ~]# docker network rm mynet1
mynet1
[root@docker-node1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
ad53e07c3e80 bridge bridge local
12e886188af6 host host local
cf8dda13f1cb none null local
可以看出,两个容器test1和test2处于同一网络,之间可以用ip通信,也可以用容器名通信。而传统的桥接模式是不能用容器名称通信的。
3、不同的自定义网络之间的通信
有两种情况:用相同网络栈和不同网络栈
(1)、容器用不同的网络栈
#创建两个自定义桥接网络
[root@docker-node1 ~]# docker network create mynet1 -d bridge
2a79172a5fe1a4b433c3daf4bdefaabf89b0a656aa5e7a07c007ae6a05a7b078
[root@docker-node1 ~]# docker network create mynet2 -d bridge
a79928a1c7ec8d4037863138b02a5fb967254ee3a560388572b0b16fd6ae0745
可以看到不同自定义网络是是不能通信的。
将一个容器加入网卡接入另一个网络中:
#将test2接入mynet1网络中
#所以test2容器有172.28.0.2(mynet1)和172.19.0.2(mynet2)两个ip
[root@docker-node1 ~]# docker network connect mynet1 test2
(2)、容器用相同的网络战栈-joined网络
示例1:
[root@docker-node1 ~]# docker run -d --name test1 --network mynet1 nginx
8d1ad6dd316d38816f509a8db9ab1c057d766e8c92b437b98b4c72578eb4700c
#用mynet2的网络栈
[root@docker-node1 ~]# docker run -d --name test2 --network container:test1 centos:7
7ae5ac441717042123b0ddf964a1918725dfc2070709200772d46a900c79b343
镜像centos是没有web服务的,但是test1和test2用了同个网络栈,所以test2有wab服务:
示例2:
phpmyadmin和mysql两个容器共用一个网络栈,phpmyadmin通过回环接口就能管理mysql,更安全。
[root@docker-node1 ~]# docker load -i mysql-5.7.tar.gz
[root@docker-node1 ~]# docker load -i phpmyadmin-latest.tar.gz
[root@docker-node1 ~]# docker network create mynet1 -d bridge
#开启phpmyadmin容器
[root@docker-node1 ~]# docker run -d --name mysqladmin --network mynet1 \
> -e PMA_ARBITRARY=1 \
> -p 80:80 phpmyadmin:latest
#开启mysql容器
[root@docker-node1 ~]# docker run -d --name mysql \
> -e MYSQL_ROOT_PASSWORD='gyj' \
> --network container:mysqladmin \
> mysql:5.7
登录:浏览器输入172.25.254.100
在mysql容器内执行命令:
[root@docker-node1 ~]# docker exec -it mysql bash
bash-4.2#
也可以用phpmyadmin管理数据库。
4、容器内外网的访问
(1)、容器访问外网
(2)、外网访问容器
5、容器的跨主机网络通信
macvlan
[root@docker-node1 ~]# ip link set eth1 promisc on
[root@docker-node1 ~]# ip link set up eth1
两主机添加macvlan网络:
[root@docker-node2 ~]# docker network create -d macvlan --subnet 1.1.1.0/24 --gateway 1.1.1.1 -o parent=eth1 macvlan1
开启容器:
[root@docker-node1 ~]# docker run -it --name test1 --network macvlan1 --ip 1.1.1.100 --rm busybox
[root@docker-node2 ~]# docker run -it --name test2 --network macvlan1 --ip 1.1.1.200 --rm busybox
测试:开处于不同主机的两个容器是否可以通信
五、docker的数据卷管理
1、bind mount数据卷
- 是将主机上的目录或文件mount到容器里。
- 使用直观高效,易于理解。
- 使用 -v 选项指定路径。
[root@docker-node1 ~]# docker run -it --rm -v /test1:/data1:rw -v /etc/passwd:/data2/passwd:ro busybox
2、docker managed数据卷
- bind mount必须指定host文件系统路径,限制了移植性
- docker managed volume 不需要指定mount源,docker自动为容器创建数据卷目录
- 默认创建的数据卷目录都在 /var/lib/docker/volumes 中
- 如果挂载时指向容器内已有的目录,原有数据会被复制到volume中
[root@docker-node1 ~]# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD='gyj' mysql:5.7
[root@docker-node1 ~]#cd /var/lib/docker/volumes/09c6f145e4449d1cbdfd5118fdd869adb32573a4195c18dc22a6ac93f3c7596b/_data/
[root@docker-node1 _data]# touch newfile
#进入容器查看是否有newfile
[root@docker-node1 ~]# docker exec -it mysql bash
bash-4.2# cd /var/lib/mysql
bash-4.2# ls
可以看到没有指定数据卷目录,默认在挂载到host的/var/lib/docker/volume/容器id/_data中,在此目录下新建文件,可以在容器内部的/var/lib/容器名/中看到新文件。
3、数据卷容器
数据卷容器( Data Volume Container )是 Docker 中一种特殊的容器,主要用于方便地在多个容器之间 共享数据卷。
#建立数据卷容器
[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
六、docker的安全优化
[root@docker-node1 ~]# docker run -d --name web nginx
516df6628241e9b4f3e802cbef696163ce681070d739b8ae716efe74708466c7
[root@docker-node1 ~]# docker inspect web | grep Pid
"Pid": 1898,
"PidMode": "",
"PidsLimit": null,
[root@docker-node1 ~]# cd /proc/
[root@docker-node1 proc]# cd 1898
[root@docker-node1 1898]# cd ns
[root@docker-node1 ns]# ls
cgroup ipc mnt net pid pid_for_children time time_for_children user uts
[root@docker-node1 ns]# cd /sys/fs/cgroup/
[root@docker-node1 cgroup]# ls
blkio cpu,cpuacct freezer misc net_prio rdma
cpu cpuset hugetlb net_cls perf_event systemd
cpuacct devices memory net_cls,net_prio pids
[root@docker-node1 cgroup]# cd memory/
[root@docker-node1 memory]# cd docker/
[root@docker-node1 docker]# ls
516df6628241e9b4f3e802cbef696163ce681070d739b8ae716efe74708466c7
cgroup.clone_children
cgroup.event_control
***
[root@docker-node1 docker]# cd 516df6628241e9b4f3e802cbef696163ce681070d739b8ae716efe74708466c7/
[root@docker-node1 516df6628241e9b4f3e802cbef696163ce681070d739b8ae716efe74708466c7]# ls
cgroup.clone_children memory.memsw.failcnt
cgroup.event_control memory.memsw.limit_in_bytes
cgroup.procs memory.memsw.max_usage_in_bytes
memory.failcnt memory.memsw.usage_in_bytes
memory.force_empty memory.move_charge_at_immigrate
memory.kmem.failcnt memory.numa_stat
memory.kmem.limit_in_bytes memory.oom_control
memory.kmem.max_usage_in_bytes memory.pressure_level
memory.kmem.slabinfo memory.soft_limit_in_bytes
memory.kmem.tcp.failcnt memory.stat
memory.kmem.tcp.limit_in_bytes memory.swappiness
memory.kmem.tcp.max_usage_in_bytes memory.usage_in_bytes
memory.kmem.tcp.usage_in_bytes memory.use_hierarchy
memory.kmem.usage_in_bytes notify_on_release
memory.limit_in_bytes tasks
memory.max_usage_in_bytes
1、docker的资源限制
(1)、限制cpu的使用量
[root@docker-node1 ~]# docker run -it --rm --name test1 --cpu-period 100000 --cpu-quota 20000 ubuntu
root@3c63c90f85ef:/# dd if=/dev/zero of=/dev/null &
[1] 9
root@3c63c90f85ef:/# top
[root@docker-node1 ~]# docker run -it --rm --name test2 --cpu-period 100000 --cpu-quota 30000 ubuntu
root@9ba159f17589:/# dd if=/dev/zero of=/dev/null &
[1] 9
root@9ba159f17589:/# top
(2)、限制cpu的优先级
[root@docker-node1 ~]# docker run -it --rm --name test1 --cpu-shares 100 ubuntu
root@0d33e9d6b5a3:/# dd if=/dev/zero of=/dev/null &
[1] 8
root@0d33e9d6b5a3:/# top
[root@docker-node1 ~]# docker run -it --rm --name test2 ubuntu
dd if=/dev/zero of=/dev/null &root@c30ea1c45318:/# dd if=/dev/zero of=/dev/null &
[1] 9
root@c30ea1c45318:/# top
(3)、限制内存使用
上传工具:
libcgroup-0.41-19.el8.x86_64.rpm
libcgroup-tools-0.41-19.el8.x86_64.rpm
[root@docker-node1 ~]# dnf install *.rpm -y
开启容器并限制内存:
[root@docker-node1 ~]# docker run -d --rm --name test1 --memory 200M --memory-swap 200M nginx
9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616
[root@docker-node1 ~]# cd /sys/fs/cgroup/
[root@docker-node1 cgroup]# cgexec -g memory:docker/9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=150
查看该容器id下的内存资源限制文件,可以看到200m的字节为 209715200,也可通过echo写入文件将内存限制从200mb改为300mb:
[root@docker-node1 ~]#cd /sys/fs/cgroup/memory/docker/9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616/
[root@docker-node1 9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616]#
cat memory.memsw.limit_in_bytes
209715200
[root@docker-node1 9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616]# echo 314572800 > memory.memsw.limit_in_bytes
[root@docker-node1 9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616]# cgexec -g memory:docker/9dec367f92ee6874fb5a6e543d369b1f0aa81f2ae8dff875ae30e1f710a04616 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=300
(4)、限制docker的磁盘io
[root@docker-node1 ~]# docker run -it --rm --device-write-bps /dev/nvme0n1:30M ubuntu
root@452768b7f1e0:/# dd if=/dev/zero of=bigfile
root@452768b7f1e0:/# dd if=/dev/zero of=bigfile bs=1M count=100
root@452768b7f1e0:/# dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct
七、docker的安全加固
1、docker默认隔离性
可以看到虽然限制了容器200m的内存,但是内存资源并没有完全隔离。
2、解决默认隔离性问题
LXCFS 是一个为 LXC ( Linux Containers )容器提供增强文件系统功能的工具。LXCFS 可以使容器内的进程看到准确的 CPU 、内存和磁盘 I/O 等资源使用信息。在没有 LXCFS 时,容器内看到的资源信息可能不准确,这会影响到在容器内运行的应用程序对资源的评估和管理。
安装lxcfs
[root@docker-node1 ~]# cd /mnt/
[root@docker-node1 mnt]# ls
hgfs lxc-libs-4.0.12-1.el9.x86_64.rpm
lxcfs-5.0.4-1.el9.x86_64.rpm lxc-templates-4.0.12-1.el9.x86_64.rpm
[root@docker-node1 mnt]# dnf install *.rpm
运行lxcfs解决隔离性问题:
[root@docker-node1 ~]# lxcfs /var/lib/lxcfs &
开启容器并指定内存:
docker run -it --name test -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
可以看到指定的内存为256m,容器显示的内存就为256m。
4、容器特权
5、容器白名单
八、容器编排工具Docker Compose
编辑vim配置文件:
vim ~/.vimrc
1、基础操作
[root@docker-node1 ~]# mkdir test
[root@docker-node1 test]# cd test/
#编辑yml文件
[root@docker-node1 test]# vim docker-compose.yml
#启动服务
[root@docker-node1 test]# docker compose up -d
[+] Running 3/3
✔ Network test_default Created 0.2s
✔ Container test-web-1 Started 1.6s
✔ Container test-test-1 Started 1.5s
[root@docker-node1 test]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1b571c4c09aa nginx:latest "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 80/tcp test-web-1
[root@docker-node1 test]# cp docker-compose.yml new-compose.yml
[root@docker-node1 test]# rm -rf docker-compose.yml
[root@docker-node1 test]# vim new-compose.yml
#可以使用-f 来指定yml文件
[root@docker-node1 test]# docker compose -f new-compose.yml up -d
[+] Running 2/2
✔ Container test-test-1 Started 1.1s
✔ Container test-web-1 Started
#停止正在运行的服务
[root@docker-node1 test]# docker compose stop
[+] Stopping 2/2
✔ Container test-web-1 Stopped 0.1s
✔ Container test-test-1 Stopped 0.0s
#重启服务
[root@docker test]# docker compose restart
#停止并删除配置文件中定义的所有服务以及相关的网络和存储卷。
[root@docker test]# docker compose down
#查看状态
[root@docker-node1 test]# docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
test-web-1 nginx:latest "/docker-entrypoint.…" web About a minute ago Up 11 seconds 80/tcp
2、构建和重新构建服务
编辑构建docker的文件:
[root@docker-node1 test]# vim Dockerfile
[root@docker-node1 test]# vim new.Dockerfile
写重新构建的文件:在之前test1、test2的基础上重新构建
[root@docker-node1 test]# vim docker-compose.yml
构建生效:
#build
[root@docker-node1 test]# docker compose -f docker-compose.yml build#构建
services中所有
[root@docker test]# docker compose -f test.yml build test1 #构建
services中的test1
可以看到构建的新镜像:test1、test2
开启容器:可以看到旧的test1、test2构建时创建的文件
以上是构建好镜像后手动开启容器。
自动开启容器:
# --build
[root@docker test]# docker compose -f docker-compose.yml up -d #会去仓库拉去镜
像
[root@docker test]# docker compose -f docker-compose.yml up --build #会先构建镜像后
启动容器
可以看到自动开启容器:
3、其他操作
- docker-compose exec :
[root@docker-node1 test]# vim docker-compose.yml
[root@docker-node1 test]# vim docker-compose.yml
[root@docker-node1 test]# docker compose -f docker-compose.yml up -d
#在正在运行的服务容器中执行命令
[root@docker-node1 test]# docker compose -f docker-compose.yml exec test1 sh
/ # touch newfile
/ # ls
bin etc lib newfile root tmp var
dev home lib64 proc sys usr
/ #
-
docker-compose pull :
[root@docker test]# docker compose -f docker-compose.yml pull
[+] Pulling 2/2
✔ test Pulled
✔ ec562eabd705 Pull complete
- docker-compose config :
[root@docker-node1 test]# docker compose config
name: test
services:
test1:
command:
- /bin/sh
- -c
- sleep 3000
container_name: busybox1
image: busybox:latest
networks:
default: null
restart: always
networks:
default:
name: test_default
4、Docker Compose 的yml文件
(1)、服务
#服务名称(service1_name/service2_name 等):每个服务在配置文件中都有一个唯一的名称,用于在命令行和其他部分引用该服务。
services:
web:
# 服务1的配置
mysql:
# 服务2的配置
#镜像(image):
#指定服务所使用的 Docker 镜像名称和标签。例如, image: nginx:latest 表示使用 nginx镜像的最新版本
services:
web:
images:nginx
mysql:
images:mysql:5.7
#将容器内部的端口映射到主机的端口,以便外部可以访问容器内的服务。例如, -"8080:80" 表示将主机的 8080 端口映射到容器内部的 80 端口。
services:
web:
image: nginx:latest
container_name: nginx1 #指定容器名称
restart: always #docekr容器自动启动
expose:
- 1234 #指定容器暴露那些端口,些端口仅对链接的服务可见,不会映射到主机的端口
ports:
- "80:8080"
#环境变量(environment):为容器设置环境变量,可以在容器内部的应用程序中使用。例如, VAR1: value1 设置环境变量 VAR1 的值为 value1
services:
web:
image: mysql:5.7
container_name: mysql1
restart: always
environment:
MYSQL_ROOT_PASSWORD: gyj
#存储卷(volumes):将主机上的目录或文件挂载到容器中,以实现数据持久化或共享。例如, -
/host/data:/container/data 将主机上的 /host/data 目录挂载到容器内的/container/data 路径。
services:
test:
image: busybox
command: ["/bin/sh","-c","sleep 3000"]
restart: always
container_name: busybox1
volumes:
- /etc/passwd:/tmp/passwd:ro #只读挂在本地文件到指定位置
#网络(networks):将服务连接到特定的网络,以便不同服务的容器可以相互通信
services:
web:
image: nginx
container_name: webserver
network_mode: bridge #使用本机自带bridge网络
services:
test:
image: busybox
container_name: webserver
command: ["/bin/sh","-c","sleep 10000"]
#network_mode: mynet2
networks:
- mynet1
- mynet2
networks:
mynet1:
driver: bridge
mynet2:
driver: bridge
#命令(command):覆盖容器启动时默认执行的命令。例如, command: python app.py 指定容器启动时运行
python app.py 命令
[root@docker test]# vim busybox.yml
services:
web:
image: busybox
container_name: busybox
#network_mode: mynet2
command: ["/bin/sh","-c","sleep10000000"]
(2)、网络
- 定义 Docker Compose 应用程序中使用的网络。可以自定义网络名称和驱动程序等属性。
- 默认情况下docker compose 在执行时会自动建立网路
services:
test:
image: busybox1
command: ["/bin/sh","-c","sleep 3000"]
restart: always
network_mode: default
container_name: busybox
test1:
image: busybox2
command: ["/bin/sh","-c","sleep 3000"]
restart: always
container_name: busybox1
networks:
- mynet1
test3:
image: busybox3
command: ["/bin/sh","-c","sleep 3000"]
restart: always
container_name: busybox1
networks:
- mynet1
networks:
mynet1:
driver: bridge #使用桥接驱动,也可以使用macvlan用于跨主机连接
default:
external: true #不建立新的网络而使用外部资源
name: bridge #指定外部资源网络名字
mynet2:
ipam:
driver: default
config:
- subnet: 172.28.0.0/16
gateway: 172.28.0.254
(3)、存储卷
services:
test:
image: busybox
command: ["/bin/sh","-c","sleep 3000"]
restart: always
container_name: busybox1
volumes:
- data:/test #挂在data卷
- /etc/passwd:/tmp/passwd:ro #只读挂在本地文件到指定位置
volumes:
data:
name: timinglee #指定建立卷的名字
九、利用docker编排完成haproxy和nginx负载均衡架构
1、只下载haproxy,找出haproxy的配置文件,编辑配置文件
#只下载不安装haproxy
[root@docker-node1 ~]# dnf install haproxy -y --downloadonly --downloaddir=/mnt
#解压文件并输出为目录,-id:i是输出,d是目录
[root@docker-node1 mnt]# rpm2cpio haproxy-2.4.22-1.el9.x86_64.rpm | cpio -id
2、编辑docker compose容器编排文件
[root@docker-node1 ~]# vim haproxy.yml
3、启动容器
[root@docker-node1 ~]# docker compose -f /root/haproxy.yml up -d
4、查看是否启动
5、写入网页内容
从配置文件可以看到,在主机的/var/lib/docker/volumes/data_web目录下,有data_web1和data_web2,这两个文件挂载的是nginx容器的网站首发内容页,所以在data_web1、data_web2这两个目录下写入网站首页内容。
6、测试
haproxy用的是轮询调度算法
删除镜像、加速器、volume
ldd /usr/local/nginx/sbin/nginx nginx运行时必须调用的模块