当前位置: 首页 > article >正文

工程师们都爱看的Docker容器技术,一看就会!保姆级教程(上)

文章目录

      • Docker简介
        • Docker在企业中的应用场景
        • Docker与虚拟化的对比
        • Docker的优势
      • 部署Docker
      • 部署Docker
      • Docker的基本操作
        • Docker镜像管理
        • 容器的常用操作
      • Docker镜像构建
        • Docker镜像结构
        • 镜像运行的基本原理
        • 镜像获得方式
        • 镜像构建
        • Docker镜像构建企业实例
      • 镜像优化方案
        • 镜像优化策略
        • 镜像优化案例
      • Docker镜像仓库的管理
        • Docker仓库介绍
        • docker hub
        • Docker仓库的工作原理
          • pull原理
          • push原理
        • 搭建Docker私有仓库
          • 搭建简单的Registry仓库
          • 为Registry提供加密传输
          • 为仓库建立登陆认证
        • 构建企业级私有仓库
          • harbor简介
          • 部署harbor
      • Docker网络
        • 原生bridge网络
        • 原生网络host
        • 原生网络none
        • docker的自定义网络
          • 自定义桥接网络
        • docker容器间的网络通信
        • docker跨主机网络
          • CNM(Container Network Model)
          • macvlan网络方式实现跨主机通信

Docker简介

在这里插入图片描述

  • Docker是管理容器的引擎,为应用打包、部署平台,而非单纯的虚拟化技术,它具有以下几个重要特点和优势:
    1. 轻量级虚拟化
      • Docker 容器相较于传统的虚拟机更加轻量和高效,能够快速启动和停止,节省系统资源。
      • 例如,启动一个 Docker 容器可能只需要几秒钟,而启动一个虚拟机则可能需要几分钟。
    2. 一致性
      • 确保应用程序在不同的环境中(如开发、测试、生产)具有一致的运行表现。
      • 无论在本地还是云端,应用的运行环境都能保持相同,减少了因环境差异导致的问题。
    3. 可移植性
      • 可以轻松地将 Docker 容器从一个平台迁移到另一个平台,无需担心依赖和环境配置的差异。
      • 比如,在本地开发的容器可以无缝部署到云服务器上。
    4. 高效的资源利用
      • 多个 Docker 容器可以共享主机的操作系统内核,从而更有效地利用系统资源。
    5. 易于部署和扩展
      • 能够快速部署新的应用实例,并且可以根据需求轻松地进行水平扩展。

总之,Docker 极大地简化了应用程序的开发、部署和管理流程,提高了开发效率和运维的便利性。它在现代软件开发和云计算领域得到了广泛的应用。

Docker在企业中的应用场景

在这里插入图片描述

  • 在企业中docker作为业务的最小载体而被广泛应用

  • 通过docker企业可以更效率的部署应用并更节省资源

IaaS(Infrastructure as a Service),即基础设施即服务

PaaS是(Platform as a Service)即指平台即服务

SaaS(Software as a Service)软件运营服务

Docker与虚拟化的对比

在这里插入图片描述

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

  • 对于运维人员:Configure once、Run anything

  • 容器技术大大提升了IT人员的幸福指数!

部署Docker

部署Docker

[root@docker-node1 ~]# ls
anaconda-ks.cfg                                    docker.tar.gz
containerd.io-1.7.20-3.1.el9.x86_64.rpm            Documents
Desktop                                            Downloads
docker-buildx-plugin-0.16.2-1.el9.x86_64.rpm       Music
docker-ce-27.1.2-1.el9.x86_64.rpm                  Pictures
docker-ce-cli-27.1.2-1.el9.x86_64.rpm              Public
docker-ce-rootless-extras-27.1.2-1.el9.x86_64.rpm  Templates
docker-compose-plugin-2.29.1-1.el9.x86_64.rpm      Videos

[root@docker-node1 ~]# yum install *.rpm -y
[root@docker-node1 ~]# yum install docker-ce -y
[root@docker-node1 ~]# systemctl enable --now docker
[root@docker-node1 ~]# docker load -i game2048.tar.gz
[root@docker-node1 ~]# docker load -i nginx-latest.tar.gz
[root@docker-node1 ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED       SIZE
nginx                latest    5ef79149e0ec   12 days ago   188MB
timinglee/game2048   latest    19299002fdbe   7 years ago   55.5MB
[root@docker-node1 ~]# docker run -d --rm --name webserver -p 80:80 nginx
d274ec6c9dfe05bbaea2c10624802bee9a32f6f8e751083b6a103bac9c9e37bb
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                               NAMES
d274ec6c9dfe   nginx     "/docker-entrypoint.…"   9 seconds ago   Up 8 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   webserver

在这里插入图片描述

[root@docker-node1 ~]# docker rm -f webserver 
webserver
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@docker-node1 ~]# docker run -d --rm --name game1 -p 80:80 timinglee/game2048:latest 
396e7333bd16d406550a19234cdc1976d5ddaaea889ba9f57b3f242702f29029
[root@docker-node1 ~]# docker rm -f game1 
game1

在这里插入图片描述

[root@docker-node1 ~]# docker load -i mario.tar.gz 
4aeeaca5ce76: Loading layer  197.2MB/197.2MB
708fd576a927: Loading layer  208.9kB/208.9kB
90222f49bc4c: Loading layer  4.608kB/4.608kB
5f70bf18a086: Loading layer  1.024kB/1.024kB
dbe97b1b7330: Loading layer  1.536kB/1.536kB
44e5704d49fb: Loading layer  9.912MB/9.912MB
Loaded image: timinglee/mario:latest
[root@docker-node1 ~]# docker load -i busybox-latest.tar.gz 
d51af96cf93e: Loading layer  4.495MB/4.495MB
Loaded image: busybox:latest
[root@docker-node1 ~]# docker run -d --rm --name game2 -p 80:80 timinglee/mario:latest
62fb4d38e35435ee0d414838d5a3cb63a0b7b528d5be8f659d6ee036674634f1

在这里插入图片描述

Docker的基本操作

Docker镜像管理
# 搜索镜像
[root@docker-node1 ~]# docker search nginx
NAME                              DESCRIPTION                                     STARS     OFFICIAL
nginx                             Official build of Nginx.                        20126     [OK]
nginx/nginx-quic-qns              NGINX QUIC interop                              1         

参数说明
NAME镜像名称
DESCRIPTION镜像说明
STARS点赞数量
OFFICIAL是否是官方的
# 拉取镜像
#从镜像仓库中拉取镜像
[root@docker-node1 ~]# docker pull busybox
[root@docker-node1 ~]# docker pull nginx:1.26-alpine  # alpine 版本:nginx镜像的最小安装发型版本

