docker技术详解,带你全方面玩懂docker


目录

一、docker简介

 1.1 什么是docker

1.2 docker与虚拟化的对比

1.3 docker的优势 

二、部署docker

2.1 容器的工作方法

2.2 部署docker

2.2.1 配置docker的软件仓库

三、docker的基本操作

3.1 docker的镜像管理

3.1.1 拉取镜像:

3.1.2 搜索镜像: 

3.1.3 查看镜像信息:

3.1.4 导出镜像:

3.1.5 删除镜像:

 3.2 docker的常用操作

3.2.1 启动容器:

3.2.2 查看容器运行的信息:

 3.2.3 停止和运行容器:

3.2.4 删除容器:

 3.2.5 容器内容提交:

3.2.6 系统中文件传输:

 3.2.7 查询容器内部的日志:

 四、docker的镜像构建

 4.1 docker镜像结构

4.2 镜像运行的基本原理

4.3 镜像构建

4.3.1 构建参数

4.3.2 dockerfile实例

4.4 镜像优化方案 

 4.4.1 优化示例

 五、docker 镜像仓库的管理

 5.1 什么是docker仓库

5.2 docker仓库的工作原理       

 5.2.1 pull原理

5.2.2 push原理

​编辑

5.3  搭建docker的私有仓库

5.3.1 搭建简单的Registry仓库

5.3.2 为Registry提加密传输

 5.3.3 为仓库建立登录认证

5.4 搭建企业级私有仓库(harbor)

5.4.1 部署harbor

 5.5 docker的WebUI工具(图形化)

六、docker原生网络及自定义桥接网络

6.1 原生网络(bridge)

6.2 原生网络(host)

6.3 原生网络(none)

6.4 自定义桥接网络

6.4.1 如何让不同的自定义网络互通?

 6.4.2 joined容器网络

6.4.2.1 joined网络示例演示:

6.5  容器内外网的访问

6.5.1 容器访问外网

6.5.2 外网访问docker容器

 6.5.3 docker容器的跨主机通信

 6.5.3.1 CNM(Container Network Model)

 6.5.3.2 macvlan网络方式实现跨主机通信

 七、Docker数据卷管理及优化

7.1为什么要使用数据卷

7.2 bind mount 数据卷

7.3 docker managed 数据卷

7.4 bind mount数据卷和docker managed数据卷的对比

 7.5 docker中数据卷的备份与迁移

八、docker的安全优化

8.1 Docker的资源限制及对CPU资源限制的方法

8.1.1 限制CPU使用

 8.1.2 docker中对内存使用的限制

8.1.2.1 自建控制器

8.1.3 限制docker的磁盘io

8.2 Docker的安全加固

8.2.1 容器的特权

8.2.2 容器的白名单

九、容器编排工具Docker Compose

 9.1 Docker Compose的常用命令参数

9.1.1 服务状态查看

9.1.1.1 示例

9.1.2 构建和重新构建服务

9.1.2.1 示例:

 9.2 Docker Compose的yml文件

 9.2.1 示例:

9.2.2 网络设定示例:

9.2.3 存储卷的示例: 

 9.3 docker compose在企业中的示例


一、docker简介

Docker 之父 Solomon Hykes Docker 就好比传统的货运集装箱

 1.1 什么是docker

 

Docker 是管理容器的引擎,为应用打包、部署平台,而非单纯的虚拟化技术
它具有以下几个重要特点和优势:

轻量级虚拟化

  •  Docker 容器相较于传统的虚拟机更加轻量和高效,能够快速启动和停止,节省系统资源。例如,启动一个 Docker 容器可能只需要几秒钟,而启动一个虚拟机则可能需要几分钟。

 一致性

  • 确保应用程序在不同的环境中(如开发、测试、生产)具有一致的运行表现。
  • 无论在本地还是云端,应用的运行环境都能保持相同,减少了因环境差异导致的问题。

可移植性

  • 可以轻松地将 Docker 容器从一个平台迁移到另一个平台,无需担心依赖和环境配置的差异。
  • 比如,在本地开发的容器可以无缝部署到云服务器上。
高效的资源利用
  • 多个 Docker 容器可以共享主机的操作系统内核,从而更有效地利用系统资源。

 易于部署和扩展

  • 能够快速部署新的应用实例,并且可以根据需求轻松地进行水平扩展。
        总之,Docker 极大地简化了应用程序的开发、部署和管理流程,提高了开发效率和运维的便利性。
        它在现代软件开发和云计算领域得到了广泛的应用。


1.2 docker与虚拟化的对比

 

虚拟机
docker 容器
操作系统
宿主机上运行虚拟机 OS
共享宿主机 OS
存储
镜像较大( GB)
镜像小( MB
性能
操作系统额外的 cpu 、内存消耗
几乎无性能损耗
移植性
笨重、与虚拟化技术耦合度高
轻量、灵活迁移
隔离性
完全隔离
安全隔离
部署
慢、分钟级
快速、秒级
运行密度
一般几十个
单机支持上千容器

1.3 docker的优势 

  • 对于开发人员:Build onceRun anywhere
  • 对于运维人员:Configure onceRun anything
  • 容器技术大大提升了IT人员的幸福指数!

二、部署docker


2.1 容器的工作方法


2.2 部署docker


2.2.1 配置docker的软件仓库

红帽9:
[root@docker-node1 ~]# vim /etc/yum.repos.d/docker.repo
[docker]
name=docker-ce
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable/
gpgcheck=0

红帽7:
[root@docker-node1 ~]# vim /etc/yum.repos.d/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
安装docker:
这样下载太慢了
[root@docker-node1 ~]# dnf makecache
[root@docker-node1 ~]# dnf search docker
[root@docker-node1 ~]# dnf install docker-ce.x86_64 -y

直接拖入准备好的docker压缩包:
[root@docker-node1 ~]# tar zxf docker.tar.gz 
[root@docker-node1 ~]# ls
anaconda-ks.cfg                               docker-ce-27.1.2-1.el9.x86_64.rpm                  docker.tar.gz  Pictures   vmset.sh
containerd.io-1.7.20-3.1.el9.x86_64.rpm       docker-ce-cli-27.1.2-1.el9.x86_64.rpm              Documents      Public
Desktop                                       docker-ce-rootless-extras-27.1.2-1.el9.x86_64.rpm  Downloads      Templates
docker-buildx-plugin-0.16.2-1.el9.x86_64.rpm  docker-compose-plugin-2.29.1-1.el9.x86_64.rpm      Music          Videos
[root@docker-node1 ~]# 
[root@docker-node1 ~]# dnf install *.rpm -y

编辑docker启动文件,设定其使用iptables的网络设定方式,默认使用nftables
[root@docker-node1 ~]# vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true #加上这个

[root@docker-node1 ~]# systemctl enable --now docker
[root@docker-node1 ~]# docker info  #查看docker信息

如果是红帽7的话:

如果用的红帽7,需要激活内核网络选项
]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
]# sysctl --system
]# systemctl restart docker

docker的镜像加速器:

[root@docker-node1 ~]# vim /etc/docker/daemon.json
{
  "registry-mirrors": ["https://docker.m.daocloud.io"]
}

[root@docker-node1 ~]# systemctl restart docker

三、docker的基本操作


3.1 docker的镜像管理

3.1.1 拉取镜像:

这样拉取太慢了
[root@docker-node1 ~]# docker pull busybox

