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

Docker原理及实例

目录

一 Docker简介及部署方法

1.1 Docker简介

1.1.1 什么是docker?

1.1.2 docker在企业中的应用场景

1.1.3 docker与虚拟化的对比

1.1.4 docker的优势

二 部署docker

2.1 容器工作方法

2.2 部署第一个容器

2.2.1 配置软件仓库

2.2.2 安装docker-ce并启动服务

2.2.3 激活内核网络选项

2.3 通过压缩包安装

三 Docker的基本操作

3.1 Docker镜像管理

3.1.1 搜索镜像

四 docker镜像构建

4.1 docker镜像结构

4.2 镜像运行的基本原理

4.3 镜像获得方式

4.4 镜像构建

4.4.1 构建参数

4.4.2 Dockerfile实例

​编辑​编辑​编辑​编辑​编辑​编辑​编辑​编辑

4.5 镜像优化方案

4.5.1 镜像优化策略

4.5.2 镜像优化示例

4.5.2.1 方法1.缩减镜像层

4.5.2.2 方法2.多阶段构建

4.5.2.3 方法3.使用最精简镜像

五 docker 镜像仓库的管理

5.1 什么是docker仓库

5.2 docker hub

5.2.1 docker hub的使用方法

5.3 docker仓库的工作原理

5.3.1 pull原理

5.3.2 push原理

5.3 搭建docker的私有仓库

5.3.1 为什么搭建私有仓库

5.3.2 搭建简单的Registry仓库

5.3.3 为Registry提加密传输

5.3.4 为仓库建立登陆认证

5.4 构建企业级私有仓库

5.4.1 部署harbor

5.4.2 管理仓库

六 Docker 网络

6.1 docker原生bridge网路

6.2 docker原生网络host

6.3 docker 原生网络none

6.4 docker的自定义网络

6.4.1 自定义桥接网络

6.4.2 为什么要自定义桥接

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

6.4.4 joined容器网络

6.4.5 joined网络示例演示

6.5 容器内外网的访问

6.5.1 容器访问外网

6.5.2 外网访问docker容器

6.6 docker跨主机网络

6.6.1 CNM (Container Network Model)

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

七 Docker 数据卷管理及优化

7.1 为什么要用数据卷

7.2 bind mount 数据卷

7.3 docker managed 数据卷

7.4 数据卷容器(Data Volume Container)

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

7.6 备份与迁移数据卷

 八 Docker 的安全优化

8.1 Docker的资源限制

8.1.1.限制cpu使用

8.1.2 限制内存使用

8.1.3 限制docker的磁盘io

8.2 Docker的安全加固

8.2.1 Docker默认隔离性

8.2.3 容器特权

九 容器编排工具Docker Compose

9.1 Docker Compose 概述

9.2 Docker Compose 的常用命令参数

9.3 Docker Compose 的yml文件

9.4 企业示例

一 Docker简介及部署方法

1.1 Docker简介

2008 年LXC(LinuX Contiainer)发布,但是没有行业标准,兼容性非常差 docker2013年首次发布,由Docker, Inc开发

1.1.1 什么是docker?

Docker是管理容器的引擎,为应用打包、部署平台,而非单纯的虚拟化技术

它具有以下几个重要特点和优势:

1. 轻量级虚拟化 :

        Docker 容器相较于传统的虚拟机更加轻量和高效,能够快速启动和停止,节省系统资源。

        例如,启动一个 Docker 容器可能只需要几秒钟,而启动一个虚拟机则可能需要几分钟。

2. 一致性 :

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

3. 可移植性 :

        可以轻松地将 Docker 容器从一个平台迁移到另一个平台,无需担心依赖和环境配置的差 异。 比如,在本地开发的容器可以无缝部署到云服务器上。

4. 高效的资源利用:

        多个 Docker 容器可以共享主机的操作系统内核,从而更有效地利用系统资 源。

5. 易于部署和扩展:

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

1.1.2 docker在企业中的应用场景

  • 在企业中docker作为业务的最小载体而被广泛应用
  • 通过docker企业可以更效率的部署应用并更节省资源

注意!!!!:

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

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

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

1.1.3 docker与虚拟化的对比

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

1.1.4 docker的优势

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

二 部署docker

2.1 容器工作方法

2.2 部署第一个容器

官方站点: https://docs.docker.com/

实验准备:

主机名IP
docker-node1172.25.254.100

由于无法拉取镜像,这个博客所以的实验用到的镜像都是提前从压缩包里准备好了的 

2.2.1 配置软件仓库

[root@docker-node1 ~]# cd /etc/yum.repos.d
[root@docker-node1 yum.repos.d]# vim docker.repo[docker]name=docker-cebaseurl=https://mirrors.tuna.tsinghua.edu.cn/docker
ce/linux/centos/7/x86_64/stable/gpgcheck=0[centos]name=extrasbaseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/7/extras/x86_64gpgcheck=0

2.2.2 安装docker-ce并启动服务

#安装docker
[root@docker-node1 ~]# yum install -y docker-ce #编辑docker启动文件,设定其使用iptables的网络设定方式,默认使用nftables
[root@docker-node1 ~]# vim /usr/lib/systemd/system/docker.serviceExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true
[root@docker-node1 ~]# systemctl  enable --now docker
[root@docker-node1 ~]# docker info

2.2.3 激活内核网络选项

#在rhel7中 需要
[root@docker-node1 ~]# vim /etc/sysctl.d/docker.confnet.bridge.bridge-nf-call-iptables = 1net.bridge.bridge-nf-call-ip6tables = 1net.ipv4.ip_forward = 1
[root@docker-node1 ~]# sysctl --system
[root@docker-node1 ~]# systemctl  restart docker

2.3 通过压缩包安装