# 查看本地镜像
[root@docker-node1 ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
example              v4        9af00573858d   4 hours ago     4.26MB
example              v2        2dbbb3e21285   4 hours ago     4.26MB
example              v3        6b6df0f84577   4 hours ago     4.26MB
example              v1        f4eed4b6a9f0   4 hours ago     4.26MB
nginx                latest    5ef79149e0ec   12 days ago     188MB
busybox              latest    65ad0d468eb1   15 months ago   4.26MB
timinglee/game2048   latest    19299002fdbe   7 years ago     55.5MB
timinglee/mario      latest    9a35a9e43e8c   8 years ago     198MB

# 查看镜像信息
[root@docker-node1 ~]# docker image inspect nginx:latest

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

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

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

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

# 删除镜像
[root@Docker-node1 ~]# docker rmi nginx:latest
[root@Docker-node1 ~]# docker rmi `docker images | awk 'NR>1{print $1":"$2}'`
容器的常用操作
# 启动容器
[root@Docker-node1 ~]# docker run -d --name mario -p 80:8080 timinglee/mario

#查看当前运行容器
[root@Docker-node1 ~]# docker ps	
#查看所有容器
[root@Docker-node1 ~]# docker ps -a	
#查看容器运行的详细信息
[root@Docker-node1 ~]# docker inspect busybox	
#停止容器
[root@Docker-node1 ~]# docker stop busybox 
#杀死容器
[root@Docker-node1 ~]# docker kill busybox 
#开启停止的容器
[root@Docker-node1 ~]# docker start busybox 
#删除停止的容器
[root@Docker-node1 ~]# docker rm centos7 
#删除运行的容器
[root@Docker-node1 ~]# docker rm -f busybox 
#删除所有停止的容器
[root@Docker-node1 ~]# docker container prune -f 

容器内容提交

默认情况下,容器被删除后,在容器中的所有操作都会被清理,包括要保存的文件

如果想永久保存,那么我们需要把动作提交,提交后会生成新的镜像

当我们在运行新镜像后即可看到我们提交的内容

[root@docker-node1 ~]# docker run -it --name test busybox
/ # touch leefile
/ # ls
bin      etc      leefile  lib64    root     tmp      var
dev      home     lib      proc     sys      usr
/ # 
[root@docker-node1 ~]# docker rm -f test
test
[root@docker-node1 ~]# docker run -it --name test busybox
/ # ls
bin    dev    etc    home   lib    lib64  proc   root   sys    tmp    usr    var
/ # 
[root@docker-node1 ~]# docker commit -m "add leefile" test busybox:v1
sha256:69ff2472a1ff1a75046ee767efdaabb1f32670118a05dd3f45af0aa31b6cbee6
[root@docker-node1 ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
busybox              v1        69ff2472a1ff   9 seconds ago   4.26MB
[root@docker-node1 ~]# docker image history busybox:v1
IMAGE          CREATED          CREATED BY                          SIZE      COMMENT
69ff2472a1ff   52 seconds ago   sh                                  8B        add leefile
65ad0d468eb1   15 months ago    BusyBox 1.36.1 (glibc), Debian 12   4.26MB    

系统中的文件和容器中的文件传输

#把容器中的文件复制到本机
[root@docker-node1 ~]# docker cp test:/leefile /mnt
Successfully copied 1.54kB to /mnt
#把本机文件复制到容器中
[root@docker-node1 ~]# docker cp /etc/fstab test:/fstab
Successfully copied 2.56kB to test:/fstab

Docker镜像构建

Docker镜像结构

在这里插入图片描述

  • 共享宿主机的kernel

  • base镜像提供的是最小的Linux发行版

  • 同一docker主机支持运行多种Linux发行版

  • 采用分层结构的最大好处是:共享资源

镜像运行的基本原理

在这里插入图片描述

  • Copy-on-Write 可写容器层

  • 容器层以下所有镜像层都是只读的

  • docker从上往下依次查找文件

  • 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改

  • 一个镜像最多127层

镜像获得方式

国内可以访问的docker镜像加速器:https://docker.m.daocloud.io

openeuler操作系统的docker镜像拉取地址:https://hub.oepkgs.net

  • 基本镜像通常由软件官方提供

  • 企业镜像可以用官方镜像+Dockerfile来生成

  • 系统关于镜像的获取动作有两种:

    • docker pull 镜像地址
    • docker load –i 本地镜像包
镜像构建
[root@docker-node1 ~]# mkdir docker
[root@docker-node1 ~]# cd docker/
[root@docker-node1 docker]# touch leefile
[root@docker-node1 docker]# 
[root@docker-node1 docker]# vim Dockerfile
# 指定使用的基础镜像
FROM busybox:latest
# 指定作者信息
MAINTAINER qwe@example.com
# 复制当前目录文件到容器指定位置,leefile必须在当前目录中
COPY leefile /

# 构建镜像
[root@docker-node1 docker]# docker build -t example:v1 .
[+] Building 0.0s (7/7) FINISHED                                          docker:default
 => [internal] load build definition from Dockerfile                                0.0s
 => => transferring dockerfile: 99B                                                 0.0s
 => WARN: MaintainerDeprecated: Maintainer instruction is deprecated in favor of u  0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                   0.0s
 => [internal] load .dockerignore                                                   0.0s
 => => transferring context: 2B                                                     0.0s
 => [internal] load build context                                                   0.0s
 => => transferring context: 28B                                                    0.0s
 => [1/2] FROM docker.io/library/busybox:latest                                     0.0s
 => [2/2] COPY leefile /                                                            0.0s
 => exporting to image                                                              0.0s
 => => exporting layers                                                             0.0s
 => => writing image sha256:f4eed4b6a9f08f469e4ec2d63c14d412497f8c5e8dc7f0568c2c68  0.0s
 => => naming to docker.io/library/example:v1                                       0.0s

 1 warning found (use docker --debug to expand):
 - MaintainerDeprecated: Maintainer instruction is deprecated in favor of using label (line 2)
 
[root@docker-node1 docker]# touch leefile{1..5}
[root@docker-node1 docker]# tar zcf leefile.gz leefile*
[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest
MAINTAINER qwe@example.com
COPY leefile /
ADD leefile.gz /

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

[root@docker-node1 docker]# docker run -it --rm --name test example:v2
/ # ls
bin       home      leefile2  leefile5  proc      tmp
dev       leefile   leefile3  lib       root      usr
etc       leefile1  leefile4  lib64     sys       var

[root@docker-node1 docker]# vim Dockerfile 
FROM busybox
MAINTAINER lee@timinglee.org
ENV NAME lee
CMD echo $NAME
#CMD ["/bin/echo", "$NAME"]
#CMD ["/bin/sh", "-c", "/bin/echo $NAME"]

[root@docker-node1 docker]# docker build -t example:v3 .
[root@Docker-node1 docker]# docker run -it --rm --name test example:v3
lee

[root@docker-node1 docker]# vim Dockerfile
FROM busybox
MAINTAINER lee@timinglee.org
ENV NAME lee
ENTRYPOINT echo $NAME

# 更改完配置文件Dockerfile过后要重新build创建一下
[root@docker-node1 docker]# docker build -t example:v3 .
[root@Docker-node1 docker]# docker run -it --rm --name test example:v3 sh
lee

[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest		# 指定镜像
MAINTAINER qwe@example.com		# 指定作者信息
COPY leefile /		# 复制文件
ADD leefile.gz /		# 功能和copy相似,指定压缩文件或url
ENV NAME lee		# 指定环境变量
#CMD echo $NAME		# 在启动容器时自动运行动作可以被覆盖
#CMD ["/bin/echo", "$NAME"]
#CMD ["/bin/sh", "-c", "/bin/echo $NAME"]
#ENTRYPOINT echo $NAME		# 和CMD功能和用法类似,但动作不可被覆盖
EXPOSE 80 443		# 暴漏容器端口
VOLUME /var/www/html		# 申明数据卷,通常指数据挂载点
WORKDIR /var/www/html		# 切换路径
RUN touch leefile		# 在容器中运行的指令

[root@Docker-node1 docker]# docker build -t example:v4 .
[root@docker-node1 docker]# docker run -it --rm --name test example:v4
/var/www/html # 
Docker镜像构建企业实例
# 导入镜像包
[root@docker-node1 ~]# ll
total 880900
-rw-r--r--  1 root root   1244738 Aug 16 09:17 nginx-1.26.1.tar.gz
[root@docker-node1 mnt]# ll
total 206740
-rw-r--r--  1 root root 211699200 Aug 26 19:23 centos-7.tar.gz
[root@docker-node1 mnt]# cd
[root@docker-node1 ~]# docker load -i /mnt/centos-7.tar.gz 
174f56854903: Loading layer  211.7MB/211.7MB
Loaded image: centos:7
[root@docker-node1 mnt]# ls
1panel-v1.10.13-lts-linux-amd64         debian11.tar.gz  leefile
1panel-v1.10.13-lts-linux-amd64.tar.gz  docker           nginx-1.23.tar.gz
centos-7.tar.gz                         hgfs             nginx-1.26.1.tar.gz

[root@docker-node1 docker]# vim Dockerfile
FROM centos:7
LABEL Mail=ccc@example.com
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1.tar.gz
RUN yum install -y gcc make pcre-devel openssl-devel
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 .
[+] Building 0.0s (6/11)                                                         docker:default
 => [internal] load build definition from Dockerfile                                       0.0s
 => => transferring dockerfile: 418B                                                       0.0s
 => [internal] load metadata for docker.io/library/centos:7                                0.0s
 => [internal] load .dockerignore                                                          0.0s
 => => transferring context: 2B                                                            0.0s
 => [internal] load build context                                                          0.0s
 => => transferring context: 2B                                                            0.0s
 => [1/7] FROM docker.io/library/centos:7                                                  0.0s
 => ERROR [2/7] ADD nginx-1.26.1.tar.gz /mnt                                               0.0s
------
 > [2/7] ADD nginx-1.26.1.tar.gz /mnt:
------
Dockerfile:3
--------------------
   1 |     FROM centos:7
   2 |     LABEL Mail=ccc@example.com
   3 | >>> ADD nginx-1.26.1.tar.gz /mnt
   4 |     WORKDIR /mnt/nginx-1.26.1.tar.gz
   5 |     RUN yum install -y gcc make pcre-devel openssl-devel
--------------------
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref ec302262-d1f5-46e0-970b-e52188d86dbd::ibej66oz3wnwfuosb1sennis0: "/nginx-1.26.1.tar.gz": not found

# 解决报错
[root@docker-node1 docker]# mv /mnt/nginx-1.26.1.tar.gz .
[root@docker-node1 docker]# ls
Dockerfile  nginx-1.26.1.tar.gz

# 再次构建镜像还是会报错,原因为连接网上的仓库失败,centos的镜像出现问题,为了解决这个问题,我们自己构建环境实现实验效果
[root@docker-node1 docker]# docker build -t nginx:v1 .

[root@docker-node1 docker]# dnf install httpd -y
# 修改监听端口,默认的80端口被nginx占用
[root@docker-node1 docker]# vim /etc/httpd/conf/httpd.conf
Listen 8888
[root@docker-node1 docker]# systemctl start httpd

在docker-node1主机上添加一个镜像

在这里插入图片描述
使用RHEL7.9的镜像
在这里插入图片描述

[root@docker-node1 docker]# mkdir /var/www/html/rhel7.9
[root@docker-node1 docker]# mount /dev/sr1 /var/www/html/rhel7.9/
mount: /var/www/html/rhel7.9: WARNING: source write-protected, mounted read-only.

在这里插入图片描述

[root@docker-node1 docker]# docker run -it --name centos centos:7
[root@53c7885f4588 /]# ls
anaconda-post.log  dev  home  lib64  mnt  proc  run   srv  tmp  var
bin                etc  lib   media  opt  root  sbin  sys  usr
[root@53c7885f4588 /]# ifconfig
bash: ifconfig: command not found
[root@53c7885f4588 /]# ip a
bash: ip: command not found
# 查看容器网络发现看不了
# 再开一个终端

[root@docker-node1 mnt]# docker inspect centos
           "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null,
                    "NetworkID": "1eb8f79c5ad647bc30d498cdb10a8510b9c884d918c2b59a279466f0c7240e5a",
                    "EndpointID": "89142da2c2219df6764e268a6340e67d9d0584e4116bfad91ed0233a858737fd",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DNSNames": null


# 容器网络IP为172.17.0.3
[root@docker-node1 mnt]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.142 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.072 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1035ms
rtt min/avg/max/mdev = 0.072/0.107/0.142/0.035 ms



[root@53c7885f4588 /]# cd /etc/yum.repos.d/
[root@53c7885f4588 yum.repos.d]# ls
CentOS-Base.repo  CentOS-Debuginfo.repo  CentOS-Sources.repo  CentOS-fasttrack.repo
CentOS-CR.repo    CentOS-Media.repo      CentOS-Vault.repo    CentOS-x86_64-kernel.repo
[root@53c7885f4588 yum.repos.d]# rm -rf *
[root@53c7885f4588 yum.repos.d]# ls
[root@53c7885f4588 yum.repos.d]# vi centos7.repo
[centos7]
name=centos7
baseurl=http://172.17.0.1:8888/rhel7.9
gpgcheck=0


[root@docker-node1 mnt]# cd
[root@docker-node1 ~]# docker commit -m "add repo" centos centos:repo
sha256:9eba96525f74fdfe6856a4bfe32d31d23202180b5f8ccb66b4b3732ad53f798c
[root@docker-node1 ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
centos               repo      9eba96525f74   8 seconds ago   204MB
busybox              v1        69ff2472a1ff   3 hours ago     4.26MB
example              v4        9af00573858d   7 hours ago     4.26MB
example              v2        2dbbb3e21285   7 hours ago     4.26MB
example              v3        6b6df0f84577   7 hours ago     4.26MB
example              v1        f4eed4b6a9f0   7 hours ago     4.26MB
nginx                latest    5ef79149e0ec   12 days ago     188MB
busybox              latest    65ad0d468eb1   15 months ago   4.26MB
centos               7         eeb6ee3f44bd   2 years ago     204MB
timinglee/game2048   latest    19299002fdbe   7 years ago     55.5MB
timinglee/mario      latest    9a35a9e43e8c   8 years ago     198MB

[root@53c7885f4588 yum.repos.d]# cd
[root@53c7885f4588 ~]# exit
exit
[root@docker-node1 docker]# docker rm centos
centos
[root@docker-node1 docker]# vim Dockerfile 
FROM centos:repo
LABEL Mail=ccc@example.com
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install -y gcc make pcre-devel openssl-devel
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 buildx build -t nginx:v1 /mnt/docker
[+] Building 24.8s (12/12) FINISHED                                              docker:default
 => [internal] load build definition from Dockerfile                                       0.0s
 => => transferring dockerfile: 414B                                                       0.0s
 => [internal] load metadata for docker.io/library/centos:repo                             0.0s
 => [internal] load .dockerignore                                                          0.0s
 => => transferring context: 2B                                                            0.0s
 => [internal] load build context                                                          0.0s
 => => transferring context: 42B                                                           0.0s
 => [1/7] FROM docker.io/library/centos:repo                                               0.0s
 => [2/7] ADD nginx-1.26.1.tar.gz /mnt                                                     0.1s
 => [3/7] WORKDIR /mnt/nginx-1.26.1                                                        0.0s
 => [4/7] RUN yum install -y gcc make pcre-devel openssl-devel                             6.6s
 => [5/7] RUN ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_st  3.9s
 => [6/7] RUN make                                                                        13.6s
 => [7/7] RUN make install                                                                 0.2s 
 => exporting to image                                                                     0.3s 
 => => exporting layers                                                                    0.3s 
 => => writing image sha256:e9b2a727b4641f0e43489d1f21c27623c2dd9803aef5189b6edda55cf5316  0.0s 
 => => naming to docker.io/library/nginx:v1                                                0.0s 

镜像优化方案

镜像优化策略
  • 选择最精简的基础镜像

  • 减少镜像的层数

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

  • 选择最精简的基础镜像

  • 减少镜像的层数

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

镜像优化案例
# 此时构建出来的镜像大小为356MB,需要继续优化
[root@docker-node1 docker]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED          SIZE
nginx                v1        e9b2a727b464   4 minutes ago    356MB

方案1:缩减镜像层

[root@docker-node1 docker]# vim Dockerfile
FROM centos:repo
LABEL Mail=ccc@example.com
ADD nginx-1.26.1.tar.gz /mnt
WORKDIR /mnt/nginx-1.26.1
RUN yum install -y gcc make pcre-devel openssl-devel && ./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 buildx build -t nginx:v1 /mnt/docker
[+] Building 20.3s (9/9) FINISHED                                          docker:default
 => [internal] load build definition from Dockerfile                                 0.0s
 => => transferring dockerfile: 456B                                                 0.0s
 => [internal] load metadata for docker.io/library/centos:repo                       0.0s
 => [internal] load .dockerignore                                                    0.0s
 => => transferring context: 2B                                                      0.0s
 => [internal] load build context                                                    0.0s
 => => transferring context: 42B                                                     0.0s
 => [1/4] FROM docker.io/library/centos:repo                                         0.0s
 => CACHED [2/4] ADD nginx-1.26.1.tar.gz /mnt                                        0.0s
 => CACHED [3/4] WORKDIR /mnt/nginx-1.26.1                                           0.0s
 => [4/4] RUN yum install -y gcc make pcre-devel openssl-devel && ./configure --pr  20.1s
 => exporting to image                                                               0.2s
 => => exporting layers                                                              0.2s
 => => writing image sha256:ee52727ed92bfebf840af7586ba4462a41f9b63176a74ed7c65b508  0.0s 
 => => naming to docker.io/library/nginx:v1                                          0.0s 
[root@docker-node1 docker]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED          SIZE
nginx                v1        ee52727ed92b   24 seconds ago   292MB

方案2:多阶段构建

[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 -y gcc make pcre-devel openssl-devel && ./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=ccc@example.com
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

[root@docker-node1 docker]# docker buildx build -t nginx:v2 /mnt/docker
[+] Building 0.1s (10/10) FINISHED                                         docker:default
 => [internal] load build definition from Dockerfile                                 0.0s
 => => transferring dockerfile: 532B                                                 0.0s
 => [internal] load metadata for docker.io/library/centos:repo                       0.0s
 => [internal] load .dockerignore                                                    0.0s
 => => transferring context: 2B                                                      0.0s
 => [internal] load build context                                                    0.0s
 => => transferring context: 42B                                                     0.0s
 => CACHED [build 1/4] FROM docker.io/library/centos:repo                            0.0s
 => CACHED [build 2/4] ADD nginx-1.26.1.tar.gz /mnt                                  0.0s
 => CACHED [build 3/4] WORKDIR /mnt/nginx-1.26.1                                     0.0s
 => CACHED [build 4/4] RUN yum install -y gcc make pcre-devel openssl-devel && ./co  0.0s
 => [stage-1 2/2] COPY --from=build /usr/local/nginx /usr/local/nginx                0.0s
 => exporting to image                                                               0.0s
 => => exporting layers                                                              0.0s
 => => writing image sha256:df2c2b56729950418b06c4245275a4aa33d87818259ffdf772218ca  0.0s
 => => naming to docker.io/library/nginx:v2                                          0.0s
[root@docker-node1 docker]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED          SIZE
nginx                v2        df2c2b567299   27 seconds ago   210MB
nginx                v1        ee52727ed92b   20 minutes ago   292MB

[root@docker-node1 docker]# docker run -d --name webserver nginx:v2
7ac92f20abea2888ffdd27eaead03ec8ca19af1426ea8f037f9c31827492a579
[root@docker-node1 docker]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS     NAMES
7ac92f20abea   nginx:v2   "/usr/local/nginx/sb…"   9 seconds ago   Up 9 seconds   80/tcp    webserver

方案3:使用最精简镜像

[root@docker-node1 docker]# docker exec -it webserver sh
sh-4.2# 
sh-4.2# ldd /usr/local/nginx/sbin/nginx 
	linux-vdso.so.1 =>  (0x00007ffc5c9e4000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f8614ad2000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f86148b6000)
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f861467f000)
	libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f861441d000)
	libssl.so.10 => /lib64/libssl.so.10 (0x00007f86141ab000)
	libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007f8613d48000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f8613b32000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f8613764000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f8614cd6000)
	libfreebl3.so => /lib64/libfreebl3.so (0x00007f8613561000)
	libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007f8613314000)
	libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007f861302b000)
	libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007f8612e27000)
	libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f8612bf4000)
	libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007f86129e4000)
	libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f86127e0000)
	libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f86125c6000)
	libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f861239f000)