[root@docker-node1 ~]# docker load -i game2048.tar.gz mario.tar.gz nginx-latest.tar.gz 
[root@docker-node1 ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
nginx                latest    5ef79149e0ec   2 weeks 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的webserver:
[root@docker-node1 ~]# docker run -d --rm --name webserver -p 80:80 nginx
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                               NAMES
00ef6b9c1803   nginx     "/docker-entrypoint.…"   39 seconds ago   Up 38 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   webserver

[root@docker-node1 ~]# docker rm -f webserver

[root@docker-node1 ~]# docker pull nginx:1.26-alpine #alpine表示是最精简版,最小安装的发行版本

3.1.2 搜索镜像: 

[root@docker-node1 ~]# docker search (后面跟你需要搜索的镜像名称)

3.1.3 查看镜像信息:

[root@docker-node1 ~]# docker image inspect nginx:1.26-alpine 

查看镜像的结构
[root@docker-node1 ~]# docker history nginx:1.26-alpine 

3.1.4 导出镜像:

  • -o:指定导出镜像的位置;

  • 可以同时导出多个镜像到一个文件中;

  • 指定.tar.gz 可以导出并压缩。

#保存镜像
[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

3.1.5 删除镜像:

[root@docker-node1 ~]# docker rmi (后面跟上你要删除的镜像名称)
[root@Docker-node1 ~]# docker rmi `docker images | awk 'NR>1{print $1":"$2}'`

 3.2 docker的常用操作

参数作用
-d后台运行
-i交互式运行
-t打开一个终端
--name指定容器名称
-p端口映射 -p 80:8080 把容器8080端口映射到本机80端口
--rm容器停止自动删除容器
--network指定容器使用的网络

3.2.1 启动容器:

[root@docker-node1 ~]# docker run -it --name test busybox

[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>退出但不停止容器

#重新进入容器
[root@docker ~]# docker attach centos7
[root@3ba22e59734f /]#
#在容器中执行命令
[root@docker ~]# docker exec -it test ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

3.2.2 查看容器运行的信息:

[root@Docker-node1 ~]# docker ps #查看当前运行容器
[root@Docker-node1 ~]# docker ps -a #查看所有容器
[root@Docker-node1 ~]# docker inspect busybox #查看容器运行的详细信息

 3.2.3 停止和运行容器:

 容器内的第一个进程必须一直处于运行的状态,否则这个容器,就会处于退出状态!

[root@Docker-node1 ~]# docker stop busybox #停止容器
[root@Docker-node1 ~]# docker kill busybox #杀死容器,可以使用信号
[root@Docker-node1 ~]# docker start busybox #开启停止的容器

3.2.4 删除容器:

[root@Docker-node1 ~]# docker rm centos7 #删除停止的容器
[root@Docker-node1 ~]# docker rm -f busybox #删除运行的容器
[root@Docker-node1 ~]# docker container prune -f #删除所有停止的容器

 3.2.5 容器内容提交:

  • 默认情况下,容器被删除后,在容器中的所有操作都会被清理,包括要保存的文件
  • 如果想永久保存,那么我们需要把动作提交,提交后会生成新的镜像
  • 当我们在运行新镜像后即可看到我们提交的内容
临时的:
[root@docker-node1 ~]# docker run -it --name test busybox
/ # touch file
/ # touch dingfile
/ # ls
bin       dingfile  file      lib       proc      sys       usr
dev       etc       home      lib64     root      tmp       var
/ # exit
[root@docker-node1 ~]# docker rm test
test
[root@docker-node1 ~]# docker run -it --name test busybox
/ # ls
bin    etc    lib    proc   sys    usr
dev    home   lib64  root   tmp    var
/ #

永久保存,就是生成新的镜像:
[root@docker-node1 ~]# docker run -it --name test busybox
/ # touch dingfile
/ # ls
bin       dingfile  home      lib64     root      tmp       var
dev       etc       lib       proc      sys       usr
按Ctrl+pq不要暂停容器
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED              STATUS              PORTS     NAMES
03d8eeb1bec5   busybox   "sh"      About a minute ago   Up About a minute             test
[root@docker-node1 ~]# docker commit -m "add dingfile" test busybox:v1
sha256:157fafd2dcbb8f55c68abbe16d56d7769a3515e0eba393d3851fd91c77d18b0c
[root@docker-node1 ~]# docker images
REPOSITORY           TAG           IMAGE ID       CREATED         SIZE
busybox              v1            157fafd2dcbb   5 seconds ago   4.26MB      ---- 生成了一个名叫v1的镜像
nginx                1.26-alpine   9703b2608a98   2 weeks ago     43.3MB
nginx                latest        5ef79149e0ec   2 weeks 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
[root@docker-node1 ~]# 
[root@docker-node1 ~]# docker run -it --name test busybox:v1
/ # ls
bin       dingfile  home      lib64     root      tmp       var
dev       etc       lib       proc      sys       usr
/ #

可以看到新的镜像会比原来的多一层,原来的只有一层,读取层,新的镜像加了一层,就是读写层,以此类推,最多可以有127层。
[root@docker-node1 ~]# docker history busybox:v1
IMAGE          CREATED         CREATED BY                          SIZE      COMMENT
157fafd2dcbb   3 minutes ago   sh                                  18B       add dingfile
65ad0d468eb1   15 months ago   BusyBox 1.36.1 (glibc), Debian 12   4.26MB    
[root@docker-node1 ~]# docker history busybox:latest 
IMAGE          CREATED         CREATED BY                          SIZE      COMMENT
65ad0d468eb1   15 months ago   BusyBox 1.36.1 (glibc), Debian 12   4.26MB    

3.2.6 系统中文件传输:

[root@docker-node1 ~]# docker cp test:/dingfile  /mnt
Successfully copied 1.54kB to /mnt
[root@docker-node1 ~]# ls /mnt/
dingfile  hgfs
[root@docker-node1 ~]#

[root@docker-node1 ~]# docker cp /etc/passwd test:/
Successfully copied 3.58kB to test:/
[root@docker-node1 ~]# docker attach test
/ # ls
bin       dingfile  home      lib64     proc      sys       usr
dev       etc       lib       passwd    root      tmp       var
/ # 

 3.2.7 查询容器内部的日志:

[root@docker-node1 ~]# docker logs (跟上你要查看的容器名称)

 四、docker的镜像构建

 4.1 docker镜像结构

  • 共享宿主机的kernel
  • base镜像提供的是最小的Linux发行版
  • 同一docker主机支持运行多种Linux发行版
  • 采用分层结构的最大好处是:共享资源

4.2 镜像运行的基本原理

 

  • Copy-on-Write 可写容器层
  • 容器层以下所有镜像层都是只读的
  • docker从上往下依次查找文件
  • 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
  • 一个镜像最多127

4.3 镜像构建

4.3.1 构建参数

参数作用
FROM指定base镜像eg:FROM busybox:version
COPY
复制文件 eg COPY file /file 或者 COPY [“file”,”/”]
MAINTAINER指定作者信息,比如邮箱eg:MAINTAINER user@exa ample.com在最新版的docker中用LABEL KEY="VALUE"代替
ADD功能和copy相似,指定压缩文件或url eg: ADD test.tar /mnt 或者eg:ADD http://ip/test.tar /mnt
ENV指定环境变量 egENV FILENAME test
EXPOSE暴漏容器端口 egEXPOSE 80
VOLUME申明数据卷,通常指数据挂载点 egVOLUME 申明数据卷,通常指数据挂载点 egVOLUME [“/var/www/html”]
WORKDIR切换路径 egWORKDIR /mnt
RUN在容器中运行的指令 eg: touch file
CMD在启动容器时自动运行动作可以被覆盖eg:CMD echo $FILENAME会调用shell解析eg:CMD [“/bin/sh”,”- c”,“echo $FILENAME”]不调用shell解析
ENTRYPOINT和CMD功能和用法类似,但动作不可被覆盖

 参数示例及用法:

[root@docker-node1 ~]# mkdir docker
[root@docker-node1 ~]# cd docker/ 
[root@docker-node1 docker]# touch dingfile
[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest				#指定使用的基础镜像
LABEL Mail="ding@timingding.org"  	#指定作者信息
COPY dingfile / 	#复制当前目录文件到容器指定位置,leefile必须在当前目录中
构建镜像:
[root@docker-node1 docker]# docker build -t example:v1 .

#ADD
[root@docker-node1 docker]# touch dingfile{1..3}
[root@docker-node1 docker]# tar zcf dingfile.gz dingfile*
[root@docker-node1 docker]# vim Dockerfile
FROM busybox
LABEL Mail="ding@timingding.org"
COPY dingfile /
ADD dingfile.gz /

[root@docker-node1 docker]# docker build -t example:v2 .
[root@docker-node1 docker]# docker run -it --rm --name test example:v2
/ # ls
bin        dingfile1  etc        lib64      sys        var
dev        dingfile2  home       proc       tmp
dingfile   dingfile3  lib        root       usr
/ # 

#ENV CMD
[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest
LABEL Mail="ding@timingding.org"
ENV name=timingding
CMD ["/bin/sh","-c","echo $name"]

[root@docker-node1 docker]# docker build -t busybox:v2 .
[root@docker-node1 docker]# docker run -it --rm --name test busybox:v2
timingding
[root@docker-node1 docker]#

CMD会被替代,如果不想被替代:
[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest
LABEL Mail="ding@timingding.org"
ENV name=timingding
CMD ["/bin/sh","-c","echo $name"]
ENTRYPOINT ["/bin/sh","-c","echo end"]		#加这个参数

[root@docker-node1 docker]# docker build -t busybox:v2 .
[root@docker-node1 docker]# docker run -it --rm --name test busybox:v2 sh
end
[root@docker-node1 docker]# 

#EXPOSE VOLUME WORKDIR
[root@docker-node1 docker]# vim Dockerfile 
FROM busybox:latest
LABEL Mail="ding@timingding.org"
ENV name=timingding
VOLUME /var/www/html
WORKDIR /var/www/html
RUN touch dingfile

[root@docker-node1 docker]# docker build -t busybox:v2 .
[root@docker-node1 docker]# docker run -it --rm --name test busybox:v2
/var/www/html # ls
dingfile
/var/www/html # 按住Ctrl+pq

[root@docker-node1 docker]# docker inspect test   --- 运行这个查看mounts

[root@docker-node1 docker]# docker rm -f test
test
[root@docker-node1 docker]# 

如何删除没构建成功的<none>
docker rmi `docker images | awk '/none/{print $3}'`

4.3.2 dockerfile实例

建立构建目录,编写构建文件:

[root@docker-node1 docker]# dnf install httpd -y
[root@docker-node1 docker]# vim /etc/httpd/conf/httpd.conf
端口改为8888,把80端口腾出来给容器用

[root@docker-node1 docker]# systemctl start httpd
[root@docker-node1 docker]# mkdir /var/www/html/rhel7.9
[root@docker-node1 docker]# mount /dev/sr1 /var/www/html/rhel7.9/

[root@docker-node1 docker]# docker run -it --name centos centos:7
[root@aacbd745d702 /]# ls
anaconda-post.log  dev  home  lib64  mnt  proc  run   srv  tmp  var
bin                etc  lib   media  opt  root  sbin  sys  usr
[root@aacbd745d702 /]#
[root@aacbd745d702 /]# cd /etc/yum.repos.d/
[root@aacbd745d702 yum.repos.d]# rm -rf *
[root@aacbd745d702 yum.repos.d]# vi centos7.repo
[centos7]
name=centos7
baseurl=http://172.17.0.1:8888/rhel7.9
gpgcheck=0

复制会话,容器里面提交:
[root@docker-node1 ~]# docker  commit -m "add repo" centos centos:repo
sha256:1316d99a6c00b5305d2b6a93d122e0142af7a5ecec40ea4b509fd520e6e41e4b

退出镜像并删除:
[root@aacbd745d702 ~]# exit
exit
[root@docker-node1 docker]# docker rm centos

[root@docker-node1 docker]# vim Dockerfile 
FROM centos:repo
LABEL Mail="ding@timingding.org"
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install gcc make pcre-devel openssl-devel -y
RUN ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_
stub_status_module
RUN make
RUN make install
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off"]

[root@docker-node1 docker]# docker build -t nginx:v1 .
查看镜像:
[root@docker-node1 docker]# docker images

4.4 镜像优化方案 

优化的策略:

  • 选择最精简的基础镜像

  • 减少镜像的层数

  • 清理镜像构建的中间产物

  • 选择最精简的基础镜像

  • 减少镜像的层数

  • 清理镜像构建的中间产物

 4.4.1 优化示例

方法一:缩减镜像层

[root@docker-node1 docker]# vim Dockerfile
FROM centos:repo
LABEL Mail="ding@timingding.org"
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install gcc make pcre-devel openssl-devel -y && ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module && make &
& make install && rm -rf /mnt/nginx-1.26.1 && yum clean all
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off"]

[root@docker-node1 docker]# docker build -t nginx:v1 .

 方法二:多阶段构建

[root@docker-node1 docker]# vim Dockerfile 

FROM centos:repo AS build
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install gcc make pcre-devel openssl-devel -y && ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module && make && make install && rm -rf /mnt/nginx-1.26.1 && yum clean all

FROM centos:repo
LABEL Mail=ding@timingding.org
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80 443
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

[root@docker-node1 docker]# docker build -t nginx:v2 .
[root@docker-node1 docker]# docker images

测试是否能运行:
[root@docker-node1 docker]# docker run -d --name webserver nginx:v2
14b4709b7c000c07dc41211f4c21110ffc855ffc32a49c31827bb337ced865c0
[root@docker-node1 docker]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS             NAMES
14b4709b7c00   nginx:v2   "/usr/local/nginx/sb…"   6 seconds ago   Up 6 seconds   80/tcp, 443/tcp   webserver
[root@docker-node1 docker]#

 方法三:使用最精简镜像

[root@docker-node1 ~]# docker load -i debian11.tar.gz 
[root@docker-node1 ~]# docker load -i nginx-1.23.tar.gz

[root@docker-node1 docker]# vim Dockerfile
FROM nginx:1.23 AS base
ARG TIME_ZONE
RUN mkdir -p /opt/var/cache/nginx && \
    cp -a --parents /usr/lib/nginx /opt && \
    cp -a --parents /usr/share/nginx /opt && \
    cp -a --parents /var/log/nginx /opt && \
    cp -aL --parents /var/run /opt && \
    cp -a --parents /etc/nginx /opt && \
    cp -a --parents /etc/passwd /opt && \
    cp -a --parents /etc/group /opt && \
    cp -a --parents /usr/sbin/nginx /opt && \
    cp -a --parents /usr/sbin/nginx-debug /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libpcre* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
    cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime

FROM gcr.io/distroless/base-debian11
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]

[root@docker-node1 docker]# docker build -t nginx:v3 .
[root@docker-node1 docker]# docker images

 测试是否能运行:

[root@docker-node1 docker]# docker run --rm -d --name webserver nginx:v3
148ddbd5c5e574ed0cbfbdbc2fb9747372fb27f3aa226292e35479f056dee486
[root@docker-node1 docker]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS             NAMES
148ddbd5c5e5   nginx:v3   "nginx -g 'daemon of…"   4 seconds ago   Up 4 seconds   80/tcp, 443/tcp   webserver
[root@docker-node1 docker]#

 五、docker 镜像仓库的管理

 5.1 什么是docker仓库

 

Docker 仓库( Docker Registry 是用于存储和分发 Docker 镜像的集中式存储库。
        它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从库中拉取所需的镜像。
Docker 仓库可以分为公共仓库和私有仓库:
  • 公共仓库,如 Docker Hub,任何人都可以访问和使用其中的镜像。许多常用的软件和应用都有在Docker Hub 上提供的镜像,方便用户直接获取和使用。
  •  私有仓库则是由组织或个人自己搭建和管理的,用于存储内部使用的、不希望公开的镜像。

5.2 docker仓库的工作原理       

仓库中的三个角色:
  • index docker索引服务,负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息。
  • registry docker仓库,是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过Index Auth serviceToken的方式进行认证
  • Registry Client Docker充当registry客户端来维护推送和拉取,以及客户端的授权。

 5.2.1 pull原理

镜像拉取分为以下几步:
  • docker客户端向index发送镜像拉去请求并完成与index的认证
  • index发送认证token和镜像位置给dockerclient
  • dockerclient携带token和根据index指引的镜像位置取连接registry
  • Registry会根据client持有的tokenindex核实身份合法性
  • index确认此token合法性
  • Registry会根据client的请求传递镜像到客户端

5.2.2 push原理

 

镜像上传的步骤:
  • clientindex发送上传请求并完成用户认证
  • index会发方tokenclient来证明client的合法性
  • client携带index提供的token连接Registry
  • Registryindex合适token的合法性
  • index证实token的合法性
  • Registry开始接收客户端上传过来的镜像

5.3  搭建docker的私有仓库

5.3.1 搭建简单的Registry仓库

1.下载registry:
[root@docker-node1 ~]# docker load -i registry.tag.gz 

2.开启registry:
[root@docker-node1 ~]# docker run -d -p 5000:5000 --restart=always --name registry registry
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                                       NAMES
d771295578b6   registry   "/entrypoint.sh /etc…"   12 seconds ago   Up 11 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry
[root@docker-node1 ~]#

3.上传镜像到仓库中:

配置非加密端口:
[root@docker-node1 ~]# vim /etc/docker/daemon.json
{
"insecure-registries" : ["http://172.25.254.100:5000"]
}

[root@docker-node1 ~]# systemctl restart docker

#给要上传的镜像打标签:
[root@docker-node1 ~]# docker run -d -p 5000:5000 --restart=always --name registry registry

上传镜像:
[root@docker-node1 ~]# docker push 172.25.254.10:5000/nginx:v3

查看镜像上传:
[root@docker-node1 ~]# curl 172.25.254.10:5000/v2/_catalog
{"repositories":["nginx"]}
[root@docker-node1 ~]#

5.3.2 为Registry提加密传输

添加本地解析
[root@docker-node1 ~]# vim /etc/hosts
172.25.254.10   docker-node1.timingding.org reg.timingding.org

把非加密端口删掉:
[root@docker-node1 ~]# vim /etc/docker/daemon.json 
[root@docker-node1 ~]# systemctl restart docker

#生成认证key和证书
[root@docker-node1 ~]# mkdir certs
[root@docker-node1 ~]# openssl req -newkey rsa:4096 \
> -nodes -sha256 -keyout certs/timingding.org.key \
> -addext "subjectAltName = DNS:reg.timingding.org" \
> -x509 -days 365 -out certs/timingding.org.crt

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Shaanxi
Locality Name (eg, city) [Default City]:Xi'an
Organization Name (eg, company) [Default Company Ltd]:timingding
Organizational Unit Name (eg, section) []:docker
Common Name (eg, your name or your server's hostname) []:reg.timingding.org
Email Address []:admin@timingding.org
[root@docker-node1 ~]# 

启动registry仓库:
[root@docker-node1 ~]# docker run -d -p 443:443 --restart=always \
> --name registry \
> -v /root/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timingding.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/timingding.org.key registry

[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                                             NAMES
389b74065f0a   registry   "/entrypoint.sh /etc…"   44 seconds ago   Up 43 seconds   0.0.0.0:443->443/tcp, :::443->443/tcp, 5000/tcp   registry
[root@docker-node1 ~]# 

[root@docker-node1 ~]# docker tag nginx:v3 reg.timingding.org/nginx:v3

#为客户端建立证书:
[root@docker-node1 ~]# docker tag nginx:v3 reg.timingding.org/nginx:v3
[root@docker-node1 ~]# mkdir -p /etc/docker/certs.d/reg.timingding.org
[root@docker-node1 ~]# cp /root/certs/timingding.org.crt /etc/docker/certs.d/reg.timingding.org/ca.crt
[root@docker-node1 ~]# ls /etc/docker/certs.d/reg.timingding.org/ca.crt 
/etc/docker/certs.d/reg.timingding.org/ca.crt
[root@docker-node1 ~]# systemctl restart docker

测试:
[root@docker-node1 ~]# docker push reg.timingding.org/nginx:v3
[root@docker-node1 ~]# curl -k https://reg.timingding.org/v2/_catalog
{"repositories":["nginx"]}
[root@docker-node1 ~]#

 5.3.3 为仓库建立登录认证

[root@docker-node1 ~]# yum install httpd-tools -y

#建立认证文件
[root@docker-node1 ~]# mkdir auth
[root@docker-node1 ~]# htpasswd -Bc auth/htpasswd xiaoding  #-B表示强制使用最安全的加密方式,默认是md5加密
New password: 
Re-type new password: 
Adding password for user xiaoding
[root@docker-node1 ~]# 

查看建立的用户:
[root@docker-node1 ~]# cat auth/htpasswd
xiaoding:$2y$05$i3ol3ZYVjHTiIMkhV5xLVuWoYOckqOI/IK.tS7Cv0gBofvmHRcZIG
[root@docker-node1 ~]# 

#添加认证到registry容器中
[root@docker-node1 ~]# docker run -d -p 443:443 --restart=always --name registry \
> -v /root/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timingding.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/timingding.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-node1 ~]# docker login reg.timingding.org
Username: xiaoding
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@docker-node1 ~]# docker push reg.timingding.org/nginx:latest
[root@docker-node1 ~]# curl -k https://172.25.254.10/v2/_catalog -u xiaoding:123
{"repositories":["nginx"]}

[root@docker-node1 ~]# curl -k https://reg.timingding.org/v2/_catalog -u xiaoding:123
{"repositories":["nginx"]}
[root@docker-node1 ~]# 

5.4 搭建企业级私有仓库(harbor)

它提供了以下主要功能和特点:
  • 基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理的灵活性。
  • 镜像复制:支持在不同的 Harbor 实例之间复制镜像,方便在多个数据中心或环境中分发镜像。
  • 图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。
  • 审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。
  • 垃圾回收:可以清理不再使用的镜像,节省存储空间。

5.4.1 部署harbor

[root@docker-node1 ~]# tar zxf harbor-offline-installer-v2.5.4.tgz
[root@docker-node1 ~]# cd harbor/
[root@docker-node1 harbor]# cp harbor.yml.tmpl harbor.yml
hostname: reg.timingding.org
certificate: /data/certs/timingding.org.crt
private_key: /data/certs/timingding.org.key
harbor_admin_password: 123456

[root@docker-node1 harbor]# mkdir /data
[root@docker-node1 harbor]# cp /root/certs/ /data -r
[root@docker-node1 harbor]#  ./install.sh --with-chartmuseum

[root@docker-node1 harbor]# docker compose down
[root@docker-node1 harbor]# docker compose up -d

[root@docker-node1 harbor]# docker login reg.timingding.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@docker-node1 harbor]# 
[root@docker-node1 harbor]# docker tag nginx:v3 reg.timingding.org/timingding/nginx:v3
[root@docker-node1 harbor]# docker push reg.timingding.org/timingding/nginx:v3

去网页查看,镜像就传上去了

 5.5 docker的WebUI工具(图形化)

示例:

[root@docker-node1 ~]# tar zxf 1panel-v1.10.13-lts-linux-amd64.tar.gz
[root@docker-node1 ~]# cd 1panel-v1.10.13-lts-linux-amd64/

可以参考这个怎么安装:
[root@docker-node1 1panel-v1.10.13-lts-linux-amd64]# less README.md
[root@docker-node1 1panel-v1.10.13-lts-linux-amd64]# sh install.sh

设置 1Panel 安装目录(默认为/opt):
[1Panel Log]: 您选择的安装路径为 /opt 
[1Panel Log]: 检测到 Docker 已安装,跳过安装步骤 
[1Panel Log]: 启动 Docker  
设置 1Panel 端口(默认为10199):8888    
[1Panel Log]: 您设置的端口为:8888 
[1Panel Log]: 防火墙未开启,忽略端口开放 
设置 1Panel 安全入口(默认为25bc0375ea):
[1Panel Log]: 您设置的面板安全入口为:25bc0375ea 
设置 1Panel 面板用户(默认为7a7b5fd61c):
[1Panel Log]: 您设置的面板用户为:7a7b5fd61c 
[1Panel Log]: 设置 1Panel 面板密码(默认为de5d5fc846): 
[1Panel Log]: 配置 1Panel Service 
Created symlink /etc/systemd/system/multi-user.target.wants/1panel.service → /etc/systemd/system/1panel.service.
[1Panel Log]: 启动 1Panel 服务 
[1Panel Log]: 1Panel 服务启动成功! 
[1Panel Log]:  
[1Panel Log]: =================感谢您的耐心等待,安装已经完成================== 
[1Panel Log]:  
[1Panel Log]: 请用浏览器访问面板: 
[1Panel Log]: 外网地址: http://111.19.7.124:8888/25bc0375ea 
[1Panel Log]: 内网地址: http://172.25.254.10:8888/25bc0375ea 
[1Panel Log]: 面板用户: 7a7b5fd61c 
[1Panel Log]: 面板密码: de5d5fc846 
[1Panel Log]:  
[1Panel Log]: 项目官网: https://1panel.cn 
[1Panel Log]: 项目文档: https://1panel.cn/docs 
[1Panel Log]: 代码仓库: https://github.com/1Panel-dev/1Panel 
[1Panel Log]:  
[1Panel Log]: 如果使用的是云服务器,请至安全组开放 8888 端口 
[1Panel Log]:  
[1Panel Log]: 为了您的服务器安全,在您离开此界面后您将无法再看到您的密码,请务必牢记您的密码。 
[1Panel Log]:  
[1Panel Log]: ================================================================ 
[root@docker-node1 1panel-v1.10.13-lts-linux-amd64]#

这里用的默认密码,可以自己设置

访问:
[root@docker-node1 1panel-v1.10.13-lts-linux-amd64]# 1pctl user-info
面板地址: http://$LOCAL_IP:8888/25bc0375ea 
面板用户:  7a7b5fd61c
面板密码:  de5d5fc846
提示:修改密码可执行命令:1pctl update password
[root@docker-node1 1panel-v1.10.13-lts-linux-amd64]# 

网页访问:http://$LOCAL_IP:8888/25bc0375ea   ---- IP改为自己的本机IP


卸载:
[root@docker-node1 1panel-v1.10.13-lts-linux-amd64]# 1pctl uninstall

在这里面可以创建容器啊等等
在里面创建的容器,虚机里面是可以看到的

六、docker原生网络及自定义桥接网络

  • docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分
  • docker安装后会自动创建3种网络:bridgehostnone

6.1 原生网络(bridge)

查看docker网络:
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME                        DRIVER    SCOPE
bce404482df2   1panel-network              bridge    local
bed113946579   bridge                      bridge    local
df76de310ac6   harbor_harbor               bridge    local
34e7d4615f58   harbor_harbor-chartmuseum   bridge    local
ac0a6a238800   host                        host      local
3ee2d964b619   none                        null      local
[root@docker-node1 ~]# 

所有的容器都是通过docker0上网:

 

  • bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。

  • 容器通过宿主机的NAT规则后可以访问外网

 

 

默认使用的火墙设置为iptables:
红帽9里面默认使用的是nftables
[root@docker-node1 ~]# grubby --update-kernel ALL --args iptables=true
[root@docker-node1 ~]# reboot

查看火墙规则:
[root@docker-node1 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy DROP)
target     prot opt source               destination         
DOCKER-USER  0    --  0.0.0.0/0            0.0.0.0/0           
DOCKER-ISOLATION-STAGE-1  0    --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
DOCKER     0    --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain DOCKER (1 references)
target     prot opt source               destination         

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination         
DOCKER-ISOLATION-STAGE-2  0    --  0.0.0.0/0            0.0.0.0/0           
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           

Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target     prot opt source               destination         
DROP       0    --  0.0.0.0/0            0.0.0.0/0           
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           

Chain DOCKER-USER (1 references)
target     prot opt source               destination         
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           
[root@docker-node1 ~]# 

查看默认的nftables规则:
[root@docker-node1 ~]# nft list ruleset

[root@docker-node1 ~]# docker run -it --name webserver --network bridge busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:32 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:4750 (4.6 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 
网关是172.17.0.1,目前是可以ping通外网的
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0
/ # 

开启一个容器之后,火墙规则就会有:
[root@docker-node1 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     0    --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     0    --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  0    --  172.17.0.0/16        0.0.0.0/0           

MASQUERADE:地址伪装

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           
[root@docker-node1 ~]# 

如果把MASQUERADE停了,依旧可以上网,因为docker里面还有一个代理网络docker-proxy

6.2 原生网络(host)

  • host网络模式需要在容器创建时指定 --network=host

  • host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性

host就是跟主机网卡直连:

[root@docker-node1 ~]# docker run -it --rm --name test --network host busybox
/ # ifconfig 
docker0   Link encap:Ethernet  HWaddr 02:42:C7:EC:F9:C7  
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:c7ff:feec:f9c7/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:27 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:342 (342.0 B)  TX bytes:3868 (3.7 KiB)

ens160    Link encap:Ethernet  HWaddr 00:0C:29:86:A1:E3  
          inet addr:172.25.254.10  Bcast:172.25.254.255  Mask:255.255.255.0
          inet6 addr: fe80::fab3:2c21:57c9:1c93/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1669 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1142 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:310462 (303.1 KiB)  TX bytes:121531 (118.6 KiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:19 errors:0 dropped:0 overruns:0 frame:0
          TX packets:19 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:2569 (2.5 KiB)  TX bytes:2569 (2.5 KiB)

/ # 

  如果公用一个网络,那么所有的网络资源都是公用的,比如启动了nginx容器那么真实主机的80端口被占用,在启动第二个nginx容器就会失败

6.3 原生网络(none)

自定义网络模式,docker提供了三种自定义网络驱动:

  • bridge

  • overlay ---- 一般对于虚拟网络设定

  • macvlan --- 一般对于Mac地址设定

bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,

overlay(基本可以划分无限个子网)和macvlan(可以划分1024个子网)是用于创建跨主机网络

建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。

6.4 自定义桥接网络

自定义桥接中会有DNS模块,默认的桥接里面没有

示例:

复制两个会话做测试:
[root@docker-node1 ~]# docker run -it --rm --name test --network bridge busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:18 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2400 (2.3 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 

[root@docker-node1 ~]# docker run -it --name test1 --network bridge busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:03  
          inet addr:172.17.0.3  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:12 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1584 (1.5 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 

IP是变的跟你开启的顺序有关系,都是用容器名称进行通信,而不是IP
原生的桥接网络没有DNS插件,能ping通同一网段的容器,但是ping不通容器名称

/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.078 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.049 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.049/0.063/0.078 ms
/ # ping test1
ping: bad address 'test1'
/ # 

创建自定义桥接网络:
[root@docker-node1 ~]# docker network create mynet1 -d bridge 
42000ab88f06e2ccae51c51e6286f3df6f5d70fe93e3d0d2cbb57425aafc6ce8
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
aa8a935339ea   bridge    bridge    local
ac0a6a238800   host      host      local
42000ab88f06   mynet1    bridge    local
3ee2d964b619   none      null      local
[root@docker-node1 ~]# 

再重新开两个容器,都设定为自定义桥接网络:
[root@docker-node1 ~]# docker run -it --name test1 --network mynet1 busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:12:00:03  
          inet addr:172.18.0.3  Bcast:172.18.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:16 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2140 (2.0 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 

[root@docker-node1 ~]# docker run -it --rm --name test --network mynet1 busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:12:00:02  
          inet addr:172.18.0.2  Bcast:172.18.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:38 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:5564 (5.4 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # ping test1
PING test1 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.122 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.079 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.081 ms
^C
--- test1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.079/0.094/0.122 ms
/ # 

自定义bridge建好后就不需要关心容器的IP到底是多少,通过容器名字就能找到它。
6.4.1 如何让不同的自定义网络互通?

创建两个自定义网络:
[root@docker-node1 ~]# docker network create mynet1 -d bridge 
01823ba512719e8c367d58ed507e4b876b9d50491e48280f0cf433a0b51deb18
[root@docker-node1 ~]# docker network create mynet2 -d bridge 
999f170ca3139c87ce6239331bb1cc53f70ceef616c840fa64db918cb23e11f5
[root@docker-node1 ~]# 

创建两个容器:

想让两个容器能通信:
[root@docker-node1 ~]# docker network connect mynet1 test1

此时就可以ping通了
[root@docker-node1 ~]# docker run -it --rm --name test --network mynet1 busybox
/ # ping test1
PING test1 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.130 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.085 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.081 ms
^C
--- test1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.081/0.098/0.130 ms
/ # 


此时test1中就会有两个网卡:
[root@docker-node1 ~]# docker run -it --rm --name test1 --network mynet2 busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:13:00:02  
          inet addr:172.19.0.2  Bcast:172.19.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:40 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:5704 (5.5 KiB)  TX bytes:0 (0.0 B)

eth1      Link encap:Ethernet  HWaddr 02:42:AC:12:00:03  
          inet addr:172.18.0.3  Bcast:172.18.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:16 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2140 (2.0 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 
 6.4.2 joined容器网络

        Joined容器一种较为特别的网络模式,•在容器创建时使用--network=container:vm1指定。(vm1指定的是运行的容器名)

        处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。

[root@docker-node1 ~]# docker run -it --rm --name test --network mynet1 busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:12:00:02  
          inet addr:172.18.0.2  Bcast:172.18.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:17 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2330 (2.2 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 

再开一个:
[root@docker-node1 ~]# docker run -it --name test1 --network container:test busybox   --- 设置和test共用一个网卡
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:12:00:02  
          inet addr:172.18.0.2  Bcast:172.18.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:19 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2470 (2.4 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 
6.4.2.1 joined网络示例演示:

利用容器部署phpmyadmin管理mysql,两个容器共用一个网络。

[root@docker-node1 ~]# docker load -i mysql-5.7.tar.gz 
[root@docker-node1 ~]# docker load -i phpmyadmin-latest.tar.gz 

运行phpmysqladmin:
[root@docker-node1 ~]# docker run -d --name mysqladmin --network mynet1 \
> -e PMA_ARBITRARY=1 \		#在web页面中可以手动输入数据库地址和端口
> -p 80:80 phpmyadmin:latest
493dc1fff9879f93543acce56fe1999f38dd19238a700dfa32bdc100bb59f830
[root@docker-node1 ~]# 

运行数据库:
[root@docker-node1 ~]# docker run -d --name mysql --network container:mysqladmin \		#把数据库容器添加到phpmyadmin容器中
> -e MYSQL_ROOT_PASSWORD='xiaoding' \	#设定数据库密码
> mysql:5.7
b0da5fdd32a9ca243538e563aab0e6ee87670f5c2d155dc1bdff7ccab7d3a75a
[root@docker-node1 ~]# 

网页访问172.25.254.10

 

可以这样进入MySQL:
[root@docker-node1 ~]# docker exec -it mysql bash
bash-4.2# mysql -uroot -pxiaoding
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 22
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| TEST               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> show tables from TEST;
+----------------+
| Tables_in_TEST |
+----------------+
| user           |
+----------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM TEST.user;
+----------+----------+
| username | password |
+----------+----------+
| user1    | 123      |
+----------+----------+
1 row in set (0.01 sec)

mysql> 

在phpmysqladmin中可以进行MySQL的所有操作。

6.5  容器内外网的访问

6.5.1 容器访问外网

 

  • 在rhel7中,docker访问外网是通过iptables添加地址伪装策略来完成容器网文外网

  • 在rhel7之后的版本中通过nftables添加地址伪装来访问外网

开启一个容器之后:
[root@docker-node1 entries]# docker run --rm -it --name test busybox


[root@docker-node1 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     0    --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     0    --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  0    --  172.17.0.0/16        0.0.0.0/0           
###内网访问外网策略

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           
[root@docker-node1 ~]# 

把策略删掉之后,就访问不了了
[root@docker-node1 ~]# iptables -t nat -D POSTROUTING 1
[root@docker-node1 ~]# iptables -t nat -nL

如何恢复,重启docker就行了
6.5.2 外网访问docker容器

 端口映射 -p 本机端口:容器端口来暴漏端口从而达到访问效果

[root@docker-node1 ~]# docker run -d --name test --rm -p 80:80 nginx
cacce4cc68be640b6485aa00c435ecba3461fbec6acfde014472188a34a2f0f8
现在是可以访问到外网的

[root@docker-node1 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     0    --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     0    --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  0    --  172.17.0.0/16        0.0.0.0/0           
MASQUERADE  6    --  172.17.0.2           172.17.0.2           tcp dpt:80

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           
DNAT       6    --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:80

##通过DNAT访问到docker的172.17.0.2,然后再去访问外网的 ,如果把这条策略删掉,还是可以访问,外网访问内网不仅走proxy,还会走网络策略。

[root@docker-node1 ~]# 


docker的路由策略是由docker-proxy来做的

docker-proxy和dnat在容器建立端口映射后都会开启,那个传输速录高走那个

 6.5.3 docker容器的跨主机通信

在生产环境中,我们的容器不可能都在同一个系统中,所以需要容器具备跨主机通信的能力

  • 跨主机网络解决方案

        docker原生的overlay和macvlan

        第三方的flannel、weave、calico

  • 众多网络方案是如何与docker集成在一起的

        libnetwork docker容器网络库

        CNM (Container Network Model)这个模型对容器网络进行了抽象

 6.5.3.1 CNM(Container Network Model)

CNM分三类组件

  • Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace)

  • Endpoint:作用是将sandbox接入network (veth pair)

  • Network:包含一组endpoint,同一network的endpoint可以通信

 6.5.3.2 macvlan网络方式实现跨主机通信

macvlan网络方式

  • Linux kernel提供的一种网卡虚拟化技术。

  • 无需Linux bridge,直接使用物理接口,性能极好

  • 容器的接口直接与主机网卡连接,无需NAT或端口映射

  • macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络

  • vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094

macvlan网络间的隔离和连通

  • macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的

  • 可以在三层上通过网关将macvlan网络连通起来

  • docker本身不做任何限制,像传统vlan网络那样管理即可

示例:

1.在两台docker主机上各添加一块网卡,打开网卡混杂模式:

[root@docker ~]# ip link set eth1 promisc on
[root@docker ~]# ip link set up eth1

eth1这款网卡在vmware中要设定为仅主机模式

2.添加macvlan网络

[root@docker-node1 ~]# docker network create \
-d macvlan \
--subnet 1.1.1.0/24 \
--gateway 1.1.1.1 \
-o parent=eth1 macvlan1

3.测试

#在docker-node1中
[root@docker ~]# docker run -it --name busybox --network macvlan1 --ip 1.1.1.100
--rm busybox
/ # ping 1.1.1.200

[root@docker-node2 ~]# docker run -it --name busybox --network macvlan1 --ip
1.1.1.200 --rm busybox

 七、Docker数据卷管理及优化

         Docker 数据卷是一个可供容器使用的特殊目录,它绕过了容器的文件系统,直接将数据存储在宿主机上。

这样可以实现以下几个重要的目的:

  • 数据持久化:即使容器被删除或重新创建,数据卷中的数据仍然存在,不会丢失。

  • 数据共享:多个容器可以同时挂载同一个数据卷,实现数据的共享和交互。

  • 独立于容器生命周期:数据卷的生命周期独立于容器,不受容器的启动、停止和删除的影响。

7.1为什么要使用数据卷

docker 分层文件系统
  • 性能差
  • 生命周期与容器相同
docker 数据卷
  • mount到主机中,绕开分层文件系统
  • 和主机磁盘性能相同,容器删除后依然保留
  • 仅限本地磁盘,不能随容器迁移
docker 提供了两种卷:
  • bind mount
  • docker managed volume

7.2 bind mount 数据卷

  • 是将主机上的目录或文件mount到容器里。

  • 使用直观高效,易于理解。

  • 使用 -v 选项指定路径,格式 :

  • -v选项指定的路径,如果不存在,挂载时会自动创建

示例:

[root@docker-node1 ~]# docker run -it --rm \
> -v /tmp/data1:/data1 \
> -v /tmp/data1:/data2:ro \
> -v /etc/passwd:/data/passwd:ro busybox
/ # tail -n 3 /data/passwd 
tcpdump:x:72:72::/:/sbin/nologin
rhel:x:1000:1000:rhel:/home/rhel:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
/ # touch /data1/dingfile1
/ # touch /data2/dingfile1
touch: /data2/dingfile1: Read-only file system
/ # 

7.3 docker managed 数据卷

  • bind mount必须指定host文件系统路径,限制了移植性

  • docker managed volume 不需要指定mount源,docker自动为容器创建数据卷目录

  • 默认创建的数据卷目录都在 /var/lib/docker/volumes 中

  • 如果挂载时指向容器内已有的目录,原有数据会被复制到volume中

清理未使用的docker数据卷:

数据卷存放的目录:
[root@docker-node1 ~]# cd /var/lib/docker/volumes/

[root@docker-node1 volumes]# docker volume prune 

示例:

建立永久的数据卷:
[root@docker-node1 volumes]# docker volume create mysqldate
mysqldate
[root@docker-node1 volumes]# docker run -d --rm --name mysql -e MYSQL_ROOT_PASSWORD='ding' -v mysqldate:/var/lib/mysql mysql:5.7 
14e2d666df1aa642ce8bb151445120660855c8a806b8166eb7b0004d6a372ca9
[root@docker-node1 volumes]# docker inspect mysql

 "Mounts": [
            {
                "Type": "volume",
                "Name": "mysqldate",
                "Source": "/var/lib/docker/volumes/mysqldate/_data",
                "Destination": "/var/lib/mysql",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],

把容器停了,数据卷依旧还在
[root@docker-node1 _data]# docker stop mysql
[root@docker-node1 volumes]# ls
backingFsBlockDev  metadata.db  mysqldate
[root@docker-node1 volumes]# 

删除数据卷:
[root@docker-node1 volumes]# docker volume rm mysqldate 
mysqldate
[root@docker-node1 volumes]# docker volume ls
DRIVER    VOLUME NAME
[root@docker-node1 volumes]# ls
backingFsBlockDev  metadata.db
[root@docker-node1 volumes]# 

创建数据卷,使用的时候可以-v指定权限,可以做到和宿主机同步
[root@docker-node1 volumes]# docker volume create test
test
[root@docker-node1 volumes]# docker run -it --rm --name test -v test:/etc busybox
/ # ls
bin    dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
/ # cd /etc/
/etc # ls
group          hostname       hosts          localtime      mtab           network        nsswitch.conf  passwd         resolv.conf    shadow
/etc # 

可以设置为只读,不能进行其他操作
[root@docker-node1 volumes]# docker run -it --rm --name test -v test:/etc:ro busybox

7.4 bind mount数据卷和docker managed数据卷的对比

相同点:

  • 两者都是 host 文件系统中的某个路径

不同点

 7.5 docker中数据卷的备份与迁移

备份数据卷

[root@docker-node1 ~]# docker run -it --rm --name test -v test:/data busybox
/ # ls
bin    data   dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
/ # cd data/
/data # [root@docker-node1 ~]# Ctrl+pq,不要停掉docker

[root@docker-node1 ~]# docker run -it --volumes-from test --rm --name test1 busybox
/ # ls
bin    data   dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
/ # tar zcf /backup/data1.tar.gz /data1

数据恢复

docker run -it --name test -v leevol1:/data1 -v `pwd`:/backup busybox /bin/sh -c "tar zxf /backup/data1.tar.gz;/bin/sh"
/ # ls
backup data1 etc lib proc sys usr
bin dev home lib64 root tmp var
/ # cd data1/ 				#查看数据迁移情况
/data1 # ls
index.html leefile1

八、docker的安全优化

Docker容器的安全性,很大程度上依赖于Linux系统自身

评估Docker的安全性时,主要考虑以下几个方面:

  • Linux内核的命名空间机制提供的容器隔离安全

  • Linux控制组机制对容器资源的控制能力安全。

  • Linux内核的能力机制所带来的操作权限安全

  • Docker程序(特别是服务端)本身的抗攻击性。

  • 其他安全增强机制对容器安全性的影响

红帽9默认使用的是cgroup2,在观察资源限制的时候最好用cgroup,因为两个模式的某些路径是不一致的,换成cgroup之后需要重启生效
出于安全角度,是推荐使用cgroup2,它的隔离性移植性会更好
[root@docker-node1 ~]# grubby --update-kernel=/boot/vmlinuz-$(uname -r) \
> --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"
[root@docker-node1 ~]# reboot

开启了之后会看到cgroup的:
[root@docker-node1 ~]# mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/misc type cgroup (rw,nosuid,nodev,noexec,relatime,misc)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
[root@docker-node1 ~]#

 1 命名空间隔离的安全:

  • 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间。命名空间提供了最基础也最直接的隔离。

  • 与虚拟机方式相比,通过Linux namespace来实现的隔离不是那么彻底。

  • 容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作系统内核。

  • 在 Linux 内核中,有很多资源和对象是不能被 Namespace 化的,比如:磁盘等等

[root@docker-node1 ~]# docker run -d --name web nginx
eb5eb91dd6c0df918d97d283e3c718da9865ba1706dd59f72b30ccd3166708d6
[root@docker-node1 ~]# docker inspect web | grep Pid
            "Pid": 2114,
            "PidMode": "",
            "PidsLimit": null,
[root@docker-node1 ~]# 
[root@docker-node1 ~]# cd /proc/2114/ns/	#进程的namespace
[root@docker-node1 ns]# ls -d /sys/fs/cgroup/memory/docker/eb5eb91dd6c0df918d97d283e3c718da9865ba1706dd59f72b30ccd3166708d6/      #资源隔离信息
/sys/fs/cgroup/memory/docker/eb5eb91dd6c0df918d97d283e3c718da9865ba1706dd59f72b30ccd3166708d6/
[root@docker-node1 ns]#

2 控制组资源控制的安全:

  • 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。

  • Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等资源。

  • 确保当发生在容器内的资源压力不会影响到本地主机系统和其他容器,它在防止拒绝服务攻击(DDoS)方面必不可少

3 内核能力机制:

  • 能力机制(Capability)是Linux内核一个强大的特性,可以提供细粒度的权限访问控制。

  • 大部分情况下,容器并不需要“真正的”root权限,容器只需要少数的能力即可。

  • 默认情况下,Docker采用“白名单”机制,禁用“必需功能”之外的其他权限。

4 Docker服务端防护:

  • 使用Docker容器的核心是Docker服务端,确保只有可信的用户才能访问到Docker服务。

  • 将容器的root用户映射到本地主机上的非root用户,减轻容器和主机之间因权限提升而引起的安全问题。

  • 允许Docker 服务端在非root权限下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。这些子进程只允许在特定范围内进行操作。

8.1 Docker的资源限制及对CPU资源限制的方法

Linux Cgroups 的全称是 Linux Control Group。

  • 是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。

  • 对进程进行优先级设置、审计,以及将进程挂起和恢复等操作。

Linux Cgroups 给用户暴露出来的操作接口是文件系统

  • 它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。

  • 执行此命令查看:mount -t cgroup

  • 在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。

  • 在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录)。

  • 控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的参数指定。

8.1.1 限制CPU使用

1.限制cpu的使用量

[root@docker-node1 ~]# docker run -it --name test --rm ubuntu
root@90d5494ef89b:/# dd if=/dev/zero of=/dev/null &
[1] 10
root@90d5494ef89b:/# top
top - 02:22:41 up 22 min,  0 user,  load average: 0.75, 0.39, 0.15
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  8.7 us, 16.2 sy,  0.0 ni, 74.6 id,  0.0 wa,  0.2 hi,  0.2 si,  0.0 st 
MiB Mem :   1935.4 total,    482.9 free,    872.8 used,    744.8 buff/cache     
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.   1062.6 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                              
     10 root      20   0    2736   1408   1408 R  99.7   0.1   0:24.79 dd                                                                                   
      1 root      20   0    4588   3840   3328 S   0.0   0.2   0:00.01 bash                                                                                 
     11 root      20   0    8864   5376   3328 R   0.0   0.3   0:00.00 top 
     

限制:
[root@docker-node1 ~]# docker run -it --rm --name test --cpu-period 100000 --cpu-quota 2000 ubuntu
root@b04a77934f86:/# 
root@b04a77934f86:/# dd if=/dev/zero of=/dev/null & 
[1] 9
root@b04a77934f86:/# top
top - 02:30:59 up 31 min,  0 user,  load average: 0.01, 0.38, 0.32
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.2 sy,  0.0 ni, 99.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st 
MiB Mem :   1935.4 total,    453.5 free,    887.7 used,    760.0 buff/cache     
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.   1047.8 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                              
      9 root      20   0    2736   1536   1536 R   2.0   0.1   0:00.64 dd      #### 只给了它%2的使用量                                                                          
      1 root      20   0    4588   3968   3456 S   0.0   0.2   0:00.01 bash                                                                                 
     10 root      20   0    8864   5248   3200 R   0.0   0.3   0:00.00 top  
     
查看限制的值:
[root@docker-node1 ~]# cd /sys/fs/cgroup/cpu/docker/
[root@docker-node1 docker]# ls
[root@docker-node1 docker]# cd faa288326c778170a1a84f8d2d6912127524e33e127c5079d0166b6e512b4efe/
[root@docker-node1 faa288326c778170a1a84f8d2d6912127524e33e127c5079d0166b6e512b4efe]# ls
[root@docker-node1 faa288326c778170a1a84f8d2d6912127524e33e127c5079d0166b6e512b4efe]# cat cpu.cfs_quota_us
2000

给它大一点:
[root@docker-node1 faa288326c778170a1a84f8d2d6912127524e33e127c5079d0166b6e512b4efe]# echo 20000 > cpu.cfs_quota_us
[root@docker-node1 faa288326c778170a1a84f8d2d6912127524e33e127c5079d0166b6e512b4efe]# cat cpu.cfs_quota_us
20000


root@faa288326c77:/# top
top - 02:38:30 up 38 min,  0 user,  load average: 0.52, 0.23, 0.23
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.9 us,  2.2 sy,  0.0 ni, 96.8 id,  0.0 wa,  0.0 hi,  0.2 si,  0.0 st 
MiB Mem :   1935.4 total,    463.2 free,    877.7 used,    760.3 buff/cache     
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.   1057.7 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                              
     10 root      20   0    2736   1536   1536 R  20.3   0.1   0:13.72 dd     ####这里使用量就变多了                                                                              
      1 root      20   0    4588   3840   3328 S   0.0   0.2   0:00.01 bash                                                                                 
     12 root      20   0    8864   5248   3200 R   0.0   0.3   0:00.00 top   

2.限制cpu的优先级

这里我只有一个CPU核心,如果有多个核心,为了看效果,把CPU核心关掉留一个即可
如何关:
root@docker ~]# echo 0 > /sys/devices/system/cpu/cpu1/online

#开启容器并限制资源
[root@docker ~]# docker run -it --rm --cpu-shares 100 ubuntu #设定cpu优先级,最大为1024,值越大优先级越高
root@dc066aa1a1f0:/# dd if=/dev/zero of=/dev/null &
root@f2098579eb01:/# top
top - 02:53:13 up 53 min,  0 user,  load average: 2.00, 1.42, 0.75
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s): 39.3 us, 60.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.7 hi,  0.0 si,  0.0 st 
MiB Mem :   1935.4 total,    434.6 free,    904.0 used,    763.0 buff/cache     
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.   1031.4 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                              
      8 root      20   0    2736   1536   1536 R  8.9   0.1   1:34.95 dd                                                                                   
      9 root      20   0    8864   5248   3200 R   0.3   0.3   0:00.01 top                                                                                  
      1 root      20   0    4588   3712   3328 S   0.0   0.2   0:00.01 bash   
      

开启一个没有设定优先级的容器:
[root@docker-node1 ~]# docker run -it --rm --name test  ubuntu
root@a5e06a918559:/# dd if=/dev/zero of=/dev/null &
[1] 9
root@a5e06a918559:/# top
top - 02:49:59 up 50 min,  0 user,  load average: 1.91, 0.91, 0.46
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s): 34.5 us, 64.7 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.7 hi,  0.0 si,  0.0 st 
MiB Mem :   1935.4 total,    443.5 free,    895.6 used,    762.5 buff/cache     
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.   1039.9 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                              
      9 root      20   0    2736   1536   1536 R  80.9   0.1   3:50.40 dd                                                                                   
      1 root      20   0    4588   3968   3456 S   0.0   0.2   0:00.01 bash                                                                                 
     10 root      20   0    8864   5120   3072 R   0.0   0.3   0:00.02 top 

 8.1.2 docker中对内存使用的限制

[root@docker-node1 ~]# docker run  --name test -it --memory 200M --memory-swap 200M ubuntu
root@73dc6cce1be9:/# free -m
               total        used        free      shared  buff/cache   available
Mem:            1935         886         451          12         762        1048
Swap:           4095           0        4095
root@73dc6cce1be9:/# 

#查看容器内存使用限制
[root@docker-node1 ~]# cd /sys/fs/cgroup/memory/docker/
[root@docker-node1 docker]# 
[root@docker-node1 docker]# cd 73dc6cce1be9bcbd6a510284ccb2af7cf0b6b853ec651b566bf26f9256b1c0f5/
[root@docker-node1 73dc6cce1be9bcbd6a510284ccb2af7cf0b6b853ec651b566bf26f9256b1c0f5]# cat memory.memsw.limit_in_bytes 
209715200

示例:

拖入需要的工具包
[root@docker-node1 ~]# dnf install *rpm -y

[root@docker-node1 ~]# docker run -d --name test --memory 200M --memory-swap 200M nginx
d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779

[root@docker-node1 ~]# cd /sys/fs/cgroup/
[root@docker-node1 cgroup]# 
[root@docker-node1 cgroup]# cd memory/
[root@docker-node1 memory]# cd docker/
[root@docker-node1 docker]# cd d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779
[root@docker-node1 d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779]# cat memory.memsw.limit_in_bytes 
209715200

[root@docker-node1 d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779]# cgexec -g memory:docker/d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779

[root@docker-node1 d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779]# cgexec -g memory:docker/d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779 dd if=/dev/zero of=/dev/shm/bidfile bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.0434598 s, 2.4 GB/s
[root@docker-node1 d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779]# 

[root@docker-node1 d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779]# cgexec -g memory:docker/d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779 dd if=/dev/zero of=/dev/shm/bidfile bs=1M count=150
150+0 records in
150+0 records out
157286400 bytes (157 MB, 150 MiB) copied, 0.0533197 s, 2.9 GB/s
[root@docker-node1 d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779]#

最大限定了200M,超过200M就不行了
[root@docker-node1 d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779]# cgexec -g memory:docker/d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779 dd if=/dev/zero of=/dev/shm/bidfile bs=1M count=200
Killed
[root@docker-node1 d87068daf1621502be36791cb61616f7e9d898328faa224bde340e5b8484a779]# 

再创建一个不做限制的容器:
[root@docker-node1 ~]# docker run -d --name test --rm  nginx
ef79c5b4eb0d49cdf8ae065305d2b3340dc0bb664b33bcd7c2dcb174f0b7e904
[root@docker-node1 ~]# cgexec -g memory:docker/ef79c5b4eb0d49cdf8ae065305d2b3340dc0bb664b33bcd7c2dcb174f0b7e904 dd if=/dev/zero of=/dev/shm/bidfile bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 0.0690067 s, 3.0 GB/s
[root@docker-node1 ~]# 

[root@docker-node1 ~]# cgexec -g memory:docker/ef79c5b4eb0d49cdf8ae065305d2b3340dc0bb664b33bcd7c2dcb174f0b7e904 dd if=/dev/zero of=/dev/shm/bidfile bs=1M count=500
500+0 records in
500+0 records out
524288000 bytes (524 MB, 500 MiB) copied, 0.248194 s, 2.1 GB/s
[root@docker-node1 ~]# 
8.1.2.1 自建控制器
[root@docker-node1 ~]# mkdir -p /sys/fs/cgroup/memory/x1/
[root@docker-node1 ~]# ls /sys/fs/cgroup/memory/x1/
[root@docker-node1 ~]# echo 209715200 > /sys/fs/cgroup/memory/x1/memory.limit_in_bytes

[root@docker-node1 ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.0414235 s, 2.5 GB/s
[root@docker-node1 ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 0.0718438 s, 2.9 GB/s
[root@docker-node1 ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=300
300+0 records in
300+0 records out
314572800 bytes (315 MB, 300 MiB) copied, 0.193193 s, 1.6 GB/s
[root@docker-node1 ~]# 

把它恢复:
[root@docker-node1 ~]# rm -fr /dev/shm/bigfile
[root@docker-node1 ~]# echo 209715200 > /sys/fs/cgroup/memory/x1/memory.memsw.limit_in_bytes
[root@docker-node1 ~]# gexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=200
bash: gexec: command not found...
[root@docker-node1 ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=200
Killed
[root@docker-node1 ~]# 

 cgexec -g memory:doceker/容器id -g表示使用指定控制器类型

8.1.3 限制docker的磁盘io

[root@docker-node1 ~]# docker run -it --rm --device-write-bps /dev/nvme0n1:30M ubuntu
root@5897ef0fca2e:/# dd if=/dev/zero of=bigfile bs=1M count=500 oflag=direct    ---- 直接写入硬盘
^C328+0 records in
328+0 records out
343932928 bytes (344 MB, 328 MiB) copied, 10.9436 s, 31.4 MB/s

root@5897ef0fca2e:/# 

8.2 Docker的安全加固

解决Docker的默认隔离性

LXCFS 是一个为 LXC(Linux Containers)容器提供增强文件系统功能的工具。

资源可见性

  • LXCFS 可以使容器内的进程看到准确的 CPU、内存和磁盘 I/O 等资源使用信息。在没有 LXCFS时,容器内看到的资源信息可能不准确,这会影响到在容器内运行的应用程序对资源的评估和管理。

性能监控

  • 方便对容器内的资源使用情况进行监控和性能分析。通过提供准确的资源信息,管理员和开发人员可以更好地了解容器化应用的性能瓶颈,并进行相应的优化。

安装LXCFS

[root@docker-node1 mnt]# ls
dingfile  hgfs  lxcfs-5.0.4-1.el9.x86_64.rpm  lxc-libs-4.0.12-1.el9.x86_64.rpm  lxc-templates-4.0.12-1.el9.x86_64.rpm
[root@docker-node1 mnt]# dnf install lxc*.rpm -y

运行lxcfs并解决容器隔离性

[root@docker-node1 ~]# lxcfs /var/lib/lxcfs &
[root@docker-node1 ~]# cd /var/lib/lxcfs/
[root@docker-node1 lxcfs]# 
[root@docker-node1 lxcfs]# ls
cgroup  proc  sys
[root@docker-node1 lxcfs]# 

[root@docker-node1 lxcfs]# docker run -it --rm --name test -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw -v /var/lib/lxcfs/proc/stat:/proc/stat:rw -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw -m 200M \
> ubuntu
root@d170695c5f8b:/# free -m
               total        used        free      shared  buff/cache   available
Mem:             200           1         196           0           1         198
Swap:            400           0         400
root@d170695c5f8b:/# 
root@d170695c5f8b:/# df -h
Filesystem             Size  Used Avail Use% Mounted on
overlay                 15G   13G  2.6G  83% /
tmpfs                   64M     0   64M   0% /dev
tmpfs                  968M     0  968M   0% /sys/fs/cgroup
shm                     64M     0   64M   0% /dev/shm
/dev/mapper/rhel-root   15G   13G  2.6G  83% /etc/hosts
tmpfs                  968M     0  968M   0% /proc/asound
tmpfs                  968M     0  968M   0% /proc/acpi
tmpfs                  968M     0  968M   0% /proc/scsi
tmpfs                  968M     0  968M   0% /sys/firmware
root@d170695c5f8b:/# 

8.2.1 容器的特权

在容器中默认情况下即使我是容器的超级用户也无法修改某些系统设定,比如网络

没有任何特权的容器:
[root@docker-node1 ~]# docker run -it --rm --name test busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:14 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1836 (1.7 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # ip a a 1.1.1.1/24 dev eth0
ip: RTNETLINK answers: Operation not permitted
/ # 

        这是因为容器使用的很多资源都是和系统真实主机公用的,如果允许容器修改这些重要资源,系统的稳定性会变的非常差

        但是由于某些需要求,容器需要控制一些默认控制不了的资源,如何解决此问题,这时我们就要设置容器特权

[root@docker-node1 ~]# docker run -it --rm --name test --privileged busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:18 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2388 (2.3 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # ip a a 1.1.1.1/24 dev eth0
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
40: eth0@if41: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 1.1.1.1/24 scope global eth0
       valid_lft forever preferred_lft forever
/ # 
#如果添加了--privileged 参数开启容器,容器获得权限近乎于宿主机的root用户

8.2.2 容器的白名单

        --privileged=true 的权限非常大,接近于宿主机的权限,为了防止用户的滥用,需要增加限制,只提供给容器必须的权限。此时Docker 提供了权限白名单的机制,使用--cap-add添加必要的权限

capabilities手册地址:capabilities(7) - Linux manual page

[root@docker-node1 ~]# docker run --rm -it --cap-add NET_ADMIN busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
42: eth0@if43: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # 
/ # 
/ # ip a a 192.168.0.100/24 dev eth0   ##### 可以对网络进行设定
/ #  fdisk -l  						##### 无法对磁盘进行管理

九、容器编排工具Docker Compose

 9.1 Docker Compose的常用命令参数

docker-compose up :

  • 启动配置文件中定义的所有服务。

  • 可以使用 -d 参数在后台启动服务。

  • 可以使用-f 来指定yml文件

  • 例如: docker-compose up -d 。

docker-compose down :

  • 停止并删除配置文件中定义的所有服务以及相关的网络和存储卷。

docker-compose start :

  • 启动已经存在的服务,但不会创建新的服务。

docker-compose stop :

  • 停止正在运行的服务

docker-compose restart :

  • 重启服务。

9.1.1 服务状态查看

docker-compose ps :

  • 列出正在运行的服务以及它们的状态,包括容器 ID、名称、端口映射等信息。

docker-compose logs :

  • 查看服务的日志输出。可以指定服务名称来查看特定服务的日志。

9.1.1.1 示例
格式要求很高,规范一下
[root@docker-node1 ~]# vim ~/.vimrc
set ts=2 sw=2 ai et

最简单的写法:
[root@docker-node1 ~]# mkdir test
[root@docker-node1 ~]# cd test
[root@docker-node1 test]#
[root@docker-node1 test]# vim docker-compose.yml
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
      
  testnode:
    image: busybox:latest
    command: ["/bin/sh","-c","sleep 100000"]
    
[root@docker-node1 test]# docker compose up -d
[+] Running 3/3
 ✔ Network test_default       Created                                                                                                                   0.1s 
 ✔ Container test-testnode-1  Started                                                                                                                   0.5s 
 ✔ Container test-web-1       Started                                                                                                                   0.5s 
[root@docker-node1 test]# docker ps
CONTAINER ID   IMAGE            COMMAND                  CREATED         STATUS         PORTS                               NAMES
07495457a698   nginx:latest     "/docker-entrypoint.…"   6 seconds ago   Up 5 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   test-web-1
9a196b4ad59b   busybox:latest   "/bin/sh -c 'sleep 1…"   6 seconds ago   Up 6 seconds                                       test-testnode-1
[root@docker-node1 test]# 

[root@docker-node1 test]# docker compose stop         ----- 停止容器,但不会删除
[+] Stopping 2/2
 ✔ Container test-web-1       Stopped                                                                                                                   0.1s 
 ✔ Container test-testnode-1  Stopped                                                                                                                  10.1s 
[root@docker-node1 test]# docker compose start		 ------ 启动容器
[+] Running 2/2
 ✔ Container test-web-1       Started                                                                                                                   0.3s 
 ✔ Container test-testnode-1  Started                                                                                                                   0.2s 
[root@docker-node1 test]# docker compose down			------ 停止容器,并会把容器删除
[+] Running 3/3
 ✔ Container test-testnode-1  Removed                                                                                                                  10.1s 
 ✔ Container test-web-1       Removed                                                                                                                   0.1s 
 ✔ Network test_default       Removed                                                                                                                   0.1s 
[root@docker-node1 test]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@docker-node1 test]# 

如果名字变了,如何运行:
[root@docker-node1 test]# mv docker-compose.yml timingding.yml
[root@docker-node1 test]# ls
timingding.yml
[root@docker-node1 test]# 
[root@docker-node1 test]# docker compose up -d
no configuration file provided: not found
[root@docker-node1 test]# docker compose -f timingding.yml up -d    ---- 就必须得用-f指定文件
[+] Running 3/3
 ✔ Network test_default       Created                                                                                                                   0.0s 
 ✔ Container test-web-1       Started                                                                                                                   0.3s 
 ✔ Container test-testnode-1  Started                                                                                                                   0.4s 
[root@docker-node1 test]# 
[root@docker-node1 test]# docker compose -f timingding.yml down
[+] Running 3/3
 ✔ Container test-testnode-1  Removed                                                                                                                  10.1s 
 ✔ Container test-web-1       Removed                                                                                                                   0.1s 
 ✔ Network test_default       Removed                                                                                                                   0.1s 
[root@docker-node1 test]# 

如何查看容器日志:
[root@docker-node1 test]# docker compose -f timingding.yml logs web

9.1.2 构建和重新构建服务

docker-compose build :

  • 构建配置文件中定义的服务的镜像。可以指定服务名称来只构建特定的服务。

docker-compose up --build :

  • 启动服务并在启动前重新构建镜像。

9.1.2.1 示例:
[root@docker-node1 test]# cd /root/docker/
[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest
RUN touch /dingfile1

[root@docker-node1 docker]# vim ding
FROM busybox:lastest
RUN touch /dingfile2

[root@docker-node1 test]# vim docker-compose.yml 
services:
  test1:
    image: test1
    build:
      context: /root/docker
      dockerfile: Dockerfile
    command: ["/bin/sh","-c","sleep 100000"]
    container_name: ding1


  test2:
    image: test2
    build:
      context: /root/docker
      dockerfile: ding
    command: ["/bin/sh","-c","sleep 100000"]
    container_name: ding2
    
这样构建太慢了
[root@docker-node1 test]# docker compose up -d

查看是否开启:

[root@docker-node1 test]# docker compose ps
NAME      IMAGE     COMMAND                  SERVICE   CREATED         STATUS         PORTS
ding1     test1     "/bin/sh -c 'sleep 1…"   test1     2 minutes ago   Up 2 minutes   
ding2     test2     "/bin/sh -c 'sleep 1…"   test2     2 minutes ago   Up 2 minutes   
[root@docker-node1 test]# 
不是运行,直接构建:
默认是两个一起构建
[root@docker-node1 test]# docker compose build

只构建test1
[root@docker-node1 test]# docker compose build test1

检测语法写的是否有问题,不加-q的话没问题的话就直接把你写的打印出来,有问题就报错,加-q的话有问题就直接报错,没问题就啥也不干:
[root@docker-node1 test]# docker compose config -q 

 9.2 Docker Compose的yml文件

  • Docker Compose 的 YAML 文件用于定义和配置多容器应用程序的各个服务。以下是一个基本的

  • Docker Compose YAML 文件结构及内容解释:

一、服务(services)

服务名称(service1_name/service2_name等):

  • 每个服务在配置文件中都有一个唯一的名称,用于在命令行和其他部分引用该服务。

镜像(image):

  • 指定服务所使用的 Docker 镜像名称和标签。例如, image: nginx:latest 表示使用 nginx镜像的最新版本

端口映射(ports):

  • 将容器内部的端口映射到主机的端口,以便外部可以访问容器内的服务。例如, -"8080:80" 表示将主机的 8080 端口映射到容器内部的 80 端口。

环境变量(environment):

  • 为容器设置环境变量,可以在容器内部的应用程序中使用。例如, VAR1: value1 设置环境变量 VAR1 的值为 value1

存储卷(volumes):

  • 将主机上的目录或文件挂载到容器中,以实现数据持久化或共享。例如, -/host/data:/container/data 将主机上的 /host/data 目录挂载到容器内的/container/data 路径。

网络(networks):

  • 将服务连接到特定的网络,以便不同服务的容器可以相互通信

命令(command):

  • 覆盖容器启动时默认执行的命令。例如, command: python app.py 指定容器启动时运行python app.py 命令

二、网络(networks)

  • 定义 Docker Compose 应用程序中使用的网络。可以自定义网络名称和驱动程序等属性。

  • 默认情况下docker compose 在执行时会自动建立网路

三、存储卷(volumes)

  • 定义 Docker Compose 应用程序中使用的存储卷。可以自定义卷名称和存储位置等属性。

 9.2.1 示例:

端口映射:
[root@docker-node1 test]# vim docker-compose.yml 

services:
  test1:
    image: test1
    build:
      context: /root/docker
      dockerfile: Dockerfile
    command: ["/bin/sh","-c","sleep 100000"]
    container_name: ding1
    expose:			----- 端口映射,开启容器之后会把端口暴漏出来
      - 1234
[root@docker-node1 test]# docker compose up -d
[root@docker-node1 test]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS      NAMES
0910e1e2b807   test1     "/bin/sh -c 'sleep 1…"   15 seconds ago   Up 15 seconds   1234/tcp   ding1
[root@docker-node1 test]#

环境变量:
[root@docker-node1 test]# vim docker-compose.yml
services:
  test1:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: ding
      
[root@docker-node1 test]# docker compose up -d
[+] Running 2/2
 ✔ Network test_default    Created                                                                                                                                    0.1s 
 ✔ Container test-test1-1  Started                                                                                                                                    0.2s 
[root@docker-node1 test]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS                 NAMES
b13d5f08e50a   mysql:5.7   "docker-entrypoint.s…"   5 seconds ago   Up 5 seconds   3306/tcp, 33060/tcp   test-test1-1
[root@docker-node1 test]# docker inspect test-test1-1 

"Env": [
                "MYSQL_ROOT_PASSWORD=ding",     ---- 可以看到我们设定的变量
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "GOSU_VERSION=1.16",
                "MYSQL_MAJOR=5.7",
                "MYSQL_VERSION=5.7.44-1.el7",
                "MYSQL_SHELL_VERSION=8.0.35-1.el7"
            ],

存储卷:
[root@docker-node1 test]# vim docker-compose.yml
services:
  test1:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: ding
    volumes:
      - /opt/mysql_data:/var/lib/mysql
[root@docker-node1 test]# docker compose up -d
[root@docker-node1 test]# docker inspect test-test1-1

 "Mounts": [
            {
                "Type": "bind",
                "Source": "/opt/mysql_data",
                "Destination": "/var/lib/mysql",   --- 可以看到挂载到我们设定的地方了
                "Mode": "rw",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],


网络:
原生网络:
[root@docker-node1 test]# vim docker-compose.yml
services:
  test1:
    image: busybox:latest
    container:_name: ding
    command: ["/bin/sh","-c","sleep 100000"]
[root@docker-node1 test]# docker compose up -d
[+] Running 2/2
 ✔ Network test_default  Created                                                                                                                                      0.1s    ------ 会自建一个默认网络
 ✔ Container ding        Started                                                                                                                                      0.4s 
[root@docker-node1 test]# 
[root@docker-node1 test]# docker network ls
NETWORK ID     NAME           DRIVER    SCOPE
7da0b89f3de2   bridge         bridge    local
ac0a6a238800   host           host      local
3ee2d964b619   none           null      local
602bc369a3cf   test_default   bridge    local
[root@docker-node1 test]# 

指定网络:
[root@docker-node1 test]# vim docker-compose.yml
services:
  test1:
    image: busybox:latest
    container_name: ding
    command: ["/bin/sh","-c","sleep 100000"]
    network_mode: bridge
[root@docker-node1 test]# docker compose up -d
[+] Running 1/1									---- 就不会新建网络
 ✔ Container ding  Started                        
 [root@docker-node1 test]# docker exec -it ding sh
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:20 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2528 (2.4 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 

自建网络:
[root@docker-node1 test]# vim docker-compose.yml
services:
  test1:
    image: busybox:latest
    container_name: ding
    command: ["/bin/sh","-c","sleep 100000"]
    networks:
      - mynet1
      - mynet2
    
networks:
  mynet1:
    driver: bridge
    
  mynet2:
    driver: bridge
[root@docker-node1 test]# docker compose up -d
[+] Running 3/3
 ✔ Network test_mynet2  Created                                                                                                                                       0.0s     ---- 会新建两个网络
 ✔ Network test_mynet1  Created                                                                                                                                       0.1s 
 ✔ Container ding       Started                                                                                                                                       0.3s 
[root@docker-node1 test]# 
[root@docker-node1 test]# docker exec -it ding sh
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:13:00:02  
          inet addr:172.19.0.2  Bcast:172.19.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:41 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:6003 (5.8 KiB)  TX bytes:0 (0.0 B)

eth1      Link encap:Ethernet  HWaddr 02:42:AC:12:00:02  
          inet addr:172.18.0.2  Bcast:172.18.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:42 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:6085 (5.9 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 

9.2.2 网络设定示例:

[root@docker-node1 test]# vim docker-compose.yml
services:
  test:
    image: busybox:latest
    container_name: test
    command: ["/bin/sh","-c","sleep 10000"]
    network_mode: default

  test2:
    image: busybox:latest
    container_name: test2
    command: ["/bin/sh","-c","sleep 10000"]
    networks:
      - mynet1

networks:
  default:
    external: true
    name: bridge
    
  mynet1:
    driver: bridge

[root@docker-node1 test]# docker compose up -d
[+] Running 3/3
 ✔ Network test_mynet1  Created                                                                                                                                       0.1s 
 ✔ Container test2      Started                                                                                                                                       0.4s 
 ✔ Container test       Started                                                                                                                                       0.3s 
[root@docker-node1 test]# 

[root@docker-node1 test]# docker network ls
NETWORK ID     NAME          DRIVER    SCOPE
7da0b89f3de2   bridge        bridge    local
ac0a6a238800   host          host      local
3ee2d964b619   none          null      local
8babe8b3b10f   test_mynet1   bridge    local			----新建了mynet1,这个网络
[root@docker-node1 test]# 

指定IP:
[root@docker-node1 test]# vim docker-compose.yml
services:
  test:
    image: busybox:latest
    container_name: test
    command: ["/bin/sh","-c","sleep 10000"]
    network_mode: default

  test2:
    image: busybox:latest
    container_name: test2
    command: ["/bin/sh","-c","sleep 10000"]
    networks:
      - mynet1
      - mynet2
networks:
  default:
    external: true
    name: bridge

  mynet1:
    driver: bridge
    
  mynet2:
    ipam:
      driver: default
      config:
        - subnet: 172.26.0.0/24
          gateway: 172.26.0.254
[root@docker-node1 test]# docker compose up -d
[+] Running 4/4
 ✔ Network test_mynet1  Created                                                                                                                                       0.1s 
 ✔ Network test_mynet2  Created                                                                                                                                       0.1s 
 ✔ Container test       Started                                                                                                                                       0.3s 
 ✔ Container test2      Started                                                                                                                                       0.4s 
[root@docker-node1 test]# 
[root@docker-node1 test]# docker network ls
NETWORK ID     NAME          DRIVER    SCOPE
7da0b89f3de2   bridge        bridge    local
ac0a6a238800   host          host      local
3ee2d964b619   none          null      local
6fbd9656ab82   test_mynet1   bridge    local
1e4996a355f8   test_mynet2   bridge    local
[root@docker-node1 test]# 
[root@docker-node1 test]# docker exec -it test2 sh
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:AC:12:00:02  
          inet addr:172.18.0.2  Bcast:172.18.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:43 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:6090 (5.9 KiB)  TX bytes:0 (0.0 B)

eth1      Link encap:Ethernet  HWaddr 02:42:AC:1A:00:01  
          inet addr:172.26.0.1  Bcast:172.26.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:43 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:6080 (5.9 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.18.0.1      0.0.0.0         UG    0      0        0 eth0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0
172.26.0.0      0.0.0.0         255.255.255.0   U     0      0        0 eth1
/ # 

9.2.3 存储卷的示例:

 

[root@docker-node1 test]# vim docker-compose.yml
services:
  test:
    image: busybox:latest
    container_name: test
    command: ["/bin/sh","-c","sleep 10000"]
    network_mode: default

  test2:
    image: busybox:latest
    container_name: test2
    command: ["/bin/sh","-c","sleep 10000"]
    networks:
      - mynet1
      - mynet2
    volumes:				---- 就让test2使用
      - data:/data

networks:
  default:
    external: true
    name: bridge

  mynet1:
    driver: bridge

  mynet2:
    ipam:
      driver: default
      config:
        - subnet: 172.26.0.0/24
          gateway: 172.26.0.254

volumes:						----- 写参数
  data:
    name: test

[root@docker-node1 test]# docker compose up -d
[+] Running 5/5
 ✔ Network test_mynet1  Created                                                                                                                                       0.1s 
 ✔ Network test_mynet2  Created                                                                                                                                       0.1s 
 ✔ Volume "test"        Created                                                                                                                                       0.0s 
 ✔ Container test       Started                                                                                                                                       0.3s 
 ✔ Container test2      Started                                                                                                                                       0.4s 
[root@docker-node1 test]# 
[root@docker-node1 test]# docker inspect test2

"Mounts": [
            {
                "Type": "volume",
                "Name": "test",
                "Source": "/var/lib/docker/volumes/test/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],

[root@docker-node1 test]# docker exec -it test2 sh
/ # ls
bin    data   dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
/ # cd data/
/data # touch ding
/data # ls
ding
/data #

[root@docker-node1 test]# docker compose down
[+] Running 4/4
 ✔ Container test       Removed                                                                                                                                      10.2s 
 ✔ Container test2      Removed                                                                                                                                      10.3s 
 ✔ Network test_mynet2  Removed                                                                                                                                       0.1s 
 ✔ Network test_mynet1  Removed                                                                                                                                       0.2s 
[root@docker-node1 test]# cd /var/lib/docker/volumes/test
[root@docker-node1 test]# 
[root@docker-node1 test]# ls
_data
[root@docker-node1 test]# cd _data/
[root@docker-node1 _data]# ls
ding
[root@docker-node1 _data]# 

 9.3 docker compose在企业中的示例

利用容器编排完成haproxy和nginx负载均衡架构实施  

[root@docker-node2 ~]# docker load -i haproxy-2.3.tar.gz 
[root@docker-node1 test]# mkdir /var/lib/docker/volumes/conf
[root@docker-node1 ~]# dnf install haproxy -y --downloadonly --downloaddir=/mnt
[root@docker-node1 ~]# cd /mnt/
[root@docker-node1 mnt]# rpm2cpio haproxy-2.4.22-3.el9_3.x86_64.rpm | cpio -id
[root@docker-node1 mnt]# cd etc/
[root@docker-node1 etc]# ls
haproxy  logrotate.d  sysconfig
[root@docker-node1 etc]# cd haproxy/
[root@docker-node1 haproxy]# ls
conf.d  haproxy.cfg
[root@docker-node1 haproxy]# cp haproxy.cfg /var/lib/docker/volumes/conf/
[root@docker-node1 haproxy]# cd /var/lib/docker/volumes/conf/ 
[root@docker-node1 conf]# ls
haproxy.cfg
[root@docker-node1 conf]# vim haproxy.cfg 
listen webcluter
  bind *:80
  balance roundrobin
  server web1 webserver1:80 check inter 3 fall 3 rise 5
  server web2 webserver2:80 check inter 3 fall 3 rise 5

[root@docker-node2 test]# vim haproxy.yml
 services:
  web1:
    image: nginx:latest
    container_name: webserver1
    restart: always
    expose:
      - 80
    volumes:
      - data_web1:/usr/share/nginx/html
    networks:
      - internel

  web2:
    image: nginx:latest
    container_name: webserver2
    restart: always
    expose:
      - 80
    volumes:
      - data_web2:/usr/share/nginx/html
    networks:
      - internel

  haproxy:
    image: haproxy:2.3
    restart: always
    container_name: haproxy
    ports:
      - "80:80"
    volumes:
      - /var/lib/docker/volumes/conf/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg

    networks:
      - internel
      - extrnal

networks:
  internel:
    driver: bridge

  extrnal:
    driver: bridge

volumes:
  data_web1:
    name: data_web1

  data_web2:
    name: data_web2
[root@docker-node2 test]# docker compose -f haproxy.yml config -q
[root@docker-node2 test]# docker compose -f haproxy.yml up -d
[+] Running 7/7
 ✔ Network test_internel  Created                                                                                                                                     0.1s 
 ✔ Network test_extrnal   Created                                                                                                                                     0.1s 
 ✔ Volume "data_web2"     Created                                                                                                                                     0.0s 
 ✔ Volume "data_web1"     Created                                                                                                                                     0.0s 
 ✔ Container haproxy      Started                                                                                                                                     1.2s 
 ✔ Container webserver1   Started                                                                                                                                     1.2s 
 ✔ Container webserver2   Started                                                                                                                                     1.1s 
[root@docker-node2 test]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                               NAMES
7158668dd70f   nginx:latest   "/docker-entrypoint.…"   7 seconds ago   Up 6 seconds   80/tcp                              webserver2
8aa9a99597df   haproxy:2.3    "docker-entrypoint.s…"   7 seconds ago   Up 6 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   haproxy
d5f6b242b8e1   nginx:latest   "/docker-entrypoint.…"   7 seconds ago   Up 6 seconds   80/tcp                              webserver1

 

写入内容:
[root@docker-node2 test]# echo webserver1 > /var/lib/docker/volumes/data_web1/_data/index.html
[root@docker-node2 test]# echo webserver2 > /var/lib/docker/volumes/data_web2/_data/index.html
[root@docker-node2 test]# curl 172.25.254.200
webserver2
[root@docker-node2 test]# curl 172.25.254.200
webserver1
[root@docker-node2 test]# curl 172.25.254.200
webserver2
[root@docker-node2 test]# curl 172.25.254.200
webserver1
[root@docker-node2 test]# 

如何大批量给容器打标签:

[root@docker-harbor ~]# docker images | awk 'NR>1{system("docker tag "$1":"$2" reg.timingding.org/library/"$1":"$2"")}'

 如何大批量上传镜像:

[root@docker-harbor ~]# docker images | awk '/reg.timingding.org/{system("docker push "$1":"$2"")}'

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

俗庸203

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值