#解压压缩包,并安装rpm包
[root@docker-node1 ~]# tar zxf docker.tar.gz 
[root@docker-node1 ~]# yum install *.rpm -y#启动docker
[root@docker-node1 ~]# systemctl  enable --now docker
[root@docker-node1 ~]# systemctl  restart docker
[root@docker-node1 ~]# docker info#将压缩包加载到本地的 Docker 环境中以供使用。
[root@docker-node1 ~]# docker load -i game2048.tar.gz
[root@docker-node1 ~]# docker load -i mario.tar.gz
[root@docker-node1 ~]# docker load -i nginx-latest.tar.gz
[root@docker-node1 ~]# docker load -i busybox-latest.tar.gz#查看是否加载成功
[root@docker-node1 ~]# docker images#运行测试是否成功
[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
dce64a796306   nginx     "/docker-entrypoint.…"   22 seconds ago   Up 22 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

三 Docker的基本操作

3.1 Docker镜像管理

3.1.1 搜索镜像

四 docker镜像构建

4.1 docker镜像结构

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

4.2 镜像运行的基本原理

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

4.3 镜像获得方式

  • 基本镜像通常由软件官方提供
  • 企业镜像可以用官方镜像+Dockerfile来生成
  • 系统关于镜像的获取动作有两种:
    • docker pull 镜像地址
    • docker load –i 本地镜像包

4.4 镜像构建

4.4.1 构建参数

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

参数示例及用法

#FROM COPY 和MAINTAINER[root@Docker-node1 ~]# mkdir  docker/[root@Docker-node1 ~]# cd docker/[root@Docker-node1 docker]# touch leefile[root@Docker-node1 docker]# vim Dockerfile 
FROM busybox:latest              #指定使用的基础镜像
MAINTAINER admin@test.org        #指定作者信息
COPY testfile /                  #复制当前目录文件到容器指定位置,testfile必须在当前目录中[root@Docker-node1 docker]# docker build -t example:v1 .    #ADD[root@Docker-node1 docker]# touch leefile{1..3}[root@Docker-node1 docker]# tar zcf leefile.gz leefile*[root@Docker-node1 docker]# vim DockerfileFROM busyboxMAINTAINER admin@test.orgCOPY 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#ENV CMDFROM busyboxMAINTAINER admin@test.orgENV NAME testCMD echo $NAME[root@Docker-node1 docker]# docker run -it --rm --name test example:v3testFROM busyboxMAINTAINER admin@test.orgENV NAME testCMD ["/bin/echo", "$NAME"][root@Docker-node1 docker]# docker run -it --rm --name test example:v3$NAME#ENV CMDFROM busyboxMAINTAINER admin@test.orgENV NAME testCMD ["/bin/sh", "-c", "/bin/echo $NAME"][root@Docker-node1 docker]# docker run -it --rm --name test example:v3test#ENTRYPOINTFROM busyboxMAINTAINER admin@test.orgENV NAME testENTRYPOINT echo $NAME[root@Docker-node1 docker]# docker run -it --rm --name test example:v3  shtest#EXPOSE VOLUME VOLUMEFROM busyboxMAINTAINER admin@test.orgENV NAME testEXPOSE 80 443VOLUME /var/www/htmlWORKDIR /var/www/htmlRUN 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 #

4.4.2 Dockerfile实例

建立centos7

准备工作:虚拟机需要两个CD/DVD,一个是rhel9.4,另外一个是rhel7.9

#将centos7加载到本地的 Docker 环境中以供使用
[root@docker-node2 ~]# docker load -i /mnt/centos-7.tar.gz 
174f56854903: Loading layer  211.7MB/211.7MB
Loaded image: centos:7
[root@docker-node2 ~]# cd docker/
[root@docker-node2 docker]# mv /mnt/nginx-1.26.1.tar.gz .
[root@docker-node2 docker]# ls
Dockerfile  nginx-1.26.1.tar.gz  #配置文件
[root@docker-node1 docker]# vim Dockerfile 
FROM centos:repo
LABEL Mail=admin@test.com
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-node2 docker]#  docker build -t webserver:v1 .#配置HTTP和挂载
[root@docker-node1 docker]# yum install httpd -y
[root@docker-node1 docker]# vim /etc/httpd/conf/httpd.conf 
[root@docker-node1 docker]# systemctl restart httpd
[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@7d4c2668f09e /]# [root@docker-node1 docker]# docker inspect centos#配置仓库
[root@docker-node1 docker]# docker run -it --name centos centos:7
[root@34b2ac427894 /]# cd /etc/yum.repos.d/
[root@34b2ac427894 yum.repos.d]# rm -rf *
[root@34b2ac427894 yum.repos.d]# vi centos7.repo
[centos7]
name=centos7
baseurl=http://172.17.0.1:8888/rhel7.9
gpgcheck=0[root@docker-node1 yum.repos.d]# docker commit -m "add repo" centos centos:repo
sha256:3e761d58fcc47abfa2a55eaab9d0be9ba22a0e734063f99d4491b0d198f45e97
[root@docker-node1 yum.repos.d]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
centos               repo      3e761d58fcc4   4 seconds ago   204MB
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@65b4c98291a5 yum.repos.d]# exit
exit
[root@docker-node1 docker]# docker rm centos
centos[root@docker-node1 docker]# docker build -t webserver:v1 .
[+] Building 28.6s (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: 1.25MB                                                0.0s=> [1/7] FROM docker.io/library/centos:repo                                       0.0s=> [2/7] ADD nginx-1.26.1.tar.gz /mnt                                             0.2s=> [3/7] WORKDIR /mnt/nginx-1.26.1                                                0.0s=> [4/7] RUN yum install gcc make pcre-devel openssl-devel -y                     4.4s=> [5/7] RUN ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with  5.0s => [6/7] RUN make                                                                18.3s => [7/7] RUN make install                                                         0.2s => exporting to image                                                             0.4s => => exporting layers                                                            0.4s => => writing image sha256:5d2d60fd89872faf40a66c168ff9b3c990d3dd0b9fa30c75f84f4  0.0s => => naming to docker.io/library/webserver:v1                                    0.0s

4.5 镜像优化方案

4.5.1 镜像优化策略

  • 选择最精简的基础镜像
  • 减少镜像的层数
  • 清理镜像构建的中间产物
  • 选择最精简的基础镜像
  • 减少镜像的层数
  • 清理镜像构建的中间产物

4.5.2 镜像优化示例

4.5.2.1 方法1.缩减镜像层
[root@node1 docker]# vim Dockerfile 
FROM centos:repo
LABEL Mail=admin@test.com
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@node1 docker]# docker build -t webserver:v1 .[root@node1 docker]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED          SIZE
webserver                         v3        cc71beda411e   13 minutes ago   34.5MB
webserver                         v2        43eba985f5db   42 minutes ago   210MB
webserver                         v1        b3309248e2bf   47 minutes ago   313MB
<none>                            <none>    f2afa136ea2d   52 minutes ago   356MB
centos                            repo      a732bd43ba9b   53 minutes ago   204MB
nginx                             latest    5ef79149e0ec   2 weeks ago      188MB
nginx                             1.23      a7be6198544f   15 months ago    142MB
centos                            7         eeb6ee3f44bd   2 years ago      204MB
gcr.io/distroless/base-debian11   latest    2a6de77407bf   N/A              20.6MB

4.5.2.2 方法2.多阶段构建
[root@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 allFROM centos:repo
LABEL Mail=admin@test.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@node1 docker]# docker build -t webserver:v2 . [root@node1 docker]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
webserver    v2        43eba985f5db   3 minutes ago    210MB
webserver    v1        f2afa136ea2d   13 minutes ago   356MB
centos       repo      a732bd43ba9b   14 minutes ago   204MB
nginx        latest    5ef79149e0ec   2 weeks ago      188MB
centos       7         eeb6ee3f44bd   2 years ago      204MB

4.5.2.3 方法3.使用最精简镜像

使用google提供的最精简镜像

下载地址: https://github.com/GoogleContainerTools/distroless

下载镜像: docker pull gcr.io/distroless/base

[root@node1 docker]# vim Dockerfile 
FROM nginx:1.23 AS baseARG TIME_ZONERUN 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/localtimeFROM gcr.io/distroless/base-debian11COPY --from=base /opt /EXPOSE 80 443ENTRYPOINT ["nginx", "-g", "daemon off;"][root@node1 docker]# docker build -t webserver:v3 .[root@node1 docker]# docker images
REPOSITORY                        TAG       IMAGE ID       CREATED              SIZE
webserver                         v3        cc71beda411e   About a minute ago   34.5MB
webserver                         v2        43eba985f5db   30 minutes ago       210MB
webserver                         v1        f2afa136ea2d   40 minutes ago       356MB
centos                            repo      a732bd43ba9b   41 minutes ago       204MB
nginx                             latest    5ef79149e0ec   2 weeks ago          188MB
nginx                             1.23      a7be6198544f   15 months ago        142MB
centos                            7         eeb6ee3f44bd   2 years ago          204MB
gcr.io/distroless/base-debian11   latest    2a6de77407bf   N/A                  20.6MB

五 docker 镜像仓库的管理

5.1 什么是docker仓库

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

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

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

  • 公共仓库,如 Docker Hub,任何人都可以访问和使用其中的镜像。许多常用的软件和应用都有在 Docker Hub 上提供的镜像,方便用户直接获取和使用。 例如,您想要部署一个 Nginx 服务器,就可以从 Docker Hub 上拉取 Nginx 的镜像。
  • 私有仓库则是由组织或个人自己搭建和管理的,用于存储内部使用的、不希望公开的镜像。 比如,一家企业为其特定的业务应用创建了定制化的镜像,并将其存储在自己的私有仓库中, 以保证安全性和控制访问权限。

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

5.2 docker hub

官网: https://hub.docker.com/

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

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

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

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

  • 例如,您可以轻松找到 Ubuntu、CentOS 等操作系统的镜像,以及 MySQL、Redis 等数据库 的镜像。

2. 官方支持:提供了由 Docker 官方维护的一些重要镜像,确保其质量和安全性。

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

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

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

5.2.1 docker hub的使用方法

#登陆官方仓库
[root@docker ~]# docker loginLog in with your Docker ID or email address to push and pull images from Docker 
Hub. If you don't have a Docker ID, head over to https://hub.docker.com/ to 
create one.You can log in with your password or a Personal Access Token (PAT). Using a 
limited-scope PAT grants better security and is required for organizations using 
SSO. Learn more at https://docs.docker.com/go/access-tokens/Username: timingleePassword:WARNING! Your password will be stored unencrypted in /root/.docker/config.json.Configure a credential helper to remove this warning. Seehttps://docs.docker.com/engine/reference/commandline/login/#credential-storesLogin Succeeded#登陆信息保存位置
[root@docker ~]# cd .docker/[root@docker .docker]# lsconfig.json[root@docker .docker]# cat config.json{"auths": {"https://index.docker.io/v1/": {"auth": "dGltaW5nbGVlOjY3NTE1MTVtaW5nemxu"}}[root@docker ~]# docker tag gcr.io/distroless/base-debian11:latest  
timinglee/base-debian11:latest[root@docker ~]# docker push  timinglee/base-debian11:latestThe push refers to repository [docker.io/timinglee/base-debian11]6835249f577a: Pushed24aacbf97031: Pushed8451c71f8c1e: Pushed2388d21e8e2b: Pushedc048279a7d9f: Pushed1a73b54f556b: Pushed2a92d6ac9e4f: Pushedbbb6cacb8c82: Pushedac805962e479: Pushedaf5aa97ebe6c: Pushed4d049f83d9cf: Pushed9ed498e122b2: Pushed577c8ee06f39: Pushed5342a2647e87: Pushedlatest: digest: 
sha256:f8179c20f1f2b1168665003412197549bd4faab5ccc1b140c666f9b8aa958042 size: 
3234

5.3 docker仓库的工作原理

仓库中的三个角色

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

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

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

5.3.1 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的请求传递镜像到客户端

5.3.2 push原理

镜像上传的步骤:

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

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

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

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

5.index证实token的合法性

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

5.3 搭建docker的私有仓库

5.3.1 为什么搭建私有仓库

docker hub虽然方便,但是还是有限制

  • 需要internet连接,速度慢
  • 所有人都可以访问
  • 由于安全原因企业不允许将镜像放到外网

好消息是docker公司已经将registry开源,我们可以快速构建企业私有仓库