# 导入debian11.tar.gz包
[root@docker-node1 ~]# docker load -i debian11.tar.gz 
5342a2647e87: Loading layer  327.7kB/327.7kB
577c8ee06f39: Loading layer   51.2kB/51.2kB
9ed498e122b2: Loading layer  3.379MB/3.379MB
4d049f83d9cf: Loading layer  1.536kB/1.536kB
af5aa97ebe6c: Loading layer   2.56kB/2.56kB
ac805962e479: Loading layer   2.56kB/2.56kB
bbb6cacb8c82: Loading layer   2.56kB/2.56kB
2a92d6ac9e4f: Loading layer  1.536kB/1.536kB
1a73b54f556b: Loading layer  10.24kB/10.24kB
c048279a7d9f: Loading layer  3.072kB/3.072kB
2388d21e8e2b: Loading layer  225.3kB/225.3kB
8451c71f8c1e: Loading layer  12.92MB/12.92MB
24aacbf97031: Loading layer  3.983MB/3.983MB
6835249f577a: Loading layer  1.505MB/1.505MB
Loaded image: gcr.io/distroless/base-debian11:latest
[root@docker-node1 ~]# docker load -i nginx-1.23.tar.gz 
8cbe4b54fa88: Loading layer  84.01MB/84.01MB
5dd6bfd241b4: Loading layer  62.51MB/62.51MB
043198f57be0: Loading layer  3.584kB/3.584kB
2731b5cfb616: Loading layer  4.608kB/4.608kB
6791458b3942: Loading layer  3.584kB/3.584kB
4d33db9fdf22: Loading layer  7.168kB/7.168kB
Loaded image: nginx:1.23
[root@docker-node1 ~]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED             SIZE
nginx                             v2        df2c2b567299   19 minutes ago      210MB
nginx                             v1        ee52727ed92b   39 minutes ago      292MB
centos                            repo      9eba96525f74   About an hour ago   204MB
busybox                           v1        69ff2472a1ff   4 hours ago         4.26MB
example                           v4        9af00573858d   8 hours ago         4.26MB
example                           v3        6b6df0f84577   8 hours ago         4.26MB
example                           v2        2dbbb3e21285   8 hours ago         4.26MB
example                           v1        f4eed4b6a9f0   8 hours ago         4.26MB
nginx                             latest    5ef79149e0ec   12 days ago         188MB
nginx                             1.23      a7be6198544f   15 months ago       142MB
busybox                           latest    65ad0d468eb1   15 months ago       4.26MB
centos                            7         eeb6ee3f44bd   2 years ago         204MB
timinglee/game2048                latest    19299002fdbe   7 years ago         55.5MB
timinglee/mario                   latest    9a35a9e43e8c   8 years ago         198MB
gcr.io/distroless/base-debian11   latest    2a6de77407bf   N/A                 20.6MB


[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 buildx build -t nginx:v3 /mnt/docker
[+] Building 0.5s (9/9) FINISHED                                           docker:default
 => [internal] load build definition from Dockerfile                                 0.0s
 => => transferring dockerfile: 1.20kB                                               0.0s
 => [internal] load metadata for docker.io/library/nginx:1.23                        0.0s
 => [internal] load metadata for gcr.io/distroless/base-debian11:latest              0.0s
 => [internal] load .dockerignore                                                    0.0s
 => => transferring context: 2B                                                      0.0s
 => [base 1/2] FROM docker.io/library/nginx:1.23                                     0.0s
 => [stage-1 1/2] FROM gcr.io/distroless/base-debian11:latest                        0.1s
 => [base 2/2] RUN mkdir -p /opt/var/cache/nginx &&  cp -a --parents /usr/lib/nginx  0.2s
 => [stage-1 2/2] COPY --from=base /opt /                                            0.0s
 => exporting to image                                                               0.0s
 => => exporting layers                                                              0.0s
 => => writing image sha256:4df49a0f3711563a109f7fbb81d77e171e8ec746fa52d8422aeb8b1  0.0s
 => => naming to docker.io/library/nginx:v3                                          0.0s
 
 
[root@docker-node1 docker]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED             SIZE
nginx                             v3        4df49a0f3711   34 seconds ago      34.5MB
nginx                             v2        df2c2b567299   28 minutes ago      210MB
nginx                             v1        ee52727ed92b   48 minutes ago      292MB

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

Docker镜像仓库的管理

Docker仓库介绍

在这里插入图片描述

Docker仓库(Docker Registry) 是用于存储和分发 Docker 镜像的集中式存储库。

它就像是一个大型的镜像仓库,开发者可以将自己创建的 Docker 镜像推送到仓库中,也可以从仓库中拉取所需的镜像。

Docker 仓库可以分为公共仓库和私有仓库:

  • 公共仓库,如 Docker Hub,任何人都可以访问和使用其中的镜像。许多常用的软件和应用都有在Docker Hub 上提供的镜像,方便用户直接获取和使用。

    • 例如,您想要部署一个 Nginx 服务器,就可以从 Docker Hub 上拉取 Nginx 的镜像。
  • 私有仓库则是由组织或个人自己搭建和管理的,用于存储内部使用的、不希望公开的镜像。

    • 比如,一家企业为其特定的业务应用创建了定制化的镜像,并将其存储在自己的私有仓库中,以保证安全性和控制访问权限。

通过 Docker 仓库,开发者能够方便地共享和复用镜像,加速应用的开发和部署过程。

docker hub

Docker Hub 是 Docker 官方提供的一个公共的镜像仓库服务。

它是 Docker 生态系统中最知名和广泛使用的镜像仓库之一,拥有大量的官方和社区贡献的镜像。

Docker Hub 的一些关键特点和优势:

  1. 丰富的镜像资源:涵盖了各种常见的操作系统、编程语言运行时、数据库、Web 服务器等众多应用的镜像。

    • 例如,您可以轻松找到 Ubuntu、CentOS 等操作系统的镜像,以及 MySQL、Redis 等数据库的镜像。
  2. 官方支持:提供了由 Docker 官方维护的一些重要镜像,确保其质量和安全性。

  3. 社区贡献:开发者们可以自由上传和分享他们创建的镜像,促进了知识和资源的共享。

  4. 版本管理:对于每个镜像,通常都有多个版本可供选择,方便用户根据需求获取特定版本。

  5. 便于搜索:用户可以通过关键词轻松搜索到所需的镜像。

Docker仓库的工作原理

仓库中的三个角色

index docker索引服务,负责并维护有关用户帐户、镜像的校验以及公共命名空间的信息。

registry docker仓库,是镜像和图表的仓库,它不具有本地数据库以及不提供用户认证,通过Index Auth service的Token的方式进行认证

Registry Client Docker充当registry客户端来维护推送和拉取,以及客户端的授权。

pull原理

镜像拉取分为以下几步:

  1. docker客户端向index发送镜像拉去请求并完成与index的认证

  2. index发送认证token和镜像位置给dockerclient

  3. dockerclient携带token和根据index指引的镜像位置取连接registry

  4. Registry会根据client持有的token跟index核实身份合法性

  5. index确认此token合法性

  6. Registry会根据client的请求传递镜像到客户端

push原理

在这里插入图片描述

镜像上传的步骤:

  1. client向index发送上传请求并完成用户认证

  2. index会发方token给client来证明client的合法性

  3. client携带index提供的token连接Registry

  4. Registry向index合适token的合法性

  5. index证实token的合法性

  6. Registry开始接收客户端上传过来的镜像

搭建Docker私有仓库
搭建简单的Registry仓库
# 导入registry仓库镜像包
[root@docker-node1 ~]# ls
anaconda-ks.cfg                                    Documents
busybox-latest.tar.gz                              Downloads
containerd.io-1.7.20-3.1.el9.x86_64.rpm            game2048.tar.gz
debian11.tar.gz                                    mario.tar.gz
Desktop                                            Music
docker                                             nginx-1.23.tar.gz
docker-buildx-plugin-0.16.2-1.el9.x86_64.rpm       nginx-latest.tar.gz
docker-ce-27.1.2-1.el9.x86_64.rpm                  Pictures
docker-ce-cli-27.1.2-1.el9.x86_64.rpm              Public
docker-ce-rootless-extras-27.1.2-1.el9.x86_64.rpm  registry.tag.gz
docker-compose-plugin-2.29.1-1.el9.x86_64.rpm      Templates
docker.tar.gz                                      Videos
# 下载本地registry镜像
[root@docker-node1 ~]# docker load -i registry.tag.gz 
ce7f800efff9: Loading layer  7.644MB/7.644MB
30609d4f10dd: Loading layer  792.6kB/792.6kB
3b6a51496c9d: Loading layer  17.55MB/17.55MB
e704e9e3e9dc: Loading layer  3.584kB/3.584kB
f019f591461d: Loading layer  2.048kB/2.048kB
Loaded image: registry:latest
# 开启registry仓库
[root@docker-node1 ~]# docker run -d -p 5000:5000 --restart=always registry
e0c2ded04513bad47dbcd3318d98281c49801d06720e43a0ec802d61ca4190c7
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS                                       NAMES
e0c2ded04513   registry   "/entrypoint.sh /etc…"   5 seconds ago   Up 4 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   heuristic_ptolemy
431d407456a8   nginx:v3   "nginx -g 'daemon of…"   11 hours ago    Up 11 hours    80/tcp, 443/tcp                             webserver

# 上传镜像到仓库中
# 给要上传的镜像打标签
[root@docker-node1 ~]# docker tag nginx:v3 172.25.254.100:5000/nginx.v3
# docker在上传的过程中默认使用https,但是我们并没有建立https认证需要的认证文件所以会报错
[root@docker-node1 ~]# docker push 172.25.254.100:5000/nginx.v3
Using default tag: latest
The push refers to repository [172.25.254.100:5000/nginx.v3]
Get "https://172.25.254.100:5000/v2/": context deadline exceeded

# 配置非加密端口
[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 push 172.25.254.100:5000/nginx.v3
Using default tag: latest
The push refers to repository [172.25.254.100:5000/nginx.v3]
d6dd14be2a40: Pushed 
6835249f577a: Pushed 
24aacbf97031: Pushed 
8451c71f8c1e: Pushed 
2388d21e8e2b: Pushed 
c048279a7d9f: Pushed 
1a73b54f556b: Pushed 
2a92d6ac9e4f: Pushed 
bbb6cacb8c82: Pushed 
ac805962e479: Pushed 
af5aa97ebe6c: Pushed 
4d049f83d9cf: Pushed 
9ed498e122b2: Pushed 
577c8ee06f39: Pushed 
5342a2647e87: Pushed 
latest: digest: sha256:6e07b84a2802a03cdada8a8569e8c9d92d370e34e198822123482d0b9716d8d0 size: 3445
# 查看镜像上传
[root@docker-node1 ~]# curl 172.25.254.100:5000/v2/_catalog
{"repositories":["nginx.v3"]}
[root@docker-node1 ~]# docker tag busybox:latest 172.25.254.100:5000/busybox:latest
[root@docker-node1 ~]# docker push 172.25.254.100:5000/busybox:latest 
The push refers to repository [172.25.254.100:5000/busybox]
d51af96cf93e: Pushed 
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527
[root@docker-node1 ~]# curl 172.25.254.100:5000/v2/_catalog
{"repositories":["busybox","nginx.v3"]}
为Registry提供加密传输
# 生成认证key和证书
# 首先清空这个/etc/docker/daemon.json文件,然后重启docker
[root@docker-node1 ~]# mkdir certs
# 添加本地解析
[root@docker-node1 ~]# vim /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.254.100  docker-node1.example.com
172.25.254.100  reg.example.com

[root@docker-node1 ~]# openssl req -newkey rsa:4096 -nodes -sha256  -keyout certs/example.com.key -addext "subjectAltName = DNS:reg.example.com" -x509 -days 365 -out certs/example.com.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]:XiAn
Organization Name (eg, company) [Default Company Ltd]:docker
Organizational Unit Name (eg, section) []:reg
Common Name (eg, your name or your server's hostname) []:reg.example.com 
Email Address []:sdmin@example.com

# 启动registry仓库
[root@docker-node1 ~]# docker run -d -p 443:443 --restart=always \
> -v /root/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/example.com.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/example.com.key registry:latest
25c40876824680b6ab95e9ccc5e05b261ec77f87678f180f2f28f4685d7ebff9
[root@docker-node1 ~]# docker tag nginx:v3 reg.example.com/nginx:v3
[root@docker-node1 ~]# mkdir -p /etc/docker/certs.d/reg.example.com
[root@docker-node1 ~]# cp /root/certs/example.com.crt /etc/docker/certs.d/reg.example.com/ca.crt
[root@docker-node1 ~]# systemctl restart docker

# 测试
[root@docker-node1 ~]# docker push reg.example.com/nginx:v3
The push refers to repository [reg.example.com/nginx]
d6dd14be2a40: Pushed 
6835249f577a: Pushed 
24aacbf97031: Pushed 
8451c71f8c1e: Pushed 
2388d21e8e2b: Pushed 
c048279a7d9f: Pushed 
1a73b54f556b: Pushed 
2a92d6ac9e4f: Pushed 
bbb6cacb8c82: Pushed 
ac805962e479: Pushed 
af5aa97ebe6c: Pushed 
4d049f83d9cf: Pushed 
9ed498e122b2: Pushed 
577c8ee06f39: Pushed 
5342a2647e87: Pushed 
v3: digest: sha256:6e07b84a2802a03cdada8a8569e8c9d92d370e34e198822123482d0b9716d8d0 size: 3445
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE             COMMAND                  CREATED         STATUS         PORTS                                             NAMES
c4e83697100b   registry:latest   "/entrypoint.sh /etc…"   2 minutes ago   Up 2 minutes   0.0.0.0:443->443/tcp, :::443->443/tcp, 5000/tcp   reverent_sinoussi
为仓库建立登陆认证
# 安装建立认证文件的工具包
[root@docker-node1 ~]# dnf install httpd-tools -y

# 建立认证文件
[root@docker-node1 ~]# mkdir auth
# -B 强制使用最安全加密方式,默认用md5加密
[root@docker-node1 ~]# htpasswd -Bc auth/.htpasswd aaa
New password: 
Re-type new password: 
Adding password for user aaa
[root@docker-node1 ~]# htpasswd -B auth/.htpasswd ccc
New password: 
Re-type new password: 
Adding password for user ccc
[root@docker-node1 ~]# cat auth/.htpasswd 
aaa:$2y$05$rRsbthyl5O.tUI5fx/9PPuG/.tE0gKF73yGAj73b9vnf6eKzPC1IK
ccc:$2y$05$hvP/5rkwGaXJqkczD/IP6uWbq6JNo5QgPUungPNst8M19cAyRS7oS

# 添加认证到registry容器中
[root@docker-node1 ~]# docker run -d -p 443:443 --restart=always -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/example.com.crt -e REGISTRY_HTTP_TLS_KEY=/certs/example.com.key -v /root/auth:/auth -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/.htpasswd registry:latest 
a23c532ef791ade2276f9cf354924c5d207703872add0bf1ec1e7c21904bf04a

# 登录测试
[root@docker-node1 ~]# docker login reg.example.com
Username: aaa
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.example.com/nginx:v3
The push refers to repository [reg.example.com/nginx]
d6dd14be2a40: Pushed 
6835249f577a: Pushed 
24aacbf97031: Pushed 
8451c71f8c1e: Pushed 
2388d21e8e2b: Pushed 
c048279a7d9f: Pushed 
1a73b54f556b: Pushed 
2a92d6ac9e4f: Pushed 
bbb6cacb8c82: Pushed 
ac805962e479: Pushed 
af5aa97ebe6c: Pushed 
4d049f83d9cf: Pushed 
9ed498e122b2: Pushed 
577c8ee06f39: Pushed 
5342a2647e87: Pushed 
v3: digest: sha256:6e07b84a2802a03cdada8a8569e8c9d92d370e34e198822123482d0b9716d8d0 size: 3445
[root@docker-node1 ~]# curl -k https://172.25.254.100/v2/_catalog -uaaa:aaa
{"repositories":["nginx"]}
构建企业级私有仓库
harbor简介

Harbor 是由vmware公司开源的企业级 Docker Registry 项目。

它提供了以下主要功能和特点:

  1. 基于角色的访问控制(RBAC):可以为不同的用户和用户组分配不同的权限,增强了安全性和管理的灵活性。

  2. 镜像复制:支持在不同的 Harbor 实例之间复制镜像,方便在多个数据中心或环境中分发镜像。

  3. 图形化用户界面(UI):提供了直观的 Web 界面,便于管理镜像仓库、项目、用户等。

  4. 审计日志:记录了对镜像仓库的各种操作,有助于追踪和审查活动。

  5. 垃圾回收:可以清理不再使用的镜像,节省存储空间。

部署harbor
# 导入软件包并解压
[root@docker-node1 ~]# tar zxf harbor-offline-installer-v2.5.4.tgz
[root@docker-node1 ~]# cd harbor/
[root@docker-node1 harbor]# ls
common.sh  harbor.v2.5.4.tar.gz  harbor.yml.tmpl  install.sh  LICENSE  prepare
[root@docker-node1 harbor]# cp harbor.yml.tmpl harbor.yml
[root@docker-node1 harbor]# 
[root@docker-node1 harbor]# vim harbor.yml
hostname: reg.example.com
  certificate: /data/certs/example.com.crt
  private_key: /data/certs/example.com.key
harbor_admin_password: 111
[root@docker-node1 harbor]# ./install.sh --help

Note: Please set hostname and other necessary attributes in harbor.yml first. DO NOT use localhost or 127.0.0.1 for hostname, because Harbor needs to be accessed by external clients.
Please set --with-notary if needs enable Notary in Harbor, and set ui_url_protocol/ssl_cert/ssl_cert_key in harbor.yml bacause notary must run under https. 
Please set --with-trivy if needs enable Trivy in Harbor
Please set --with-chartmuseum if needs enable Chartmuseum in Harbor
[root@docker-node1 harbor]# ./install.sh --with-chartmuseum

[root@docker-node1 harbor]# cp /root/certs/ /data/ -r
[root@docker-node1 harbor]# ls /data/
certs  secret
[root@docker-node1 harbor]# ./install.sh --with-chartmuseum
✔ ----Harbor has been installed and started successfully.----
[root@docker-node1 harbor]# cd
[root@docker-node1 ~]# docker logout reg.example.com
Removing login credentials for reg.example.com
[root@docker-node1 ~]# docker login reg.example.com
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 ~]# docker tag nginx:v3 reg.example.com/aaa/nginx:v3
[root@docker-node1 ~]# docker push reg.example.com/aaa/nginx:v3 
The push refers to repository [reg.example.com/aaa/nginx]
d6dd14be2a40: Pushed 
6835249f577a: Pushed 
24aacbf97031: Pushed 
8451c71f8c1e: Pushed 
2388d21e8e2b: Pushed 
c048279a7d9f: Pushed 
1a73b54f556b: Pushed 
2a92d6ac9e4f: Pushed 
bbb6cacb8c82: Pushed 
ac805962e479: Pushed 
af5aa97ebe6c: Pushed 
4d049f83d9cf: Pushed 
9ed498e122b2: Pushed 
577c8ee06f39: Pushed 
5342a2647e87: Pushed 
v3: digest: sha256:6e07b84a2802a03cdada8a8569e8c9d92d370e34e198822123482d0b9716d8d0 size: 3445

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Docker网络

docker安装后会自动创建3种网络:bridge、host、none

在做实验之前把防火墙策略默认选择为iptables,并将网络还原

[root@docker-node1 ~]# grubby --update-kernel ALL --args iptables=true
[root@docker-node1 ~]# reboot
[root@docker-node1 ~]# cd harbor/
[root@docker-node1 harbor]# docker compose down 
WARN[0000] /root/harbor/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion 
[+] Running 12/12
 ✔ Container registryctl              Removed                                        0.0s 
 ✔ Container harbor-jobservice        Removed                                        0.0s 
 ✔ Container chartmuseum              Removed                                        0.0s 
 ✔ Container nginx                    Removed                                        0.0s 
 ✔ Container harbor-portal            Removed                                        0.1s 
 ✔ Container harbor-core              Removed                                        0.0s 
 ✔ Container harbor-db                Removed                                        0.1s 
 ✔ Container registry                 Removed                                        0.1s 
 ✔ Container redis                    Removed                                        0.2s 
 ✔ Container harbor-log               Removed                                       10.1s 
 ✔ Network harbor_harbor-chartmuseum  Removed                                        0.1s 
 ✔ Network harbor_harbor              Removed                                        0.2s 
 
 [root@docker-node1 harbor]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
69a4dc8c8489   bridge    bridge    local
4bd953d7c4ac   host      host      local
c9977c22ee4e   none      null      local
原生bridge网络

docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口

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

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

[root@docker-node1 harbor]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@docker-node1 harbor]# 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 harbor]# cd
[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:15 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:2042 (1.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)
          
/ # ping www.baidu.com
PING www.baidu.com (36.155.132.76): 56 data bytes
64 bytes from 36.155.132.76: seq=0 ttl=127 time=28.611 ms
64 bytes from 36.155.132.76: seq=1 ttl=127 time=27.987 ms
^C
--- www.baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 27.987/28.299/28.611 ms
/ # 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
/ # exit

# ping通外网,网关为172.17.0.1,这个IP为docker0的ip
[root@docker-node1 ~]# ifconfig 
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:9ff:fe08:baaf  prefixlen 64  scopeid 0x20<link>
        ether 02:42:09:08:ba:af  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 28  bytes 4257 (4.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.25.254.100  netmask 255.255.255.0  broadcast 172.25.254.255
        inet6 fe80::710e:6c55:6c39:99f6  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:2d:14:17  txqueuelen 1000  (Ethernet)
        RX packets 714  bytes 68603 (66.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 676  bytes 208341 (203.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

# 查看iptables策略 MASQUERADE地址伪装,把宿主机当成一个路由器,docker0负责接受所有容器的请求,然后再通过内核路由功能到达eth0,然后进行地址伪装,伪装成172.25.254.100
[root@docker-node1 ~]# iptables -t nat -nL
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  0    --  172.17.0.0/16        0.0.0.0/0           

原生网络host

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

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

[root@docker-node1 ~]# docker rm webserver 
webserver
[root@docker-node1 ~]# docker run -it --rm --name test --network host busybox
/ # ifconfig 
docker0   Link encap:Ethernet  HWaddr 02:42:09:08:BA:AF  
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:9ff:fe08:baaf/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:34 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:342 (342.0 B)  TX bytes:4771 (4.6 KiB)

eth0      Link encap:Ethernet  HWaddr 00:0C:29:2D:14:17  
          inet addr:172.25.254.100  Bcast:172.25.254.255  Mask:255.255.255.0
          inet6 addr: fe80::710e:6c55:6c39:99f6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1379 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1113 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:139041 (135.7 KiB)  TX bytes:251685 (245.7 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:254 errors:0 dropped:0 overruns:0 frame:0
          TX packets:254 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:21559 (21.0 KiB)  TX bytes:21559 (21.0 KiB)

在这里插入图片描述

host网络模式直接使用真机的网络

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

原生网络none

none模式是指禁用网络功能,只有lo接口,在容器创建时使用

--network=none指定。

[root@docker-node1 ~]# docker run -it --rm --name test --network none busybox
/ # 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)
docker的自定义网络

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

  • bridge

  • overlay

  • macvlan

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

overlay和macvlan是用于创建跨主机网络

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

自定义桥接网络

自定义桥接模式中有dns模块,但是默认的桥接模式中没有。

[root@docker-node1 ~]# docker run -it --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: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:2318 (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 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:11 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:1370 (1.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)

此时test的ip地址为172.17.0.2,test1的为172.17.0.3。现在exit退出两个容器再做测试。

[root@docker-node1 ~]# docker start test1
test1
[root@docker-node1 ~]# docker attach test1 
/ # 
/ # 
/ # 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)

[root@docker-node1 ~]# docker start test 
test
[root@docker-node1 ~]# docker attach test
/ # 
/ # 
/ # 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:15 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:2058 (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)

现在test1的ip变为了172.17.0.2,现在test的ip变为了172.17.0.3。这样就会出现一个问题,通信的时候ip出现变化就会导致访问出现问题。虽然ip会发生变化,但是不变的是容器名称,所以在容器或者k8s当中都是用容器名称进行通信,而不是用ip地址进行通信。

# 此时发现在test容器里面ping172.24.254.2这个ip的时候是通的,但是ping容器名称test1是不通的,这说明原生的bridge桥接模式当中没有dns模块。所以需要自定义桥接模式使用容器名称进行通信。
/ # ping test1
ping: bad address 'test1'
/ # 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.136 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.095 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.095/0.115/0.136 ms
# 自定义桥接网络
[root@docker-node1 ~]# docker network create net1 -d bridge 
b1f98aa77ceb2f23774e2fb54058258cc3ff753b9186b249245b05ad91409d6d
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
69a4dc8c8489   bridge    bridge    local
4bd953d7c4ac   host      host      local
b1f98aa77ceb   net1      bridge    local
c9977c22ee4e   none      null      local

[root@docker-node1 ~]# docker rm test
test
[root@docker-node1 ~]# docker rm test1
test1

[root@docker-node1 ~]# docker run -it --name test --network net1 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:37 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:5454 (5.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)

# 通过容器的名字可以进行通信
/ # ping test1
PING test1 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.230 ms
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.105 ms
64 bytes from 172.18.0.3: seq=2 ttl=64 time=0.089 ms
^C
--- test1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.089/0.141/0.230 ms

[root@docker-node1 ~]# docker run -it --name test1 --network net1 busybox
docker容器间的网络通信
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
69a4dc8c8489   bridge    bridge    local
4bd953d7c4ac   host      host      local
c9977c22ee4e   none      null      local
[root@docker-node1 ~]# docker network create net1 -d bridge 
d1171761c571ab344654280888b79890bd2979de5ff252945e82f07c155a3e36
[root@docker-node1 ~]# docker network create net2 -d bridge 
cdc5e0c9a785597c0f94435aec6434efe9466ef841307b17015a27acef804efb
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
69a4dc8c8489   bridge    bridge    local
4bd953d7c4ac   host      host      local
d1171761c571   net1      bridge    local
cdc5e0c9a785   net2      bridge    local
c9977c22ee4e   none      null      local

[root@docker-node1 ~]# docker run -it --name test --network net1 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:26 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:3636 (3.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)

[root@docker-node1 ~]# docker run -it --name test1 --network net2 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:30 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:4324 (4.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)
/ # ping test
ping: bad address 'test'
# 此时两个网络之间不能进行通信

# 实现容器两个网络栈之间的通信
[root@docker-node1 ~]# docker network connect net1 test1

[root@docker-node1 ~]# docker run -it --name test1 --network net2 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:47 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:6360 (6.2 KiB)  TX bytes:364 (364.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: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:2198 (2.1 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:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:710 (710.0 B)  TX bytes:710 (710.0 B)

/ # ping test
PING test (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.236 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.143 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.094 ms
^C
--- test ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.094/0.157/0.236 ms

joined容器网络

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

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

两个容器用同一个网络栈实现通信

[root@docker-node1 ~]# docker rm test test1
test
test1
[root@docker-node1 ~]# docker run -it --name test --network net1 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: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)

[root@docker-node1 ~]# docker run -it --name test1 --network container:test 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: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 ~]# docker rm test test1
test
test1

[root@docker-node1 ~]# docker run -d --name test --network net1 nginx
ca6cf1bc6e1f889ec915da614aa582914efb3856dabac6fa5a6ea0676921f0bf
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
ca6cf1bc6e1f   nginx     "/docker-entrypoint.…"   3 seconds ago   Up 3 seconds   80/tcp    test

[root@docker-node1 ~]# docker run -it --name test1 --network container:test centos:7
# centos:7 通过回环接口进行通信
[root@ca6cf1bc6e1f /]# curl localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

[root@docker-node1 ~]# docker stop test 
test
[root@docker-node1 ~]# docker rm test test1

# 利用容器部署phpmyadmin管理mysql
# 导入mysql-5.7.tar.gz和phpmyadmin-latest.tar.gz
[root@docker-node1 ~]# docker load -i mysql-5.7.tar.gz 
cff044e18624: Loading layer    145MB/145MB
7ff7abf4911b: Loading layer  11.26kB/11.26kB
8b2952eb02aa: Loading layer  2.383MB/2.383MB
d76a5f910f6b: Loading layer  13.91MB/13.91MB
8527ccd6bd85: Loading layer  7.168kB/7.168kB
4555572a6bb2: Loading layer  3.072kB/3.072kB
0d9e9a9ce9e4: Loading layer  79.38MB/79.38MB
532b66f4569d: Loading layer  3.072kB/3.072kB
337ec6bae222: Loading layer  278.8MB/278.8MB
73cb62467b8f: Loading layer  17.41kB/17.41kB
441e16cac4fe: Loading layer  1.536kB/1.536kB
Loaded image: mysql:5.7
[root@docker-node1 ~]# docker load -i phpmyadmin-latest.tar.gz 
4cae4ea97049: Loading layer  3.584kB/3.584kB
7f0d23b78477: Loading layer  320.2MB/320.2MB
8f42af1dd50e: Loading layer   5.12kB/5.12kB
7285b46fc0b1: Loading layer  51.28MB/51.28MB
886076bbd0e5: Loading layer  9.728kB/9.728kB
fe49c1c8ccdc: Loading layer   7.68kB/7.68kB
c98461c57e2d: Loading layer  13.41MB/13.41MB
4646cbc7a84d: Loading layer  4.096kB/4.096kB
7183cf0cacbe: Loading layer  49.48MB/49.48MB
923288b71444: Loading layer   12.8kB/12.8kB
eb4f3a0b1a71: Loading layer  4.608kB/4.608kB
43cd9aa62af4: Loading layer  4.608kB/4.608kB
9f9985f7ecbd: Loading layer  9.134MB/9.134MB
25d63a36933d: Loading layer  6.656kB/6.656kB
13ccf69b5807: Loading layer  53.35MB/53.35MB
a65e8a0ad246: Loading layer  8.192kB/8.192kB
26f3cdf867bf: Loading layer  3.584kB/3.584kB
Loaded image: phpmyadmin:latest

# 运行phpmysqladmin
[root@docker-node1 ~]# docker run -d --name mysqladmin --network net1 \
> -e PMA_ARBITRARY=1 \
> -p 80:80 phpmyadmin:latest
1a7d0cb189d69c508451149316c1313f1a1809e9d30ab506c5c8b48f02faf470
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED          STATUS          PORTS                               NAMES
1a7d0cb189d6   phpmyadmin:latest   "/docker-entrypoint.…"   18 seconds ago   Up 17 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   mysqladmin

# 运行mysql
[root@docker-node1 ~]# docker run -d --name mysql --network container:mysqladmin \
> -e MYSQL_ROOT_PASSWORD='123' \
> mysql:5.7
cdeeebbb71ba4b4c0e60ae497ae605126bb68342b987ff3c4c107915bbda2d5d
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS         PORTS                               NAMES
cdeeebbb71ba   mysql:5.7           "docker-entrypoint.s…"   3 seconds ago   Up 3 seconds                                       mysql
1a7d0cb189d6   phpmyadmin:latest   "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   mysqladmin

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

[root@docker-node1 ~]# docker exec -it mysql bash
bash-4.2# mysql -uroot -p123
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 16
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> 
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

docker跨主机网络

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

  • 跨主机网络解决方案
    • docker原生的overlay和macvlan
    • 第三方的flannel、weave、calico
  • 众多网络方案是如何与docker集成在一起的
    • libnetwork docker容器网络库
    • CNM (Container Network Model)这个模型对容器网络进行了抽象
CNM(Container Network Model)

在这里插入图片描述
CNM分三类组件

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

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

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

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

macvlan网络方式

  • Linux kernel提供的一种网卡虚拟化技术。
  • 无需Linux bridge,直接使用物理接口,性能极好
  • 容器的接口直接与主机网卡连接,无需NAT或端口映射。
  • macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络
  • vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094

macvlan网络间的隔离和连通

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

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

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

# docker-node2上安装docker
[root@docker-node2 ~]# ls
anaconda-ks.cfg        Desktop        Documents  Music     Public     Videos
busybox-latest.tar.gz  docker.tar.gz  Downloads  Pictures  Templates
[root@docker-node2 ~]# tar zxf docker.tar.gz 
[root@docker-node2 ~]# ls
anaconda-ks.cfg                                    docker.tar.gz
busybox-latest.tar.gz                              Documents
containerd.io-1.7.20-3.1.el9.x86_64.rpm            Downloads
Desktop                                            Music
docker-buildx-plugin-0.16.2-1.el9.x86_64.rpm       Pictures
docker-ce-27.1.2-1.el9.x86_64.rpm                  Public
docker-ce-cli-27.1.2-1.el9.x86_64.rpm              Templates
docker-ce-rootless-extras-27.1.2-1.el9.x86_64.rpm  Videos
docker-compose-plugin-2.29.1-1.el9.x86_64.rpm
[root@docker-node2 ~]# dnf install *.rpm -y
[root@docker-node2 ~]# systemctl enable --now docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
[root@docker-node2 ~]# docker load -i busybox-latest.tar.gz 
d51af96cf93e: Loading layer  4.495MB/4.495MB
Loaded image: busybox:latest


# 在docker-node1和docker-node2两台主机上各添加一张网卡,设为仅主机模式,打开混杂模式
[root@docker-node2 ~]# ip link set eth1 promisc on
[root@docker-node2 ~]# ifconfig eth1
eth1: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST>  mtu 1500
        ether 00:0c:29:1e:8b:4c  txqueuelen 1000  (Ethernet)
        RX packets 3  bytes 288 (288.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@docker-node2 ~]# docker network create -d macvlan --subnet 4.4.4.0/24 --gateway 4.4.4.4  -o parent=eth1 mynet1
d91e357f1521a7d7fe0cdd427745b54870ff10b79c8275856aec0c68ee4baa37
[root@docker-node2 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
c8e7cb428485   bridge    bridge    local
0b46b496c786   host      host      local
d91e357f1521   mynet1    macvlan   local
7af801f50a8b   none      null      local
[root@docker-node2 ~]# docker run -it --name test --network mynet1 busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:04:04:04:01  
          inet addr:4.4.4.1  Bcast:4.4.4.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  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:0 
          RX bytes:0 (0.0 B)  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 ~]# ip link set eth1 promisc on
[root@docker-node1 ~]# ifconfig eth1
eth1: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST>  mtu 1500
        ether 00:0c:29:2d:14:21  txqueuelen 1000  (Ethernet)
        RX packets 3  bytes 288 (288.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@docker-node1 ~]# docker network create -d macvlan --subnet 4.4.4.0/24 \
> --gateway 4.4.4.4 \
> -o parent=eth1 mynet1
278ee54437519d7d0f135be91a440306a2f9d89734549ff6fb067db205404db7
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
69a4dc8c8489   bridge    bridge    local
4bd953d7c4ac   host      host      local
278ee5443751   mynet1    macvlan   local
c9977c22ee4e   none      null      local
[root@docker-node1 ~]# docker run -it --name test --network mynet1 --ip 4.4.4.2 busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:04:04:04:02  
          inet addr:4.4.4.2  Bcast:4.4.4.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  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:0 
          RX bytes:0 (0.0 B)  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 4.4.4.1
PING 4.4.4.1 (4.4.4.1): 56 data bytes
64 bytes from 4.4.4.1: seq=0 ttl=64 time=1.302 ms
64 bytes from 4.4.4.1: seq=1 ttl=64 time=0.340 ms
^C
--- 4.4.4.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.340/0.821/1.302 ms
/ # 


http://www.kler.cn/a/284913.html

相关文章:

  • Axure网络短剧APP端原型图,竖屏微剧视频模版40页
  • Electron 项目启动外部可执行文件的几种方式
  • Chrome使用IE内核
  • 【AI大模型】ELMo模型介绍:深度理解语言模型的嵌入艺术
  • 【C++】类与对象的基础概念
  • RT-DETR融合CVPR[2020]轻量化卷积模块Ghost Module模块
  • Nginx负载均衡请求队列配置:优化流量管理
  • MySQL:简述事务的SQL操作
  • K8S Job
  • CSS优化实践
  • 计算机毕业设计选题推荐-二手物品回收系统-Java/Python项目实战
  • Nuxt3入门:资源文件(第2节)
  • LeetCode第65题 有效数字 结合设计模式:状态模式
  • Linux下C++编程使用动态链接库
  • Openldap可视化工具PhpLdapAdmin服务配置
  • TMPDIR在pip|pip3 install时的作用以及tmp只有noexec权限的解决方法
  • 问题记录之Qt Creator下qDebug中文乱码
  • SparkSQL缓存的用法
  • IM社交-前言
  • 负载均衡的分类有哪些?
  • 路由策略工具
  • 51单片机——模块化编程
  • Kafka分布式集群部署实战:跨越理论,直击生产环境部署难题与解决方案,性能调优、监控与管理策略大揭秘,轻松上手分布式消息中间件
  • 【SQL基础】【leetcode】SQL50题
  • 『功能项目』技能释放【08】
  • Java设计模式【解释器模式】-行为型