5.3.2 搭建简单的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
[root@docker-node1 ~]# docker images开启Registry
[root@docker-node1 ~]# docker run -d -p 5000:5000 --restart=always --name registry registry
20706cfdd2e5280950ddc58d0e7890f41f752ab484e680ca8cb8ebe7e6da565e
[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS                                       NAMES
20706cfdd2e5   registry   "/entrypoint.sh /etc…"   5 seconds ago   Up 5 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   registry#给要上传的经镜像打标签
#docker在上传的过程中默认使用https,但是我们并没有建立https认证需要的认证文件所以会报错
[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]
Get "https://172.25.254.100:5000/v2/": http: server gave HTTP response to HTTPS client#配置非加密端口
[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/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"]}

5.3.3 为Registry提加密传输

#生成认证key和证书
[root@docker-node1 ~]# mkdir certs
[root@docker-node1 ~]#  openssl req -newkey  rsa:4096 \
> -nodes -sha256 -keyout certs/test.org.key \
> -addext "subjectAltName = DNS:www.test.com" \
> -x509 -days 365 -out certs/test.org.crt#启动registry仓库
[root@docker-node1 ~]#  docker run -d -p 443:443 --restart=always --name registry  --name registry -v /opt/registry:/var/lib/registry  -v /root/certs:/certs  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/test.org.crt  -e REGISTRY_HTTP_TLS_KEY=/certs/test.org.key registry#为客户端建立证书
[root@docker-node1 ~]# mkdir /etc/docker/certs.d/www.test.com/ -p
[root@docker-node1 ~]#  cp /root/certs/test.org.crt /etc/docker/certs.d/www.test.com/ca.crt
[root@docker-node1 ~]# systemctl restart docker#测试
[root@docker-node1 ~]#    docker tag busybox www.test.com/busybox:latest
[root@docker-node1 ~]# docker push www.test.com/busybox:latest
The push refers to repository [www.test.com/busybox]
d51af96cf93e: Pushed 
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527

5.3.4 为仓库建立登陆认证

#建立认证文件
[root@docker-node1 ~]#  mkdir auth
[root@docker-node1 ~]# htpasswd -Bc auth/htpasswd test
New password: 
Re-type new password: 
Adding password for user test#添加认证到registry容器中
[root@docker-node1 ~]# docker run -d -p 443:443 --restart=always --name registry -v /opt/registry:/var/lib/registry -v /root/certs:/certs -e REGISTRY_HTTP_ADDR=0.0.0.0:443 -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/test.org.crt -e REGISTRY_HTTP_TLS_KEY=/certs/test.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
3b335f65a14ef5291fe56adf22fda37fd3d36fe955a73b0115f89b505dc32098#登陆测试
[root@docker-node1 ~]#  curl -k https://www.test.com/v2/_catalog -u test:redhat
{"repositories":["busybox"]}
[root@docker-node1 ~]#  docker login www.test.com
Username: test
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-storesLogin Succeeded

当仓库开启认证后必须登陆仓库才能进行镜像上传

#未登陆情况下上传镜像
[root@docker ~]# docker push  www.test.com/busyboxUsing default tag: latestThe push refers to repository [www.test.com/busybox]d51af96cf93e: Preparingno basic auth credentials#未登陆请款下也不能下载
[root@docker-node2 ~]# docker pull www.test.com/busyboxUsing default tag: latestError response from daemon: Head 
"https://www.test.com/v2/busybox/manifests/latest": no basic auth 
credentials

5.4 构建企业级私有仓库

下载软件包地址 https://github.com/goharbor/harbor/releases

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

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

  • 基于角色的访问控制(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[root@docker-node1 harbor]# vim harbor.yml5 hostname: www.test.com17   certificate: /data/certs/test.org.crt18   private_key: /data/certs/test.org.key34 harbor_admin_password: redhat[root@docker-node1 ~]# cp certs/test.org.crt /data/certs/test.org.crt
[root@docker-node1 ~]# cp certs/test.org.key /data/certs/test.org.key[root@docker-node1 harbor]# ./install.sh --with-chartmuseum#管理harbor的容器
[root@docker-node1 harbor]# docker compose stop
[root@docker-node1 harbor]# docker compose up -d#上传镜像
[root@docker-node1 ~]# docker login www.test.com
Authenticating with existing credentials...
Stored credentials invalid or expired
Username (test): 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-storesLogin Succeeded[root@docker-node1 ~]# docker tag busybox:latest www.test.com/test1/busybox:latest
[root@docker-node1 ~]# docker push www.test.com/test1/busybox:latest
The push refers to repository [www.test.com/test1/busybox]
d51af96cf93e: Pushed 
latest: digest: sha256:28e01ab32c9dbcbaae96cf0d5b472f22e231d9e603811857b295e61197e40a9b size: 527

5.4.2 管理仓库

1.登陆

2.建立仓库项目

上传镜像

查看上传的镜像

六 Docker 网络

docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分

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

[root@node1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
379f9058b579   bridge    bridge    local
1f1aaf679312   host      host      local
64a9d568f680   none      null      local

6.1 docker原生bridge网路

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

[root@node1 ~]# ip link show type bridge
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default link/ether 02:42:a6:ea:66:f0 brd ff:ff:ff:ff:ff:ff

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

[root@docker-node1 ~]# docker run -d --name web -p 80:80 nginx
e117d06382066e2f0963bb5851f91931607ebe40b61a23fbb12abc32796c98e5
[root@docker-node1 ~]# ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255ether 02:42:ba:22:ea:b4  txqueuelen 0  (Ethernet)RX packets 0  bytes 0 (0.0 B)RX errors 0  dropped 0  overruns 0  frame 0TX packets 27  bytes 3866 (3.7 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet 172.25.254.100  netmask 255.255.255.0  broadcast 172.25.254.255inet6 fe80::10dc:4e34:b1e0:2000  prefixlen 64  scopeid 0x20<link>ether 00:0c:29:55:95:0d  txqueuelen 1000  (Ethernet)RX packets 2630  bytes 421690 (411.8 KiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 2074  bytes 339687 (331.7 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536inet 127.0.0.1  netmask 255.0.0.0inet6 ::1  prefixlen 128  scopeid 0x10<host>loop  txqueuelen 1000  (Local Loopback)RX packets 508  bytes 60604 (59.1 KiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 508  bytes 60604 (59.1 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0vethe59a8b3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet6 fe80::e8e7:c2ff:fe65:36b8  prefixlen 64  scopeid 0x20<link>ether ea:e7:c2:65:36:b8  txqueuelen 0  (Ethernet)RX packets 0  bytes 0 (0.0 B)RX errors 0  dropped 0  overruns 0  frame 0TX packets 18  bytes 2308 (2.2 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

6.2 docker原生网络host

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

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

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

[root@docker-node1 ~]# docker run -it --name test  --network host busybox
/ # ifconfig 
docker0   Link encap:Ethernet  HWaddr 02:42:BA:22:EA:B4  inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0UP BROADCAST MULTICAST  MTU:1500  Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:21 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:0 (0.0 B)  TX bytes:3326 (3.2 KiB)eth0      Link encap:Ethernet  HWaddr 00:0C:29:55:95:0D  inet addr:172.25.254.100  Bcast:172.25.254.255  Mask:255.255.255.0inet6 addr: fe80::10dc:4e34:b1e0:2000/64 Scope:LinkUP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1RX packets:825 errors:0 dropped:0 overruns:0 frame:0TX packets:694 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:195172 (190.5 KiB)  TX bytes:126886 (123.9 KiB)lo        Link encap:Local Loopback  inet addr:127.0.0.1  Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING  MTU:65536  Metric:1RX packets:508 errors:0 dropped:0 overruns:0 frame:0TX packets:508 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:60604 (59.1 KiB)  TX bytes:60604 (59.1 KiB)

6.3 docker 原生网络none

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

[root@docker-node1 ~]#  docker run -it --name test --rm --network none  busybox
/ # ifconfig 
lo        Link encap:Local Loopback  inet addr:127.0.0.1  Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING  MTU:65536  Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

6.4 docker的自定义网络

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

bridge

overlay

macvlan

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

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

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

6.4.1 自定义桥接网络

  • 在建立自定以网络时,默认使用桥接模式
  • 桥接默认是单调递增
  • 桥接也支持自定义子网和网关
[root@docker-node1 ~]# docker network create my_net1
e911d2714ea9d07c66dfcd7d0f790bf63f66bd2e825ae0a8ee52218ce4e231ce
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
5cc1606816e0   bridge    bridge    local
6097c99f9b54   host      host      local
e911d2714ea9   my_net1   bridge    local
eac05d3a0460   none      null      local
[root@docker-node1 ~]# ifconfig
br-e911d2714ea9: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255ether 02:42:5a:11:3d:3b  txqueuelen 0  (Ethernet)RX packets 0  bytes 0 (0.0 B)RX errors 0  dropped 0  overruns 0  frame 0TX packets 21  bytes 2518 (2.4 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255ether 02:42:ba:22:ea:b4  txqueuelen 0  (Ethernet)RX packets 0  bytes 0 (0.0 B)RX errors 0  dropped 0  overruns 0  frame 0TX packets 27  bytes 3866 (3.7 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0[root@docker-node1 ~]# docker network create my_net2 --subnet 192.168.0.0/24 --gateway 192.168.0.100
ca9e8110801bab5595930b42b3c9782cce271212ab6bf18f5659827c5e3c4cdd
[root@docker-node1 ~]# docker network  inspect my_net2
[{"Name": "my_net2","Id": "ca9e8110801bab5595930b42b3c9782cce271212ab6bf18f5659827c5e3c4cdd","Created": "2024-08-29T11:35:19.919558195+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": {},"Config": [{"Subnet": "192.168.0.0/24","Gateway": "192.168.0.100"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {},"Options": {},"Labels": {}}
]

6.4.2 为什么要自定义桥接

多容器之间如何互访?通过ip可以,但是有什么问题?

  • docker引擎在分配ip时时根据容器启动顺序分配到,谁先启动谁用,是动态变更的
  • 多容器互访用ip很显然不是很靠谱,那么多容器访问一般使用容器的名字访问更加稳定
  • docker原生网络是不支持dns解析的,自定义网络中内嵌了dns

注意:不同的自定义网络是不能通讯的

[root@docker-node1 ~]# docker run  -d --name web1 nginx
6c47331826ec47d8e38816381f6f9d075828ecf1232601d57c841eb500dcf8bd
[root@docker-node1 ~]# docker run  -d --name web2 nginx
b8f9bf49f8208f99e16d0102a03feb85cfd9557c1e32ddb4f24b6075d8c5af2c
[root@docker-node1 ~]#  docker inspect  web1[root@docker-node1 ~]# docker run -d --network my_net1 --name web nginx
06fbd8d7695bff43f5add707ef2f2c2783b43ccf5b9132ca9f512dd539365eab
[root@docker-node1 ~]# docker run  -it --network my_net1  --name  test busybox
/ # ping web
PING web (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.298 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.100 ms

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

[root@docker-node1 ~]# docker run -d  --name web1 --network my_net1 nginx
[root@docker-node1 ~]# docker network connect my_net1 test
[root@docker-node1 ~]# docker run  -it --name test --network my_net2 busybox
/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:C0:A8:00:01  inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1RX packets:13 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:1630 (1.5 KiB)  TX bytes:0 (0.0 B)lo        Link encap:Local Loopback  inet addr:127.0.0.1  Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING  MTU:65536  Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 02:42:C0:A8:00:01  inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1RX packets:18 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:2388 (2.3 KiB)  TX bytes:0 (0.0 B)eth1      Link encap:Ethernet  HWaddr 02:42:AC:12:00:04  inet addr:172.18.0.4  Bcast:172.18.255.255  Mask:255.255.0.0UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1RX packets:6 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:516 (516.0 B)  TX bytes:0 (0.0 B)lo        Link encap:Local Loopback  inet addr:127.0.0.1  Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING  MTU:65536  Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
/ # ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.203 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.259 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.098 ms

6.4.4 joined容器网络

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

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

[root@docker-node1 ~]# docker run  -it --rm  --network container:web1 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.0UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1RX packets:21 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:0 RX bytes:2450 (2.3 KiB)  TX bytes:0 (0.0 B)lo        Link encap:Local Loopback  inet addr:127.0.0.1  Mask:255.0.0.0inet6 addr: ::1/128 Scope:HostUP LOOPBACK RUNNING  MTU:65536  Metric:1RX packets:0 errors:0 dropped:0 overruns:0 frame:0TX packets:0 errors:0 dropped:0 overruns:0 carrier:0collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)[root@docker-node1 ~]#  docker run  -it --rm  --network container:web1 centos:7
[root@36d58d4314d3 /]#  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>

6.4.5 joined网络示例演示

利用容器部署phpmyadmin管理mysql

注意!!!!:开启的phpmyadmin容器中是没有数据库的,这里填写的localhost:3306是因为mysql容器和phpmyadmin容器公用一个网络站

[root@docker-node1 ~]# docker load -i mysql-5.7.tar.gz 
[root@docker-node1 ~]# docker load -i phpmyadmin-latest.tar.gz [root@docker-node1 ~]# docker run -d --name mysqladmin --network my_net1 \
> -e PMA_ARBITRARY=1 \
> -p 80:80 phpmyadmin:latest
523f241bbbbbe6186b0fd89c974096927aa87f938e389969dd79dfc2988aadb0
[root@docker-node1 ~]# docker run  -d --name mysql \
> -e MYSQL_ROOT_PASSWORD='redhat' \
> --network container:mysqladmin  \
> mysql:5.7
98c4710f682b012a721402c308505c3b1b566184424af9872c4f483ac01e1164[root@docker-node1 ~]# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED              STATUS              PORTS                               NAMES
98c4710f682b   mysql:5.7           "docker-entrypoint.s…"   About a minute ago   Up About a minute                                       mysql
523f241bbbbb   phpmyadmin:latest   "/docker-entrypoint.…"   2 minutes ago        Up 2 minutes        0.0.0.0:80->80/tcp, :::80->80/tcp   mysqladmin
f37bbc10b61a   busybox             "sh"                     53 minutes ago       Up 53 minutes                                           sweet_mcnulty[root@docker-node1 ~]# docker exec -it mysql bash
bash-4.2# mysql -uroot -predhat

6.5 容器内外网的访问

6.5.1 容器访问外网

  • 在rhel7中,docker访问外网是通过iptables添加地址伪装策略来完成容器网文外网
  • 在rhel7之后的版本中通过nftables添加地址伪装来访问外网
[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 LOCALChain 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 LOCALChain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  0    --  172.20.0.0/16        0.0.0.0/0           
MASQUERADE  0    --  172.19.0.0/16        0.0.0.0/0           
MASQUERADE  0    --  172.17.0.0/16        0.0.0.0/0           
MASQUERADE  0    --  172.18.0.0/16        0.0.0.0/0           
MASQUERADE  6    --  172.20.0.3           172.20.0.3           tcp dpt:80        #内网访问外网策略Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           
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.20.0.3:80

6.5.2 外网访问docker容器

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

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

#通过docker-proxy对数据包进行内转
[root@docker-node1 test]# docker run  -d --name webserver -p 80:80 nginx
faa550d1bcb5aa4eff324767016367c7a39b81edc48815d6832c70b99948ffcf
[root@docker-node1 test]# ps axPID TTY      STAT   TIME COMMAND1 ?        Ss     0:04 /usr/lib/systemd/systemd rhgb --switched-root --system --dese2 ?        S      0:00 [kthreadd]3 ?        I<     0:00 [rcu_gp]#通过dnat策略来完成浏览内转
[root@docker-node1 test]# 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 LOCALChain 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 LOCALChain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  0    --  172.20.0.0/16        0.0.0.0/0           
MASQUERADE  0    --  172.19.0.0/16        0.0.0.0/0           
MASQUERADE  0    --  172.17.0.0/16        0.0.0.0/0           
MASQUERADE  0    --  172.18.0.0/16        0.0.0.0/0           
MASQUERADE  6    --  172.17.0.2           172.17.0.2           tcp dpt:80Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           
RETURN     0    --  0.0.0.0/0            0.0.0.0/0           
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

6.6 docker跨主机网络

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

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

6.6.1 CNM (Container Network Model)

CNM分三类组件

  • Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace)
  • Endpoint:作用是将sandbox接入network (veth pair)
  • Network:包含一组endpoint,同一network的endpoint可以通信

6.6.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主机上各添加一块网卡,打开网卡混杂模式:

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

[root@docker-node1 ~]# ip link set eth1 promisc on
[root@docker-node1 ~]# ip link set up eth1 
[root@docker-node1 ~]# ifconfig eth1
eth1: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST>  mtu 1500ether 00:0c:29:55:95:17  txqueuelen 1000  (Ethernet)RX packets 10  bytes 640 (640.0 B)RX errors 0  dropped 0  overruns 0  frame 0TX packets 0  bytes 0 (0.0 B)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

2.添加macvlan网路

#添加macvlan网路
[root@docker-node2 ~]# docker network create -d macvlan --subnet 1.1.1.0/24 --gateway 1.1.1.1 -o parent=eth1 macvlan1

3.测试

#测试
#node1中
[root@docker-node1 ~]# docker run -it --name busybox --network macvlan1 --ip 1.1.1.100 --rm busybox
/ # ping 1.1.1.200
PING 1.1.1.200 (1.1.1.200): 56 data bytes
64 bytes from 1.1.1.200: seq=0 ttl=64 time=0.441 ms
64 bytes from 1.1.1.200: seq=1 ttl=64 time=0.298 ms#node2中
[root@docker-node2 ~]# docker run -it --name busybox --network macvlan1 --ip 1.1.1.200 --rm busybox
/ # ping 1.1.1.100
PING 1.1.1.100 (1.1.1.100): 56 data bytes
64 bytes from 1.1.1.100: seq=0 ttl=64 time=0.633 ms
64 bytes from 1.1.1.100: seq=1 ttl=64 time=0.324 ms

七 Docker 数据卷管理及优化

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

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

  • 数据持久化:即使容器被删除或重新创建,数据卷中的数据仍然存在,不会丢失。
  • 数据共享:多个容器可以同时挂载同一个数据卷,实现数据的共享和交互。
  • 独立于容器生命周期:数据卷的生命周期独立于容器,不受容器的启动、停止和删除的影响。

7.1 为什么要用数据卷

docker分层文件系统

  • 性能差
  • 生命周期与容器相同

docker数据卷

  • mount到主机中,绕开分层文件系统
  • 和主机磁盘性能相同,容器删除后依然保留
  • 仅限本地磁盘,不能随容器迁移

docker提供了两种卷:

  • bind mount
  • docker managed volume

7.2 bind mount 数据卷

  • 是将主机上的目录或文件mount到容器里。
  • 使用直观高效,易于理解。
  • 使用 -v 选项指定路径
  • -v选项指定的路径,如果不存在,挂载时会自动创建

实例:

[root@docker-node2 ~]# 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
redhat:x:1000:1000::/home/redhat:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
/ # 
/ # touch /data1/testfile1
/ # touch /data2/testfile1
touch: /data2/testfile1: Read-only file system

7.3 docker managed 数据卷

  • bind mount必须指定host文件系统路径,限制了移植性
  • docker managed volume 不需要指定mount源,docker自动为容器创建数据卷目录
  • 默认创建的数据卷目录都在 /var/lib/docker/volumes 中
  • 如果挂载时指向容器内已有的目录,原有数据会被复制到volume中

实例:

注意!!!!!!: 

  • 在执行 docker volume prune 命令之前,请确保你确实不再需要这些数据卷中的数据,因为 该操作是不可逆的,一旦删除数据将无法恢复。
  • 如果有重要的数据存储在数据卷中,建议先进行备份,或者确保数据已经被妥善保存到其他地 方。
[root@docker-node2 ~]# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD='redhat' mysql:5.7
2dc258a190ede7e246ca63b4d162fd4a2f699995b11fd9d7e22a4ced6274a5cd
[root@docker-node2 ~]# ls -l  /var/lib/docker/volumes/
total 24
drwx-----x 3 root root     19 Aug 30 11:51 fc707119ded2c882c1f25b69fe8c68ca530e64cb29ddd91c84f96e3738cc3792
-rw------- 1 root root  32768 Aug 30 11:51 metadata.db[root@docker-node2 ~]# cd /var/lib/docker/volumes/
[root@docker-node2 volumes]# touch fc707119ded2c882c1f25b69fe8c68ca530e64cb29ddd91c84f96e3738cc3792/_data/testfile[root@docker-node2 volumes]# docker exec  -it mysql  bash
bash-4.2# cd /var/lib/mysql
bash-4.2# ls
auto.cnf	 client-key.pem  ibdata1     performance_schema  server-key.pem
ca-key.pem	 ib_buffer_pool  ibtmp1      private_key.pem	 sys
ca.pem		 ib_logfile0	 mysql	     public_key.pem	 testfile
client-cert.pem  ib_logfile1	 mysql.sock  server-cert.pem
bash-4.2# pwd
/var/lib/mysql
bash-4.2# exit
exit#清理未使用的 Docker 数据卷
[root@docker-node2 volumes]# docker volume prune
WARNING! This will remove anonymous local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Total reclaimed space: 0B#建立数据卷
[root@docker-node2 volumes]# docker volume create testvill
testvill
[root@docker-node2 volumes]# ls -l /var/lib/docker/volumes/testvill/_data/
total 0#查看卷
[root@docker-node2 volumes]# docker volume ls
DRIVER    VOLUME NAME
local     d47031f356e8fa259690746818ae05f980755ae31991eee0bf01ed3b9df2c4e8
local     fc707119ded2c882c1f25b69fe8c68ca530e64cb29ddd91c84f96e3738cc3792
local     testvill#使用建立的数据卷
[root@docker-node2 _data]# docker run -d --name web1 -p 80:80 -v testvill:/usr/share/nginx/html nginx
67ae52da673745d9dfe08ce4eebf5f619c70b81c87cb442f5040c2d3ff708750
[root@docker-node2 _data]# ls
50x.html  index.html
[root@docker-node2 _data]# echo testvill > index.html
[root@docker-node2 _data]# curl 172.25.254.200

建立永久的数据库

[root@docker-node1 ~]#  docker run  -d --rm --name mysql -e  MYSQL_ROOT_PASSWORD='redhat' -v mysqldate:/var/lib/mysql mysql:5.7
99aca644bf32da4e46149cdf6e7cdf941357d3f9834d5fa65b9a73edb58f5f96
[root@docker-node1 ~]# docker inspect mysql
{"Type": "volume","Name": "mysqldate","Source": "/var/lib/docker/volumes/mysqldate/_data","Destination": "/var/lib/mysql",

7.4 数据卷容器(Data Volume Container)

数据卷容器(Data Volume Container)是 Docker 中一种特殊的容器,主要用于方便地在多个容器之间 共享数据卷。

1.建立数据卷容器

[root@docker-node1 ~]# docker run -d --name data -v /tmp/data1:/data1:rw -v /tmp/data2:/data2:ro -v /etc/resolv.conf:/etc/hosts busybox

2.使用数据卷容器

[root@docker-node1 ~]# docker run  -it --name test --rm --volumes-from data busybox
/ # ls
bin    data2  etc    lib    proc   sys    usr
data1  dev    home   lib64  root   tmp    var
/ # cat /etc/resolv.conf 
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.nameserver 114.114.114.114
search exam.com# Based on host file: '/etc/resolv.conf' (legacy)
# Overrides: []
/ # touch data1/leefile1
/ # touch /data2/leefile1
touch: /data2/leefile1: Read-only file system

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

相同点:

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

不同点:

bind mountdocker managed volume
volume位置可任意指定/var/lib/docker/volumes/...
对已有mount point影响隐藏并替换为volume原有数据复制到volume
是否支持单个文件支持不支持,可能是目录
权限控制可设置为只读,默认为读写权限无控制,均为读写权限
移植性移植性弱,与host path绑定移植性强,无需指定host目录

7.6 备份与迁移数据卷

1.备份数据卷

[root@docker-node1 ~]# docker run --volumes-from data  -v `pwd`:/backup busybox tar zcf /backup/data1.tar.gz  /data1
tar: removing leading '/' from member names

2.数据恢复

[root@docker-node1 ~]# docker run  -it --name test -v testvol1:/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
leefile1

 八 Docker 的安全优化

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

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

  • Linux内核的命名空间机制提供的容器隔离安全
  • Linux控制组机制对容器资源的控制能力安全。
  • Linux内核的能力机制所带来的操作权限安全
  • Docker程序(特别是服务端)本身的抗攻击性。
  • 其他安全增强机制对容器安全性的影响
[root@docker-node1 ~]# grubby --update-kernel=/boot/vmlinuz-$(uname -r) \
> --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"

 1 命名空间隔离的安全

  • 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间。命名空间提供了 最基础也最直接的隔离。
  • 与虚拟机方式相比,通过Linux namespace来实现的隔离不是那么彻底。
  • 容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作 系统内核。
  • 在 Linux 内核中,有很多资源和对象是不能被 Namespace 化的,比如:磁盘等等
[root@docker-node1 ~]#  docker run -d --name web nginx
20cebac2da2d036e47acc96650d18b3ef634ae3dbe35801c70c51069ecaea1a7
[root@docker-node1 ~]# docker inspect web  | grep Pid"Pid": 2228,"PidMode": "","PidsLimit": null,
[root@docker-node1 ~]# cd /proc/2228/ns/    #进程的namespace
[root@docker-node1 ns]# ls
cgroup  ipc  mnt  net  pid  pid_for_children  time  time_for_children  user  uts[root@docker-node1 ns]# ls -d /sys/fs/cgroup/memory/docker/20cebac2da2d036e47acc96650d18b3ef634ae3dbe35801c70c51069ecaea1a7/    #资源隔离信息

 2 控制组资源控制的安全

  • 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。
  • Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等 资源。
  • 确保当发生在容器内的资源压力不会影响到本地主机系统和其他容器,它在防止拒绝服务攻击 (DDoS)方面必不可少
#内存资源默认没有被隔离
[root@docker-node1 ~]# docker run  -it --name test busybox
/ # free -mtotal        used        free      shared  buff/cache   available
Mem:           1743         395         832           6         517        1197
Swap:          4096           0        4096
/ # exit
[root@docker-node1 ~]# free -mtotal        used        free      shared  buff/cache   available
Mem:            1743         510         867           5         517        1232
Swap:           4095           0        4095

3 内核能力机制

  • 能力机制(Capability)是Linux内核一个强大的特性,可以提供细粒度的权限访问控制。
  • 大部分情况下,容器并不需要“真正的”root权限,容器只需要少数的能力即可。
  • 默认情况下,Docker采用“白名单”机制,禁用“必需功能”之外的其他权限。

4 Docker服务端防护

  • 使用Docker容器的核心是Docker服务端,确保只有可信的用户才能访问到Docker服务。
  • 将容器的root用户映射到本地主机上的非root用户,减轻容器和主机之间因权限提升而引起的安全 问题。
  • 允许Docker 服务端在非root权限下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。 这些子进程只允许在特定范围内进行操作。
#默认docker是用root用户控制资源的
[root@docker-node1 ~]# ls -ld /var/lib/docker/
drwx--x--- 12 root root 171 Aug 30 14:56 /var/lib/docker/

8.1 Docker的资源限制

Linux Cgroups 的全称是 Linux Control Group。

  • 是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。
  • 对进程进行优先级设置、审计,以及将进程挂起和恢复等操作。

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

  • 它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。
  • 执行此命令查看:mount -t cgroup
[root@docker-node1 ~]# mount -t cgroup         
#在rhel9中默认使用cgroup2
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/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
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/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/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)

  • 在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。
  • 在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录)。
  • 控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的参数指定。

8.1.1.限制cpu使用

1.限制cpu的使用量

#设置 CPU 周期的长度,单位为微秒(通常为100000,即 100 毫秒)

#设置容器在一个周期内可以使用的 CPU 时间,单位也是微秒

#限制cpu的使用
[root@docker-node1 ~]# docker run  -it --rm --name test --cpu-period 100000 --cpu-quota20000 ubuntu
root@c63c40406775:/#  dd if=/dev/zero of=/dev/null &
[1] 9
root@c63c40406775:/# top#在cgroup中查看docker的资源限制
[root@docker-node1 ~]# cat /sys/fs/cgroup/cpu/docker/17a8cb815ec559b4d7e8c8d87034a6058884a16465fb7e5cad98f8e6afe1f1cc/cpu.cfs_quota_us 
20000

2.限制cpu的优先级

#关闭cpu的核心,当cpu都不空闲下才会出现争抢的情况,为了实验效果我们可以关闭一个cpu核心
[root@docker-node1 cpu]# echo 0 > /sys/devices/system/cpu/cpu1/online
[root@docker-node1 cpu]# cat /proc/cpuinfo 
processor	: 0
vendor_id	: AuthenticAMD
cpu family	: 25
model		: 80
model name	: AMD Ryzen 7 5800H with Radeon Graphics
stepping	: 0
cpu MHz		: 3193.999
cache size	: 512 KB
physical id	: 0
siblings	: 1
core id		: 0
cpu cores	: 1            #cpu核心数为1#开启一个容器不限制cpu的优先级
[root@docker-node1 ~]# docker run -it  --rm ubuntu
root@d37c882f9005:/#  dd if=/dev/zero of=/dev/null &
[1] 9
root@d37c882f9005:/# top
top - 04:50:51 up 10:32,  0 user,  load average: 1.33, 0.44, 0.16
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s): 24.6 us, 73.9 sy,  0.0 ni,  0.0 id,  0.0 wa,  1.4 hi,  0.0 si,  0.0 st 
MiB Mem :   1743.5 total,    183.9 free,    765.5 used,    978.5 buff/cache     
MiB Swap:   4096.0 total,   4094.7 free,      1.3 used.    977.9 avail Mem PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND           9 root      20   0    2736   1560   1456 R  90.4   0.1   1:12.96 dd        #cpu为被限制        1 root      20   0    4588   3840   3328 S   0.0   0.2   0:00.02 bash              10 root      20   0    8868   5124   3072 R   0.0   0.3   0:00.01 top               #开启容器并限制资源
[root@docker-node1 ~]# docker run -it  --rm --cpu-shares 100 ubuntu         
#设定cpu优先
级,最大为1024,值越大优先级越高
root@00470db4dc4c:/# dd if=/dev/zero of=/dev/null &
[1] 8
root@00470db4dc4c:/# top
top - 04:50:29 up 10:32,  0 user,  load average: 1.07, 0.33, 0.12
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s): 25.8 us, 72.6 sy,  0.0 ni,  0.0 id,  0.0 wa,  1.6 hi,  0.0 si,  0.0 st 
MiB Mem :   1743.5 total,    183.9 free,    765.6 used,    978.5 buff/cache     
MiB Swap:   4096.0 total,   4094.7 free,      1.3 used.    977.9 avail Mem PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND           8 root      20   0    2736   1408   1408 R   8.9   0.1   0:00.97 dd                1 root      20   0    4588   3840   3328 S   0.0   0.2   0:00.01 bash              9 root      20   0    8868   5248   3200 R   0.0   0.3   0:00.00 top               

8.1.2 限制内存使用

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

#开启容器并限制容器使用内存大小
[root@docker-node1 ~]# docker run -d --name test --memory 200M --memory-swap 200M nginx
accc55186859f2411c3f49b8d67e3d816a88579d2e7159a10baa1a0b6f3600ba#查看容器内存使用限制
[root@docker-node1 ~]# cd  /sys/fs/cgroup/memory/docker/
20cebac2da2d036e47acc96650d18b3ef634ae3dbe35801c70c51069ecaea1a7/
accc55186859f2411c3f49b8d67e3d816a88579d2e7159a10baa1a0b6f3600ba/
[root@docker-node1 ~]# cd  /sys/fs/cgroup/memory/docker/accc55186859f2411c3f49b8d67e3d816a88579d2e7159a10baa1a0b6f3600ba/
[root@docker-node1 accc55186859f2411c3f49b8d67e3d816a88579d2e7159a10baa1a0b6f3600ba]# cat memory.limit_in_bytes 
209715200
[root@docker-node1 accc55186859f2411c3f49b8d67e3d816a88579d2e7159a10baa1a0b6f3600ba]# cat memory.memsw.limit_in_bytes 
209715200[root@docker-node1 ~]# docker run  -d --name test --rm --memory 200M --memory-swap 200M nginx
6674c3655720aa941222b4fecc2b9e325f9ce1083a15d0c17356ac4894b12e26[root@docker-node1 ~]# cgexec -g memory:docker/6674c3655720aa941222b4fecc2b9e325f9ce1083a15d0c17356ac4894b12e26 dd if=/dev/zero of=/dev/shm/bigfile  bs=1M count=150
150+0 records in
150+0 records out
157286400 bytes (157 MB, 150 MiB) copied, 0.324094 s, 485 MB/s
[root@docker-node1 ~]# 
[root@docker-node1 ~]# cgexec -g memory:docker/6674c3655720aa941222b4fecc2b9e325f9ce1083a15d0c17356ac4894b12e26 dd if=/dev/zero of=/dev/shm/bigfile  bs=1M count=180
180+0 records in
180+0 records out
188743680 bytes (189 MB, 180 MiB) copied, 0.28863 s, 654 MB/s
[root@docker-node1 ~]# cgexec -g memory:docker/6674c3655720aa941222b4fecc2b9e325f9ce1083a15d0c17356ac4894b12e26 dd if=/dev/zero of=/dev/shm/bigfile  bs=1M count=120
120+0 records in
120+0 records out
125829120 bytes (126 MB, 120 MiB) copied, 0.10569 s, 1.2 GB/s
[root@docker-node1 ~]# cgexec -g memory:docker/6674c3655720aa941222b4fecc2b9e325f9ce1083a15d0c17356ac4894b12e26 dd if=/dev/zero of=/dev/shm/bigfile  bs=1M count=200
Killed#也可以自建控制器
[root@docker-node1 ~]# mkdir -p /sys/fs/cgroup/memory/x1/
[root@docker-node1 ~]# ls /sys/fs/cgroup/memory/x1/
cgroup.clone_children               memory.memsw.failcnt
cgroup.event_control                memory.memsw.limit_in_bytes
cgroup.procs                        memory.memsw.max_usage_in_bytes
memory.failcnt                      memory.memsw.usage_in_bytes
memory.force_empty                  memory.move_charge_at_immigrate
memory.kmem.failcnt                 memory.numa_stat
memory.kmem.limit_in_bytes          memory.oom_control
memory.kmem.max_usage_in_bytes      memory.pressure_level
memory.kmem.slabinfo                memory.soft_limit_in_bytes
memory.kmem.tcp.failcnt             memory.stat
memory.kmem.tcp.limit_in_bytes      memory.swappiness
memory.kmem.tcp.max_usage_in_bytes  memory.usage_in_bytes
memory.kmem.tcp.usage_in_bytes      memory.use_hierarchy
memory.kmem.usage_in_bytes          notify_on_release
memory.limit_in_bytes               tasks
memory.max_usage_in_bytes
[root@docker-node1 ~]# echo 209715200 > /sys/fs/cgroup/memory/x1/memory.limit_in_bytes #内存可用大小限制
[root@docker-node1 ~]# cat /sys/fs/cgroup/memory/x1/tasks     #此控制器被那个进程调用
[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.0946101 s, 1.1 GB/s
[root@docker-node1 ~]# free -mtotal        used        free      shared  buff/cache   available
Mem:            1743         675         477         106         853        1067
Swap:           4095           0        4095
[root@docker-node1 ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M c
ount=300
300+0 records in
300+0 records out
314572800 bytes (315 MB, 300 MiB) copied, 0.517283 s, 608 MB/s
[root@docker-node1 ~]# free -mtotal        used        free      shared  buff/cache   available
Mem:            1743         774         377         204         951         968
Swap:           4095         102        3993
[root@docker-node1 ~]# 
[root@docker-node1 ~]# rm -rf /dev/shm//bigfile 
[root@docker-node1 ~]# echo 209715200 > /sys/fs/cgroup/memory/x1/memory.memsw.limit_in_bytes		#内存+swap控制
[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:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=199
Killed
[root@docker-node1 ~]# rm -rf /dev/shm/bigfile 
[root@docker-node1 ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=180
180+0 records in
180+0 records out
188743680 bytes (189 MB, 180 MiB) copied, 0.15931 s, 1.2 GB/s
[root@docker-node1 ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=200
Killed

8.1.3 限制docker的磁盘io

[root@docker-node1 ~]# docker run -it --rm --device-write-bps /dev/nvme0n1:30M ubunturoot@9dc480693659:/# dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 3.33741 s, 31.4 MB/sroot@9dc480693659:/# dd if=/dev/zero of=bigfile bs=1M count=100             
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.131838 s, 795 MB/sroot@9dc480693659:/# dd if=/dev/zero of=bigfile                
dd: writing to 'bigfile': No space left on device
4791193+0 records in
4791192+0 records out
2453090304 bytes (2.5 GB, 2.3 GiB) copied, 24.0392 s, 102 MB/s

8.2 Docker的安全加固

8.2.1 Docker默认隔离性

在系统中运行容器,我们会发现资源并没有完全隔离开

[root@docker-node1 ~]# free -mtotal        used        free      shared  buff/cache   available
Mem:            1743         714         235          11         978        1028
Swap:           4095           1        4094
[root@docker-node1 ~]# docker run --rm  --memory 200M -it ubuntu
root@542e4acca41b:/# free -m total        used        free      shared  buff/cache   available
Mem:            1743         766         182          11         978         976
Swap:           4095           1        4094

7.2.2 解决Docker的默认隔离性

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

主要功能:

        1. 资源可见性:

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

        2. 性能监控:

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

1.安装lxcfs

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

2. 运行lxcfs并解决容器隔离性

[root@docker-node1 mnt]# lxcfs  /var/lib/lxcfs &
[root@docker-node1 mnt]# docker run -it --rm --name test \
> -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
> -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \
> -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
> -v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
> -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
> -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
> -m 200M \
> ubuntu
root@9d093b844d82:/# free -mtotal        used        free      shared  buff/cache   available
Mem:             200           1         198           0           0         198
Swap:            400           0         400

8.2.3 容器特权

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

[root@docker-node1 ~]# docker run --rm -it busybox
/ # whoami
root
/ # id root
uid=0(root) gid=0(root) groups=0(root),10(wheel)
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ffinet 172.17.0.3/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever
/ # ip a a 172.25.254.10/24 dev eth0
ip: RTNETLINK answers: Operation not permitted

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

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

[root@docker-node1 ~]# docker run --rm -it --privileged busybox
/ # id root
uid=0(root) gid=0(root) groups=0(root),10(wheel)
/ # ip a a 172.25.254.10/24 dev eth0
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
11: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ffinet 172.17.0.3/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft foreverinet 172.25.254.10/24 scope global eth0valid_lft forever preferred_lft forever
/ # fdisk -l
Disk /dev/nvme0n1: 20 GB, 21474836480 bytes, 41943040 sectors
82241 cylinders, 255 heads, 2 sectors/track
Units: sectors of 1 * 512 = 512 bytesDevice       Boot StartCHS    EndCHS        StartLBA     EndLBA    Sectors  Size Id Type
/dev/nvme0n1p1 *  4,4,1       1023,254,2        2048    2099199    2097152 1024M 83 Linux
/dev/nvme0n1p2    1023,254,2  1023,254,2     2099200   41943039   39843840 18.9G 8e Linux LVM
Disk /dev/dm-0: 15 GB, 16101933056 bytes, 31449088 sectors
1957 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytesDisk /dev/dm-0 doesn't contain a valid partition table
Disk /dev/dm-1: 4096 MB, 4294967296 bytes, 8388608 sectors
522 cylinders, 255 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytesDisk /dev/dm-1 doesn't contain a valid partition table

7.2.4 容器特权的白名单

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

capabilities手册地址: http://man7.org/linux/man-pages/man7/capabilities.7.html

[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 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ffinet 172.17.0.3/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever
/ # ip a a 172.25.254.10/24 dev eth0
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ffinet 172.17.0.3/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft foreverinet 172.25.254.10/24 scope global eth0valid_lft forever preferred_lft forever
/ # fdisk -l

九 容器编排工具Docker Compose

9.1 Docker Compose 概述

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。

其是官方的一个开源项目,托管到github上

网址: https://github.com/docker/compose

主要功能

1. 定义服务:

  • 使用 YAML 格式的配置文件来定义一组相关的容器服务。每个服务可以指定镜像、端口映射、 环境变量、存储卷等参数。
  • 例如,可以在配置文件中定义一个 Web 服务和一个数据库服务,以及它们之间的连接关系。

2. 一键启动和停止:

  • 通过一个简单的命令,可以启动或停止整个应用程序所包含的所有容器。这大大简化了多容器 应用的部署和管理过程。
  • 例如,使用 docker-compose up 命令可以启动配置文件中定义的所有服务,使用 compose down 命令可以停止并删除这些服务。

3. 服务编排:

  • docker 可以定义容器之间的依赖关系,确保服务按照正确的顺序启动和停止。例如,可以指定数据库 服务必须在有序列表 Web 服务之前启动。
  • 支持网络配置,使不同服务的容器可以相互通信。可以定义一个自定义的网络,将所有相关的 容器连接到这个网络上。

4. 环境变量管理:

  • 可以在配置文件中定义环境变量,并在容器启动时传递给容器。这使得在不同环境(如开发、 测试和生产环境)中使用不同的配置变得更加容易。
  • 例如,可以定义一个数据库连接字符串的环境变量,在不同环境中可以设置不同的值。

工作原理

1. 读取配置文件:

  • Docker Compose 读取 YAML 配置文件,解析其中定义的服务和参数。

2. 创建容器:

  • 根据配置文件中的定义,Docker Compose 调用 Docker 引擎创建相应的容器。它会下载所需 的镜像(如果本地没有),并设置容器的各种参数。

3. 管理容器生命周期:

  • Docker Compose 监控容器的状态,并在需要时启动、停止、重启容器。
  • 它还可以处理容器的故障恢复,例如自动重启失败的容器。

Docker Compose 中的管理层

  • 服务 (service) 一个应用的容器,实际上可以包括若干运行相同镜像的容器实例
  • 项目 (project) 由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中 定义
  • 容器(container)容器是服务的具体实例,每个服务可以有一个或多个容器。容器是基于服务定义 的镜像创建的运行实例

9.2 Docker Compose 的常用命令参数

[root@docker-node1 ~]# mkdir test
[root@docker-node1 ~]# cd test/
[root@docker-node1 test]# vim docker-compose.yml 
services:web:image: nginx:latestports:- "80:80"testnode:image: busybox:latestcommand: [ "/bin/sh","-c","sleep 10000" ]

以下是一些 Docker Compose 常用命令:

一、服务管理 1. docker-compose up :

  • 启动配置文件中定义的所有服务。
  • 可以使用 -d 参数在后台启动服务。
  • 可以使用-f 来指定yml文件
  • 例如: docker-compose up -d。
#启动
[root@docker-node1 test]# docker compose up -d
[+] Running 3/3? Network test_default       Created                                              0.1s ? Container test-testnode-1  Started                                              0.8s ? Container test-web-1       Started                                              0.7s 
[root@docker-node1 test]# cd
[root@docker-node1 ~]# docker compose -f test/docker-compose.yml up -d
[+] Running 2/0? Container test-web-1       Running                                              0.0s ? Container test-testnode-1  Running                                              0.0s 

2. docker-compose down :

  • 停止并删除配置文件中定义的所有服务以及相关的网络和存储卷。
[root@docker-node1 ~]# cd test/
[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 

3. docker-compose start :

  • 启动已经存在的服务,但不会创建新的服务。
[root@docker-node1 test]# docker compose start
[+] Running 2/2? Container test-testnode-1  Removed                                             10.1s ? Container test-web-1       Removed                                              0.1s 

二、服务状态查看

1. docker-compose ps :

  • 列出正在运行的服务以及它们的状态,包括容器 ID、名称、端口映射等信息。
[root@docker-node1 test]# docker compose ps

2. docker-compose logs :

  • 查看服务的日志输出。可以指定服务名称来查看特定服务的日志。
[root@docker-node1 test]# docker compose  logs db

三、构建和重新构建服务(了解)

1. docker-compose build :

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

2. docker-compose up --build:

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

四、其他操作

1. docker-compose exec :

  • 在正在运行的服务容器中执行命令。

2. docker-compose pull :

  • 拉取配置文件中定义的服务所使用的镜像。

3. docker-compose config :

  • 验证并查看解析后的 Compose 文件内容

9.3 Docker Compose 的yml文件

Docker Compose 的 YAML 文件用于定义和配置多容器应用程序的各个服务。以下是一个基本的 Docker Compose YAML 文件结构及内容解释:

一、服务(services)

1. 服务名称(service1_name/service2_name 等):

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

 2. 镜像(image):

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

3. 端口映射(ports):

  • 将容器内部的端口映射到主机的端口,以便外部可以访问容器内的服务。例如, "8080:80" 表示将主机的 8080 端口映射到容器内部的 80 端口。
[root@docker-node1 test]# vim docker-compose.yml 
[root@docker-node1 test]# docker compose up -d
WARN[0000] Found orphan containers ([test-testnode-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up. 
[+] Running 2/2? Container test-web-1  Recreated                                                 1.5s ? Container game        Started                                                   0.3s 
[root@docker-node1 test]# cat docker-compose.yml 
services:web:image: mysql:5.7container_name: gamerestart: alwaysexpose:- 1234ports: - "80:8080"

4. 环境变量(environment):

  • 为容器设置环境变量,可以在容器内部的应用程序中使用。例如, VAR1: value1 设置环境变量 VAR1 的值为 value1
[root@docker-node1 test]# vim docker-compose.yml 
[root@docker-node1 test]# docker compose up -d
WARN[0000] Found orphan containers ([test-testnode-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up. 
[+] Running 2/2? Container busybox     Recreated                                                 0.0s ? Container test-web-1  Started                                                   0.2s 
[root@docker-node1 test]# cat docker-compose.yml 
services:web:image: mysql:5.7environment:MYSQL_ROOT_PASSWORD: redhat

5. 存储卷(volumes):

  • 将主机上的目录或文件挂载到容器中,以实现数据持久化或共享。例如, -/host/data:/container/data 将主机上的 /host/data 目录挂载到容器内的/container/data 路径。
[root@docker-node1 test]# vim docker-compose.yml 
[root@docker-node1 test]# docker compose up -d
WARN[0000] Found orphan containers ([test-testnode-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up. 
[+] Running 2/2✔ Container test-web-1  Recreated                                                 1.9s ✔ Container busybox1    Started                                                   0.2s 
[root@docker-node1 test]# cat docker-compose.yml 
services:web:image: busyboxcommand: ["/bin/sh","-c","sleep 3000"]restart: alwayscontainer_name: busybox1volumes:- /etc/passwd:/tmp/passwd:ro

6. 网络(networks):

  • 将服务连接到特定的网络,以便不同服务的容器可以相互通信
[root@docker-node1 test]# vim docker-compose.yml 
[root@docker-node1 test]# docker compose up -d
validating /root/test/docker-compose.yml: services.web Additional property networ_mode is not allowed
[root@docker-node1 test]# vim docker-compose.yml 
[root@docker-node1 test]# docker compose up -d
WARN[0000] Found orphan containers ([test-testnode-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up. 
[+] Running 1/1? Container busybox1  Started                                                    10.3s 
[root@docker-node1 test]# cat docker-compose.yml 
services:web:image: nginxcontainer_name: busybox1network_mode: bridge

[root@docker-node1 test]# vim docker-compose.yml 
[root@docker-node1 test]# docker compose up -d
[+] Running 1/0? Network test_mynet2  Created                                                    0.1s ? Network test_mynet1  Creating                                                   0.0s 
[+] Running 4/4d orphan containers ([test-testnode-1]) for this project. If you removed  ? Network test_mynet2  Created                                                    0.1s  ? Network test_mynet1  Created                                                    0.1s ? Container busybox1   Recreated                                                  0.1s ? Container webserver  Started                                                    0.3s 
[root@docker-node1 test]# cat docker-compose.yml 
services:web:image: busyboxcontainer_name: webservercommand: ["/bin/sh","-c","sleep=100000"]networks:- mynet1- mynet2networks:mynet1:driver: bridgemynet2:driver: bridge

7. 命令(command):

  • 覆盖容器启动时默认执行的命令。例如, command: python app.py 指定容器启动时运行python app.py 命令
[root@docker-node1 test]# vim docker-compose.yml 
[root@docker-node1 test]# docker compose up -d
WARN[0000] Found orphan containers ([test-testnode-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up. 
[+] Running 2/2? Container webserver  Recreated                                                  0.0s ? Container busybox    Started                                                    0.2s 
[root@docker-node1 test]# cat docker-compose.yml 
services:web:image: busyboxcontainer_name: busyboxcommand: ["/bin/sh","-c","sleep=100000"]

二、网络(networks)

  • 定义 Docker Compose 应用程序中使用的网络。可以自定义网络名称和驱动程序等属性。
  • 默认情况下docker compose 在执行时会自动建立网路
[root@docker-node1 test]# vim docker-compose.yml 
services:test1:image: busybox:latestcommand: ["/bin/sh","-c","sleep 3000"]restart: alwaysnetwork_mode: defaultcontainer_name: busybox1_containertest2:image: busybox:latestcommand: ["/bin/sh","-c","sleep 3000"]restart: alwayscontainer_name: busybox2_containernetworks:- mynet1test3:image: busybox:latestcommand: ["/bin/sh","-c","sleep 3000"]restart: alwayscontainer_name: busybox3_containernetworks:- mynet1networks:mynet1:driver: bridgedefault:external: truename: bridgemynet2:ipam:driver: defaultconfig: - subnet: 172.18.0.0/16gateway: 172.28.0.254[root@docker-node1 test]# docker compose up -d
WARN[0000] Found orphan containers ([test-testnode-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up. 
[+] Running 3/3? Container busybox2_container  Started                                          10.7s ? Container busybox3_container  Started                                          10.7s ? Container busybox1_container  Started                                          10.7s 

三、存储卷(volumes)

  • 定义 Docker Compose 应用程序中使用的存储卷。可以自定义卷名称和存储位置等属性。
services:test:image: busyboxcommand: ["/bin/sh","-c","sleep 3000"]restart: alwayscontainer_name: busybox1volumes:- data:/test                          - /etc/passwd:/tmp/passwd:ro          
volumes:data:name: timinglee                         

9.4 企业示例

[root@docker-node1 test]# vim haproxy.yml 
services:web1:image: nginx:latestrestart: alwayscontainer_name: webserver1networks:- mynet1expose:- 80volumes:- data_web1:/usr/share/nginx/htmlweb2:image: nginx:latestrestart: alwayscontainer_name: webserver2networks:- mynet1expose:- 80volumes:- data_web2:/usr/share/nginx/htmlhaproxy:image: haproxy:2.3restart: alwayscontainer_name: haproxynetworks:- mynet1- mynet2volumes:- /var/lib/docker/volumes/conf/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfgports:- "80:80"networks:mynet1:driver: bridgemynet2:driver: bridgevolumes:data_web1:name: data_web1data_web2:name: data_web2[root@docker-node1 ~]# cd /var/lib/docker/volumes/conf/
[root@docker-node1 conf]# vim haproxy.cfg
listen webclusterbind *:80balance roundrobinserver web1 webserver1:80 check inter 3 fall 3 rise 5server web2 webserver2:80 check inter 3 fall 3 rise 5[root@docker-node1 test]# echo webserver1 > /var/lib/docker/volumes/data_web1/_data/index.html
[root@docker-node1 test]# echo webserver2 > /var/lib/docker/volumes/data_web2/_data/index.html[root@docker-node1 test]# docker compose -f haproxy.yml up -d
[+] Running 5/5✔ Network test_mynet1   Created                                                   0.1s ✔ Network test_mynet2   Created                                                   0.1s ✔ Container haproxy     Started                                                   1.0s ✔ Container webserver1  Started                                                   0.9s ✔ Container webserver2  Started                                                   0.8s [root@docker-node1 test]# docker compose ps
NAME         IMAGE          COMMAND                  SERVICE   CREATED         STATUS         PORTS
haproxy      haproxy:2.3    "docker-entrypoint.s…"   haproxy   5 seconds ago   Up 4 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp
webserver1   nginx:latest   "/docker-entrypoint.…"   web1      5 seconds ago   Up 5 seconds   80/tcp
webserver2   nginx:latest   "/docker-entrypoint.…"   web2      5 seconds ago   Up 5 seconds   80/tcp
[root@docker-node1 test]# curl 172.25.254.100
webserver1
[root@docker-node1 test]# curl 172.25.254.100
webserver2

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 使用docker部署project-exam-system(项目)
  • QT connect的使用
  • SLM2110CG 1.0A/1.6A600V完美代替IR2110 精准驱动,可靠之芯 高压、高速的功率MOSFET和IGBT驱动器
  • 【深度解读】知识库的作用
  • NVIDIA GeForce RTX标志升级 加入AI的力量
  • 9、Django Admin优化查询
  • MacOS下WKWebView设置背景透明问题
  • 行业内幕曝光!全域运营公司究竟哪家好?
  • 【mac】MAC命令快速模糊查找文件
  • MySQL的事务认识
  • 国产游戏技术:迈向全球引领者的征途
  • 构建高效搜索系统 - Faiss向量数据库的快速入门
  • windows C++ 并行编程-并发的异常处理(三)
  • 关于一个早期的计算机网络的理解
  • JAVAEE初阶第二节——多线程基础(上)
  • android 一些 utils
  • CentOS 7 防火墙操作
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • JavaScript服务器推送技术之 WebSocket
  • JavaScript设计模式之工厂模式
  • JavaScript实现分页效果
  • Java-详解HashMap
  • Netty 4.1 源代码学习:线程模型
  • Spring声明式事务管理之一:五大属性分析
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 从输入URL到页面加载发生了什么
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 对象引论
  • 记一次删除Git记录中的大文件的过程
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 微信小程序--------语音识别(前端自己也能玩)
  • 由插件封装引出的一丢丢思考
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • 新海诚画集[秒速5センチメートル:樱花抄·春]
  • 昨天1024程序员节,我故意写了个死循环~
  • # 达梦数据库知识点
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • %check_box% in rails :coditions={:has_many , :through}
  • ()、[]、{}、(())、[[]]命令替换
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第1节 (全局数据、栈和堆)
  • (pycharm)安装python库函数Matplotlib步骤
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (web自动化测试+python)1
  • (九)One-Wire总线-DS18B20
  • (六)软件测试分工
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (三) diretfbrc详解
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • ***详解账号泄露:全球约1亿用户已泄露
  • .gitattributes 文件
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .Net Core 中间件与过滤器
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