Docker容器技术

Docker简介及部署方法

1 Docker简介

1. 什么是docker?

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

重要特点和优势:

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

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

2.docker在企业中的应用场景

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

注:

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

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

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

3.docker与虚拟化的对比

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

4.docker的优势

  • 对于开发人员:Build once、Run anywhere。

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

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

2 部署docker

  1. 容器工作方法

  2. 部署第一个容器

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

配置软件仓库

bash 复制代码
#利用阿里云部署软件仓库
[root@docker-node1 ~]# vim /etc/yum.repos.d/docker.repo
[docker]
name=docker-ce
baseurl=https://mirrors.aliyun.com/docker-ce/linux/rhel/9/x86_64/stable
gpgcheck=0

安装docker-ce并启动服务

bash 复制代码
#更新软件源信息,并生成本地缓存
[root@docker-node1 ~]# dnf makecache
正在更新 Subscription Management 软件仓库。
无法读取客户身份

本系统尚未在权利服务器中注册。可使用 "rhc" 或 "subscription-manager" 进行注册。

docker                                                              7.3 kB/s |  46 kB     00:06
AppStream                                                           3.1 MB/s | 3.2 kB     00:00
BaseOS                                                              2.7 MB/s | 2.7 kB     00:00
元数据缓存已建立。

[root@docker-node1 ~]# dnf search docker
正在更新 Subscription Management 软件仓库。
无法读取客户身份

本系统尚未在权利服务器中注册。可使用 "rhc" 或 "subscription-manager" 进行注册。

上次元数据过期检查:2 days, 2:21:10 前,执行于 2026年03月15日 星期日 14时49分42秒。
================================== 名称 和 概况 匹配:docker ==================================
docker-buildx-plugin.x86_64 : Docker Buildx plugin for the Docker CLI
docker-ce-rootless-extras.x86_64 : Rootless support for Docker
docker-compose-plugin.x86_64 : Docker Compose plugin for the Docker CLI
docker-model-plugin.x86_64 : Docker Model Runner plugin for the Docker CLI
pcp-pmda-docker.x86_64 : Performance Co-Pilot (PCP) metrics from the Docker daemon
podman-docker.noarch : Emulate Docker CLI using podman
====================================== 名称 匹配:docker ======================================
docker-ce.x86_64 : The open-source application container engine
docker-ce-cli.x86_64 : The open-source application container engine

[root@docker-node1 ~]# dnf install docker-ce-3:28.5.2-1.el9 -y

激活内核网络选项

bash 复制代码
[root@docker-node1 ~]# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --iptables=true

[root@docker-node1 ~]# echo br_netfilter > /etc/modules-load.d/docker_mod.conf
[root@docker-node1 ~]# modprobe -a br_netfilter
[root@docker-node1 ~]# vim /etc/sysctl.d/docker.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1

[root@docker-node1 ~]# sysctl --system
[root@docker-node1 ~]# systemctl enable --now docker

设定docker加速器

bash 复制代码
[root@docker-node1 ~]# vim /etc/docker/daemon.json
{
    "registry-mirrors": ["https://docker.1ms.run"]
}

[root@docker-node1 ~]# systemctl restart docker
[root@docker-node1 ~]# docker info
 Registry Mirrors:
  https://docker.1ms.run/

Docker的基本操作

1 Docker 镜像管理

镜像查看

root@docker-node1 \~\]# docker images IMAGE ID DISK USAGE CONTENT SIZE EXTRA 搜索镜像 \[root@docker-node1 \~\]# docker search nginx NAME DESCRIPTION STARS OFFICIAL nginx Official build of Nginx. 21206 下载镜像 \[root@docker-node1 \~\]# docker pull nginx Using default tag: latest latest: Pulling from library/nginx 9eef040df109: Pull complete df9da45c1db2: Pull complete 79697674b897: Pull complete a9d395129dce: Pull complete 206356c42440: Pull complete 75a1d70aee50: Pull complete 18a071c04bd1: Pull complete 23abb0f9ce55: Download complete d99947bc9177: Download complete Digest: sha256:bc45d248c4e1d1709321de61566eb2b64d4f0e32765239d66573666be7f13349 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest \[root@docker-node1 \~\]# docker pull busybox Using default tag: latest latest: Pulling from library/busybox 61dfb50712f5: Pull complete 96cfb76e59bd: Download complete Digest: sha256:b3255e7dfbcd10cb367af0d409747d511aeb66dfac98cf30e97e87e4207dd76f Status: Downloaded newer image for busybox:latest docker.io/library/busybox:latest 查看镜像提交历史 \[root@docker-node1 \~\]# docker history busybox:latest IMAGE CREATED CREATED BY SIZE COMMENT b3255e7dfbcd 17 months ago BusyBox 1.37.0 (glibc), Debian 13 4.49MB \[root@docker-node1 \~\]# docker images IMAGE ID DISK USAGE CONTENT SIZE EXTRA busybox-file:latest e93187408c68 6.71MB 2.21MB nginx:1.26 41b194461e4b 279MB 75.2MB 导出镜像 \[root@docker-node1 \~\]# docker save -o game2048-latest.tar timinglee/game2048:latest 删除镜像 \[root@docker-node1 \~\]# docker rmi timinglee/mario:latest 导入镜像 \[root@docker-node1 \~\]# docker load -i game2048-latest.tar 运行镜像 \[root@docker-node1 \~\]# docker run -d --name web nginx:1.26 0471dadd1d29c72b28ba6dad490277a7bb65c682c13c8341bccf74add988cdc4

-d #后台运行

-i #交互式运行

-t #打开一个终端

--name #指定容器名称

-p #端口映射 -p 80:8080 把容器8080端口映射到本机80端口

--rm #容器停止自动删除容器

--network #指定容器使用的网络
查看运行容器

root@docker-node1 \~\]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0471dadd1d29 nginx:1.26 "/docker-entrypoint...." About a minute ago Up About a minute 80/tcp web 查看所有容器 \[root@docker-node1 \~\]# docker ps -a 交互模式运行容器 \[root@docker-node1 \~\]# docker run -it --name busybox busybox:latest 交互运行容器默认退出后会停止 \[root@docker-node1 \~\]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0471dadd1d29 nginx:1.26 "/docker-entrypoint...." 4 minutes ago Up 4 minutes 80/tcp web 3472b02fe085 busybox:latest "sh" 2 days ago Exited (137) 2 days ago test 运行停止的容器 \[root@docker-node1 \~\]# docker start busybox root@docker-node1 \~\]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d1b27167a247 busybox:latest "sh" 2 minutes ago Up 1 second busybox 运行停止的容器 \[root@docker-node1 \~\]# docker start busybox root@docker-node1 \~\]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d1b27167a247 busybox:latest "sh" 2 minutes ago Up 1 second busybox 退出交互容器不对其停止 \[root@docker-node1 \~\]# docker attach busybox / # \[ctrl\]+\[p\]+\[q\] #按键 \[root@docker-node1 \~\]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d1b27167a247 busybox:latest "sh" 3 minutes ago Up About a minute busybox 查看容器信息 \[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 exec busybox touch /root/haha #非交互 \[root@docker-node1 \~\]# docker exec busybox ls /root file1 file2 haha \[root@docker-node1 \~\]# docker exec -it web /bin/bash #交互的 root@f3e369725fab:/# 容器删除 \[root@docker-node1 \~\]# docker rm -f busybox busybox \[root@docker-node1 \~\]# docker stop web web \[root@docker-node1 \~\]# docker rm web web 内容提交 注: 默认情况下,容器被删除后,在容器中的所有操作都会被清理,包括要保存的文件 如果想永久保存,那么我们需要把动作提交,提交后会生成新的镜像 当我们在运行新镜像后即可看到我们提交的内容 \[root@docker-node1 \~\]# docker run -it --name test busybox:latest / # touch /root/file / # ls /root/ file ctrl+qp 退出当前环境并继续运行容器 \[root@docker-node1 \~\]# docker commit -m "add file" test busybox-file:latest sha256:31a32089d241d025a5a54f144f15319cc6fb55be1b41d049f8905a472d5a028e \[root@docker-node1 \~\]# docker images i Info → U In Use IMAGE ID DISK USAGE CONTENT SIZE EXTRA busybox-file:latest 31a32089d241 6.71MB 2.21MB \[root@docker-node1 \~\]# docker run -it --name test busybox-file:latest 文件在镜像中的复制 \[root@docker-node1 \~\]# docker run -it --name test busybox-file:latest root@docker-node1 \~\]# docker cp test:/root/file /mnt Successfully copied 1.54kB to /mnt \[root@docker-node1 \~\]# ls /mnt/ file hgfs \[root@docker-node1 \~\]# docker cp /etc/passwd test:/root/ Successfully copied 3.07kB to test:/root/ \[root@docker-node1 \~\]# docker exec test ls /root file passwd

Docker 镜像构建

1 docker镜像结构

  • 共享宿主机的kernel

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

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

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

2 镜像运行的基本原理

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

3 镜像获得方式

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

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

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

    docker pull 镜像地址
    docker load --i 本地镜像包

4 镜像构建

构建参数

指令 说明 示例
FROM 指定基础镜像 FROM busybox:version
COPY 复制文件或目录到镜像中 COPY file /fileCOPY ["file","/"]
MAINTAINER 指定作者信息(如邮箱),新版 Docker 中建议用 LABEL替代 MAINTAINER user@example.com(旧版)
ADD 功能类似 COPY,但支持自动解压压缩包或从 URL 下载文件 ADD test.tar /mntADD http://ip/test.tar /mnt
ENV 设置环境变量 ENV FILENAME test
EXPOSE 声明容器运行时对外暴露的端口 EXPOSE 80
VOLUME 声明数据卷(挂载点),用于持久化数据 VOLUME ["/var/www/html"]
WORKDIR 设置工作目录,后续指令默认在此目录下执行 WORKDIR /mnt
RUN 在构建镜像过程中执行命令(每执行一次 RUN 会生成一层镜像) RUN touch file
CMD 指定容器启动时默认执行的命令(可被覆盖) CMD ["/bin/sh", "-c", "echo $NAME"] 会调用shell解析 CMD ["/bin/echo", "$NAME"] 不调用shell解析
ENTRYPOINT 与 CMD 类似,但容器启动时的命令不可被覆盖,常用于固定入口程序 与 CMD 用法类似,但更强调"不可被覆盖"的特性

参数示例及用法

FROM COPY LABEL ADD

bash 复制代码
#建立构建目录
[root@docker-node1 ~]# mkdir docker
[root@docker-node1 ~]# cd docker/

#COPY    复制文件
#编写构建规则文件
[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest        #指定使用的基础镜像
COPY timinglee /root       #复制当前目录文件到容器指定位置,timinglee必须在当前目录中

[root@docker-node1 docker]# echo timinglee > timinglee
[root@docker-node1 docker]# cat timinglee
timinglee

#构建命令
[root@docker-node1 docker]# docker build -t timinglee:v1 .   #构建镜像
[+] Building 10.5s (7/7) FINISHED                                               docker:default
 => [internal] load build definition from Dockerfile                                      0.0s
 => => transferring dockerfile: 78B                                                       0.0s
 => [internal] load metadata for docker.io/library/busybox:latest                        10.3s
 => [internal] load .dockerignore                                                         0.0s
 => => transferring context: 2B                                                           0.0s
 => [internal] load build context                                                         0.0s
 => => transferring context: 46B                                                          0.0s
 => [1/2] FROM docker.io/library/busybox:latest@sha256:b3255e7dfbcd10cb367af0d409747d511  0.0s
 => => resolve docker.io/library/busybox:latest@sha256:b3255e7dfbcd10cb367af0d409747d511  0.0s
 => CACHED [2/2] COPY timinglee /root                                                     0.0s
 => exporting to image                                                                    0.1s
 => => exporting layers                                                                   0.0s
 => => exporting manifest sha256:276ec2e7c5470733f55d38b39d194c7206fb6d4558ace9977f01354  0.0s
 => => exporting config sha256:5e0ed7cc92fbb073473128bfc3eafba921185467a33753c72a67f559a  0.0s
 => => exporting attestation manifest sha256:ad5cdc2dc693dfa7cd48a752db2eb8c759eb71e817d  0.0s
 => => exporting manifest list sha256:d8d52842119cf8801716c627abae70488da9fe3a3eb4287968  0.0s
 => => naming to docker.io/library/timinglee:v1                                           0.0s
 => => unpacking to docker.io/library/timinglee:v1


#ADD    功能和copy相似,指定压缩文件或url
[root@docker-node1 docker]# echo lee > lee
[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest
LABEL Creater=lee        元数据标签,添加标签标注创建者为 "lee"
COPY timinglee  /root
ADD lee /root

[root@docker-node1 docker]# docker build -t lee:v1 .
[root@docker-node1 docker]# docker history  lee:v1
IMAGE          CREATED         CREATED BY                          SIZE      COMMENT
d8a91be8df68   2 days ago      COPY timinglee /root # buildkit     4.1kB     buildkit.dockerfile.v0
<missing>      2 days ago      LABEL Create=lee                    0B        buildkit.dockerfile.v0
<missing>      17 months ago   BusyBox 1.37.0 (glibc), Debian 13   4.49MB

[root@docker-node1 docker]# docker build -t lee:v2 .
[root@docker-node1 docker]# docker run  -it --name test --rm lee:v2
/ # cat /root/*
lee
timinglee

#add可以解压缩COPY不能
[root@docker-node1 docker]# tar zcf bin.tar.gz /bin
tar: 从成员名中删除开头的"/"
[root@docker-node1 docker]# ls
bin.tar.gz  Dockerfile  lee  timinglee

[root@docker-node1 docker]# vim Dockerfile
FROM busybox:latest
LABEL Creater=lee
COPY bin.tar.gz /root
ADD bin.tar.gz /mnt

[root@docker-node1 docker]# docker build -t lee:v3 .
[root@docker-node1 docker]# docker run  -it --name test --rm lee:v3
/ # ls /root/
bin.tar.gz
/ # ls /mnt/
bin
/ #

ENV EXPOSE VOLUME WORKDIR RUN

bash 复制代码
#ENV    指定环境变量
[root@docker-node1 docker]# vim Dockerfile
ENV NAME=timinglee    
RUN ["/bin/sh","-c","touch /root/$NAME" ]      #使用ENV变量

[root@docker-node1 docker]# docker build -t lee:v4 .
[root@docker-node1 docker]# docker run  -it --name test --rm lee:v4
/ # ls /root/
timinglee

#EXPOSE    暴漏容器端口
[root@docker-node1 docker]# vim Dockerfile
EXPOSE 8080

[root@docker-node1 docker]# docker build -t lee:v5 .
[root@docker-node1 docker]# docker history lee:v5
IMAGE          CREATED         CREATED BY                                    SIZE      COMMENT
79cb903371c2   16 hours ago    RUN /bin/sh -c touch /root/$NAME # buildkit   0B        buildkit.dockerfile.v0
<missing>      16 hours ago    EXPOSE [8080/tcp]                             0B        buildkit.dockerfile.v0
<missing>      16 hours ago    ENV NAME=timinglee                            0B        buildkit.dockerfile.v0
<missing>      16 hours ago    LABEL Create=lee                              0B        buildkit.dockerfile.v0
<missing>      17 months ago   BusyBox 1.37.0 (glibc), Debian 13             4.49MB



#VOLUEM    申明数据卷,通常指数据挂载点
[root@docker-node1 docker]# docker inspect lee:v5 | grep -i mount		#查看是否有挂载

[root@docker-node1 docker]# vim Dockerfile
VOLUME "/mnt"    

[root@docker-node1 docker]# docker build -t lee:v6 .
[root@docker-node1 docker]# docker run  -it --name test --rm lee:v6
/ # 

#在复制的session中查看挂载信息
[root@docker-node1 ~]# docker inspect test | grep -i mounts -A10
        "Mounts": [
            {
                "Type": "volume",
                "Name": "cc96cc9f29e86d6049722c3aa1ff01359d5e87b93c9810a8af84776e92aff93f",
                "Source": "/var/lib/docker/volumes/cc96cc9f29e86d6049722c3aa1ff01359d5e87b93c9810a8af84776e92aff93f/_data",
                "Destination": "/mnt",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }


[root@docker-node1 ~]# cd /var/lib/docker/volumes/cc96cc9f29e86d6049722c3aa1ff01359d5e87b93c9810a8af84776e92aff93f/_data
[root@docker-node1 _data]# touch lee{1..5}

#在容器里
/ # ls /mnt/
lee1  lee2  lee3  lee4  lee5


#WORKDIR    切换路径到/mnt
[root@docker-node1 docker]# vim Dockerfile
WORKDIR "/mnt"     

[root@docker-node1 docker]# docker build -t lee:v7 .
[root@docker-node1 docker]# docker run -it --name test --rm lee:v7
/mnt #


#CMD    在启动容器时自动运行动作可以被覆盖
[root@docker-node1 docker]# vim Dockerfile
CMD ["/bin/echo","$NAME"]    #不调用shell解析

[root@docker-node1 docker]# docker build -t lee:v8 .
[root@docker-node1 docker]# docker run -it --name test --rm lee:v8
$NAME
[root@docker-node1 docker]# docker history lee:v8
IMAGE          CREATED             CREATED BY                                    SIZE      COMMENT
4906888beb96   About an hour ago   CMD ["/bin/echo" "$NAME"]                     0B        buildkit.dockerfile.v0
[root@docker-node1 docker]# docker run -it --name test --rm lee:v8 echo haha
haha

[root@docker-node1 docker]# vim Dockerfile
#CMD ["/bin/echo", "$NAME"]
CMD ["/bin/sh", "-c", "/bin/echo $NAME"]    #会调用shell解析

[root@docker-node1 docker]# docker run -it --name test --rm lee:v9
timinglee
[root@docker-node1 docker]# docker run -it --name test --rm lee:v9 echo haha
haha

#ENTRYPOINT     和CMD功能和用法类似,但动作不可被覆盖
[root@docker-node1 docker]# vim Dockerfile
ENTRYPOINT ["/bin/sh","-c","echo $NAME"]

[root@docker-node1 docker]# docker build -t lee:v10 .
[root@docker-node1 docker]# docker run -it --name test --rm lee:v10
timinglee
[root@docker-node1 docker]# docker run -it --name test --rm lee:v10 echo haha
timinglee

5 构建centos可用仓库实验

bash 复制代码
[root@docker-node1 docker]# docker pull centos:7
7: Pulling from library/centos
2d473b07cdd5: Pull complete
Digest: sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4
Status: Downloaded newer image for centos:7
docker.io/library/centos:7

[root@docker-node1 docker]# docker run -it --name centos centos:7 /bin/bash
[root@acb20a81363e /]# cat /etc/centos-release    #查看centos版本
CentOS Linux release 7.9.2009 (Core)
[root@acb20a81363e /]# ls /etc/yum.repos.d/
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@docker-node1 docker]# vim Dockerfile
FROM centos:7
LABEL Creater=lee
RUN ["/bin/bash", "-c", "rm -rf /etc/yum.repos.d/*"]    #centos:7 版本内容已停更,其软件仓库
                                                        #也无法使用,需全部删除
COPY centos7.repo /etc/yum.repos.d/centos7.repo

[root@docker-node1 docker]# docker images
                                                                          i Info →   U  In Use
IMAGE               ID             DISK USAGE   CONTENT SIZE   EXTRA
busybox:latest      b3255e7dfbcd        6.7MB         2.22MB    U
centos-7:repo       a19555d37a6e        299MB         76.1MB
centos:7            be65f488b776        299MB         76.1MB    U
nginx:1.26          41b194461e4b        279MB         75.2MB    U
nginx:1.26-alpine   1eadbb078203       71.6MB         21.5MB

[root@docker-node1 docker]# docker build -t centos-7:repo .
[root@docker-node1 docker]# docker run -it --name centos --rm centos-7:repo /bin/bash          
[root@d82cca7cbcd6 /]# ls /etc/yum.repos.d/  

#手动指定能用源
[root@docker-node1 docker]# vim centos7.repo
[centos7]
name = centos7
baseurl= https://mirrors.aliyun.com/centos-vault/7.9.2009/os/x86_64/
gpgcheck= 0


[root@docker-node1 docker]# docker build -t centos-7:repo .
[root@docker-node1 docker]# docker run -it --name centos --rm centos-7:repo /bin/bash
[root@327abc3e07e3 /]# yum install gcc -y

6 镜像优化方案

1.镜像优化策略

  • 选择最精简的基础镜像

  • 减少镜像的层数

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

2.镜像优化示例

方法一:缩减镜像

bash 复制代码
[root@server1 docker]# vim Dockerfile
FROM centos:7 AS build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.23.3 && yum clean all
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]

[root@server1 docker]# docker build -t webserver:v2 .

[root@server1 docker]# docker images  webserver
REPOSITORY   TAG       IMAGE ID       CREATED             SIZE
webserver    v2        caf0f80f2332   4 seconds ago       317MB
webserver    v1        bfd6774cc216   About an hour ago   494MB

方法二:多阶段构建

bash 复制代码
[root@server1 docker]# vim Dockerfile
FROM centos:7 AS build
ADD nginx-1.23.3.tar.gz /mnt
WORKDIR /mnt/nginx-1.23.3
RUN yum install -y gcc make pcre-devel openssl-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --with-http_ssl_module --with-http_stub_status_module && make && make install && cd .. && rm -fr nginx-1.23.3 && yum clean all

FROM centos:7
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@server1 docker]# docker build -t webserver:v3 .

[root@server1 docker]# docker images  webserver
REPOSITORY   TAG       IMAGE ID       CREATED             SIZE
webserver    v3        1ac964f2cefe   29 seconds ago      205MB
webserver    v2        caf0f80f2332   3 minutes ago       317MB
webserver    v1        bfd6774cc216   About an hour ago   494MB

方法三:使用最精简镜像

使用google提供的最精简镜像

下载地址:

https://github.com/GoogleContainerTools/distroless

下载镜像:

docker pull gcr.io/distroless/base-debian11

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

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


[root@docker-node1 docker]# docker build -t webserver:v1 .
[+] Building 10.7s (9/9) FINISHED                                               docker:default
 => [internal] load build definition from Dockerfile                                      0.0s
 => => transferring dockerfile: 1.27kB                                                    0.0s
 => [internal] load metadata for docker.io/library/nginx:1.26                            10.3s
 => [internal] load metadata for gcr.io/distroless/base-debian11:latest                   0.2s
 => [internal] load .dockerignore                                                         0.0s
 => => transferring context: 2B                                                           0.0s
 => [base 1/2] FROM docker.io/library/nginx:1.26@sha256:41b194461e4bae16f9b25d68b0976ed4  0.0s
 => => resolve docker.io/library/nginx:1.26@sha256:41b194461e4bae16f9b25d68b0976ed4735b8  0.0s
 => [stage-1 1/2] FROM gcr.io/distroless/base-debian11:latest@sha256:cac381e9184d647928d  0.0s
 => => resolve gcr.io/distroless/base-debian11:latest@sha256:cac381e9184d647928d96962ec6  0.0s
 => CACHED [base 2/2] RUN mkdir -p /opt/var/cache/nginx &&     cp -a --parents /usr/lib/  0.0s
 => CACHED [stage-1 2/2] COPY --from=base /opt /                                          0.0s
 => exporting to image                                                                    0.1s
 => => exporting layers                                                                   0.0s
 => => exporting manifest sha256:5b01a0228089b35735b5eeaf6862e84b10ee6fe825f72319d48d4d1  0.0s
 => => exporting config sha256:86fb7b9b021d6bd39f3443154e2b88046b1efa75d6823e04c23395299  0.0s
 => => exporting attestation manifest sha256:78a25785dc5a57977f9701e9047a614f167b9e2235a  0.0s
 => => exporting manifest list sha256:ead32f4875bbe8a5e168944b5261745e167b50ca5097aea42e  0.0s
 => => naming to docker.io/library/webserver:v1                                           0.0s
 => => unpacking to docker.io/library/webserver:v1                                        0.0s

[root@docker-node1 docker]# docker images  webserver:v1
                                                                          i Info →   U  In Use
IMAGE          ID             DISK USAGE   CONTENT SIZE   EXTRA
webserver:v1   ead32f4875bb       84.9MB         33.6MB

docker 镜像仓库管理

1 什么是docker仓库

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

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

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

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

    eg:您想要部署一个 Nginx 服务器,就可以从 Docker Hub 上拉取 Nginx 的镜像。

  • 私有仓库则是由组织或个人自己搭建和管理的,用于存储内部使用的、不希望公开的镜像。

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

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

2 docker hub及使用方法


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

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

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

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

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

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

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

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

1.docker hub的使用方法

#登陆官方仓库

root@docker \~\]# docker login Log 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: timinglee 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 \~\]# cd .docker/ \[root@docker .docker\]# ls config.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:latest The push refers to repository \[docker.io/timinglee/base-debian11

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:f8179c20f1f2b1168665003412197549bd4faab5ccc1b140c666f9b8aa958042 size: 3234

Tip:
在国内因为网络等原因, docker hub 连接困难,可以使用国内的镜像加速解决镜像无法下载的问题

bash 复制代码
[root@harbor docker]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://docker.m.daocloud.io"],
}
[root@harbor docker]# systemctl restart docker

3 docker仓库的工作原理

仓库中的三个角色

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

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

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

1. pull原理

2. push原理

镜像上传的步骤:
1.client 向 index 发送上传请求并完成用户认证
2.index 会发方 token 给 client 来证明 client 的合法性
3.client 携带 index 提供的 token 连接 Registry
4.Registry 向 index 合适 token 的合法性
5.index 证实 token 的合法性
6.Registry 开始接收客户端上传过来的镜像

4 搭建docker的私有仓库

1. 为什么搭建私有仓库

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

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

好消息是 docker 公司已经将 registry 开源,我们可以快速构建企业私有仓库
地址: https://docs.docker.com/registry/deploying/

2. 搭建简单的Registry仓库

下载Registry镜像

root@docker \~\]# docker pull registry Using default tag: latest latest: Pulling from library/registry 930bdd4d222e: Pull complete a15309931e05: Pull complete 6263fb9c821f: Pull complete 86c1d3af3872: Pull complete a37b1bf6a96f: Pull complete Digest: sha256:12120425f07de11a1b899e418d4b0ea174c8d4d572d45bdb640f93bc7ca06a3d Status: Downloaded newer image for registry:latest docker.io/library/registry:latest **开启Registry** \[root@docker \~\]# docker run -d -p 5000:5000 --restart=always --name registry registry bc58d3753a701ae67351fac335b06a4d7f66afa10ae60b992f647117827734c5 \[root@docker \~\]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES bc58d3753a70 registry "/entrypoint.sh /etc..." 7 seconds ago Up 6 seconds 5000/tcp, 0.0.0.0:5000-\>5000/tcp, :::5000-\>5000/tcp registry **上传镜像到仓库中** #给要上传的经镜像大标签 \[root@docker \~\]# docker tag busybox:latest 172.25.254.100:5000/busybox:latest #docker在上传的过程中默认使用https,但是我们并没有建立https认证需要的认证文件所以会报错 \[root@docker \~\]# 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/": dial tcp 172.25.254.100:5000: connect: connection refused

#配置非加密端口

root@docker \~\]# vim /etc/docker/daemon.json { "insecure-registries" : \["http://172.25.254.100:5000"

}

root@docker \~\]# systemctl restart docker #上传镜像 \[root@docker \~\]# 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 \~\]# curl 172.25.254.100:5000/v2/_catalog {"repositories":\["busybox"\]}

3.为registry加密传输

生成认证key和证书

bash 复制代码
[root@docker-node1 ~]# mkdir /etc/docker/certs
[root@docker-node1 docker]# openssl req -newkey rsa:4096 \
> -nodes -sha256 -keyout /etc/docker/certs/timinglee.org.key \
> -addext "subjectAltName = DNS:reg.timinglee.org" \
> -x509 -days 365 -out /etc/docker/certs/timinglee.org.crt
...
Common Name (eg, your name or your server's hostname) []:reg.timinglee.org    #与dns一致
...

[root@docker-node1 docker]# ls /etc/docker/certs/
timinglee.org.crt  timinglee.org.key

查看证书信息

启动registry仓库

bash 复制代码
[root@docker-node1 docker]# docker run -d -p 443:443 --restart=always --name registry \
> -v /etc/docker/certs:/certs \
> -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
> -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \
> -e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key registry
Unable to find image 'registry:latest' locally
latest: Pulling from library/registry
3e2f893a11ee: Pull complete
bc1da058f299: Pull complete
7369e5bd3505: Pull complete
3aeded8eec5f: Pull complete
a8100d968019: Pull complete
db921fed581e: Download complete
e7513cd11830: Download complete
Digest: sha256:6c5666b861f3505b116bb9aa9b25175e71210414bd010d92035ff64018f9457e
Status: Downloaded newer image for registry:latest
3cee64c5cfb1408d6dab13787818006990c8b5446f08202c3e572bfd18834ede

测试前需要配置解析才可以push

bash 复制代码
[root@docker-node1 docker]# vim /etc/hosts
192.168.131.10     reg.timinglee.org
[root@docker-node2 docker]# vim /etc/hosts
192.168.131.10     reg.timinglee.org

测试:

bash 复制代码
#docker客户端没有key和证书
[root@docker-node1 ~]# docker push reg.timinglee.org/webserver:v1 
failed to do request: Head "https://reg.timinglee.org/v2/webserver/blobs/sha256:853e455d00c0eb6a30e5efdd9e4894a4842be492f1c2cbc7c7a1a263439be114": tls: failed to verify certificate: x509: certificate signed by unknown authority

为客户端建立证书

bash 复制代码
[root@docker-node1 ~]# mkdir /etc/docker/certs.d/reg.timinglee.org/ -p
[root@docker-node1 ~]# cp /etc/docker/certs/timinglee.org.crt /etc/docker/certs.d/reg.timinglee.org/ca.crt
[root@docker-node1 ~]# docker push reg.timinglee.org/webserver:v1    ##成功使用仓库
The push refers to repository [reg.timinglee.org/webserver]
8451c71f8c1e: Pushed
6835249f577a: Pushed
9ed498e122b2: Pushed
af5aa97ebe6c: Pushed
c048279a7d9f: Pushed
2a92d6ac9e4f: Pushed
577c8ee06f39: Pushed
4d049f83d9cf: Pushed
853e455d00c0: Pushed
4b4696834e1f: Pushed
ac805962e479: Pushed
bbb6cacb8c82: Pushed
5342a2647e87: Pushed
1a73b54f556b: Pushed
2388d21e8e2b: Pushed
24aacbf97031: Pushed
v1: digest: sha256:ead32f4875bbe8a5e168944b5261745e167b50ca5097aea42e66e1bf960fa6bb size: 856

[root@docker-node1 ~]# curl -k https://192.168.131.10/v2/_catalog
{"repositories":["webserver"]}

3. 为仓库建立登录认证

安装建立认证文件的工具包

root@docker-node1 \~\]# dnf install httpd-tools -y 建立认证文件 ```bash [root@docker-node1 ~]# mkdir /etc/docker/auth [root@docker-node1 ~]# htpasswd -Bc /etc/docker/auth/htpasswd lee #-B 强制使用最安全加密方式,默认用md5加密 New password: Re-type new password: Adding password for user lee ``` 添加认证到registry容器中 ```bash [root@docker-node1 ~]# docker rm -f registry registry [root@docker-node1 ~]# docker run -d -p 443:443 --restart=always --name registry \ -v /etc/docker/certs:/certs \ -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \ -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/timinglee.org.crt \ -e REGISTRY_HTTP_TLS_KEY=/certs/timinglee.org.key \ -v /etc/docker/auth:/auth \ -e "REGISTRY_AUTH=htpasswd" \ -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \ -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \ > registry 8a1f3a4444a921a28431c87aad5c40f3b5966383c96f1d49b3721557475d0b7e [root@docker-node1 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8cf8bb5115c0 registry "/entrypoint.sh /etc..." 6 seconds ago Up 5 seconds 0.0.0.0:443->443/tcp, [::]:443->443/tcp, 5000/tcp registry ``` 测试: ```bash [root@docker-node1 ~]# docker login reg.timinglee.org Username: lee Password: WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'. Configure a credential helper to remove this warning. See https://docs.docker.com/go/credential-store/ Login Succeeded [root@docker-node1 ~]# docker push reg.timinglee.org/webserver:v1 The push refers to repository [reg.timinglee.org/webserver] 4b4696834e1f: Pushed bbb6cacb8c82: Pushed 24aacbf97031: Pushed ac805962e479: Pushed 5342a2647e87: Pushed 577c8ee06f39: Pushed 4d049f83d9cf: Pushed af5aa97ebe6c: Pushed 2a92d6ac9e4f: Pushed 1a73b54f556b: Pushed c048279a7d9f: Pushed 8451c71f8c1e: Pushed 6835249f577a: Pushed 853e455d00c0: Pushed 9ed498e122b2: Pushed 2388d21e8e2b: Pushed v1: digest: sha256:ead32f4875bbe8a5e168944b5261745e167b50ca5097aea42e66e1bf960fa6bb size: 856 ``` 注:当仓库开启认证后必须登陆仓库才能进行镜像上传 ```bash #未登陆情况下上传镜像 [root@docker ~]# docker push reg.timinglee.org/busybox Using default tag: latest The push refers to repository [reg.timinglee.org/busybox] d51af96cf93e: Preparing no basic auth credentials #未登陆情况下也不能下载 [root@docker-node2 ~]# docker pull reg.timinglee.org/busybox Using default tag: latest Error response from daemon: Head "https://reg.timinglee.org/v2/busybox/manifests/latest": no basic auth credentials ```

5 构建企业级私有仓库

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

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

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

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

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

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

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

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

部署harbor

bash 复制代码
[root@docker-node1 ~]# tar zxf harbor-offline-installer-v2.5.4.tgz -C /opt
[root@docker-node1 ~]# mkdir /opt/habor/certs

创建证书
[root@docker -node1 ~]#  openssl req -newkey  rsa:4096 \
-nodes -sha256 -keyout certs/timinglee.org.key \
-addext "subjectAltName = DNS:reg.timinglee.org" \		
-x509 -days 365 -out certs/timinglee.org.crt

[root@docker-node1 ~]# mkdir /data	#因为harbor.yml中data_volume: /data
[root@docker-node1 ~]# cp -rp /etc/docker/certs /data/
[root@docker-node1 ~]# ll /data/certs/timinglee.org.crt
-rw-r--r-- 1 root root 2199  3月 21 00:07 /data/certs/timinglee.org.crt
[root@docker-node1 ~]# ll /data/certs/timinglee.org.key
-rw------- 1 root root 3268  3月 21 00:04 /data/certs/timinglee.org.key

[root@docker-node1 ~]# cd /opt/harbor/
[root@docker harbor]# cp harbor.yml.tmpl harbor.yml
[root@docker-node1 harbor]# vim harbor.yml
hostname: reg.timinglee.org
  certificate: /etc/docker/certs/timinglee.org.crt
  private_key: /etc/docker/certs/timinglee.org.key
harbor_admin_password: lee

加载镜像
[root@docker-node1 harbor]# ./install.sh

管理harbor的容器
[root@docker harbor]# docker compose stop
[root@docker harbor]# docker compose  up -d

可直接通过本地ip访问登录harbor

镜像为空

bash 复制代码
上传镜像
[root@docker-node1 ~]# docker login reg.timinglee.org
Authenticating with existing credentials... [Username: lee]

i Info → To login with a different account, run 'docker logout' followed by 'docker login'


Stored credentials invalid or expired
Username (lee): admin
Password:

WARNING! Your credentials are stored unencrypted in '/root/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded
[root@docker-node1 ~]# docker tag busybox:latest reg.timinglee.org/timinglee/busybox:latest
[root@docker-node1 ~]# docker push reg.timinglee.org/timinglee/busybox:latest
The push refers to repository [reg.timinglee.org/timinglee/busybox]
cb03befeffa1: 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
v1: digest: sha256:402cace45d3c134f79c324b2c32a49651e9b2c0c5860137319ea909e0b114918 size: 527

查看上传的镜像

Docker 网络

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

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

bash 复制代码
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME            DRIVER    SCOPE
efb274f9ee49   bridge          bridge    local
e17576648810   host            host      local
bb17b3835ebe   none            null      local

1 docker原生bridge网络

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

bash 复制代码
[root@docker-node1 ~]# ip link show type bridge
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 56:94:31:0b:a8:91 brd ff:ff:ff:ff:ff:ff
  • bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。

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

bash 复制代码
[root@docker mnt]# docker run -d --name web -p 80:80 nginx:1.23
defeba839af1b95bac2a200fd1e06a45e55416be19c7e9ce7e0c8daafa7dd470
[root@docker mnt]# 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:5fff:fee2:346c  prefixlen 64  scopeid 0x20<link>
        ether 02:42:5f:e2:34:6c  txqueuelen 0  (Ethernet)
        RX packets 21264  bytes 1497364 (1.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 27358  bytes 215202237 (205.2 MiB)
        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::30b2:327e:b13a:31cf  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:ec:fc:d3  txqueuelen 1000  (Ethernet)
        RX packets 1867778  bytes 2163432019 (2.0 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 822980  bytes 848551940 (809.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 11819  bytes 1279944 (1.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 11819  bytes 1279944 (1.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth022a7c9: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::a013:5fff:fefc:c9e4  prefixlen 64  scopeid 0x20<link>
        ether a2:13:5f:fc:c9:e4  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 15  bytes 2007 (1.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth022a7c9 为容器使用的网卡
[root@docker mnt]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.02425fe2346c       no              veth022a7c9

2 docker 原生网络host

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

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

bash 复制代码
[root@docker ~]# docker run -it --name test  --network host busybox
/ # ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:5F:E2:34:6C
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:5fff:fee2:346c/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:21264 errors:0 dropped:0 overruns:0 frame:0
          TX packets:27359 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1497364 (1.4 MiB)  TX bytes:215202367 (205.2 MiB)

eth0      Link encap:Ethernet  HWaddr 00:0C:29:EC:FC:D3
          inet addr:172.25.254.100  Bcast:172.25.254.255  Mask:255.255.255.0
          inet6 addr: fe80::30b2:327e:b13a:31cf/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1902507 errors:0 dropped:0 overruns:0 frame:0
          TX packets:831640 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2202443300 (2.0 GiB)  TX bytes:849412124 (810.0 MiB)

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:11819 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11819 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1279944 (1.2 MiB)  TX bytes:1279944 (1.2 MiB)

/ #

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

3 docker 原生网络none

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

--network=none指定。

bash 复制代码
[root@docker ~]# 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.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)

4 docker 的自定义网络

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

bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,overlay和macvlan是用于创建跨主机网络

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

1.自定义桥接网络

在建立自定以网络时,默认使用桥接模式

bash 复制代码
[root@docker ~]# docker network create my_net1
f2aae5ce8ce43e8d1ca80c2324d38483c2512d9fb17b6ba60d05561d6093f4c4
[root@docker ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
2a93d6859680   bridge    bridge    local
4d81ddd9ed10   host      host      local
f2aae5ce8ce4   my_net1   bridge    local
8c8c95f16b68   none      null      local

桥接默认是单调递增

bash 复制代码
[root@docker ~]# ifconfig
br-f2aae5ce8ce4: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:70:57:f2:82  txqueuelen 0  (Ethernet)
        RX packets 21264  bytes 1497364 (1.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 27359  bytes 215202367 (205.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:5fff:fee2:346c  prefixlen 64  scopeid 0x20<link>
        ether 02:42:5f:e2:34:6c  txqueuelen 0  (Ethernet)
        RX packets 21264  bytes 1497364 (1.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 27359  bytes 215202367 (205.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

桥接也支持自定义子网和网关

bash 复制代码
[root@docker ~]# docker network create my_net2 --subnet 192.168.0.0/24 --gateway 192.168.0.100
7e77cd2e44c64ff3121a1f1e0395849453f8d524d24b915672da265615e0e4f9
[root@docker ~]# docker network  inspect my_net2
[
    {
        "Name": "my_net2",
        "Id": "7e77cd2e44c64ff3121a1f1e0395849453f8d524d24b915672da265615e0e4f9",
        "Created": "2024-08-17T17:05:19.167808342+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": {}
    }
]

2.为什么要自定义桥接

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

答:docker引擎在分配ip时时根据容器启动顺序分配到,谁先启动谁用,是动态变更的

多容器互访用ip很显然不是很靠谱,那么多容器访问一般使用容器的名字访问更加稳定

docker原生网络是不支持dns解析的,自定义网络中内嵌了dns

bash 复制代码
[root@docker ~]# docker run  -d --name web1 nginx
d5da7eaa913fa6cdd2aa9a50561042084eca078c114424cb118c57eeac473424
[root@docker ~]# docker run  -d --name web2 nginx
0457a156b02256915d4b42f6cc52ea71b18cf9074ce550c886f206fef60dfae5
[root@docker ~]# docker inspect  web1
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:03",
                    "DriverOpts": null,
                    "NetworkID": "2a93d6859680b45eae97e5f6232c3b8e070b1ec3d01852b147d2e1385034bce5",
                    "EndpointID": "4d54b12aeb2d857a6e025ee220741cbb3ef1022848d58057b2aab544bd3a4685",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",		#注意ip信息
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DNSNames": null

[root@docker ~]# docker inspect  web1
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "02:42:ac:11:00:03",
                    "DriverOpts": null,
                    "NetworkID": "2a93d6859680b45eae97e5f6232c3b8e070b1ec3d01852b147d2e1385034bce5",
                    "EndpointID": "4d54b12aeb2d857a6e025ee220741cbb3ef1022848d58057b2aab544bd3a4685",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",		#注意ip信息
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DNSNames": null
                    
#关闭容器后重启容器,启动顺序调换
[root@docker ~]# docker stop web1 web2
web1
web2
[root@docker ~]# docker start web2
web2
[root@docker ~]# docker start web1
web1

#我们会发现容器ip颠倒

测试

bash 复制代码
[root@docker ~]# docker run -d --network my_net1 --name web nginx
d9ed01850f7aae35eb1ca3e2c73ff2f83d13c255d4f68416a39949ebb8ec699f
[root@docker ~]# docker run  -it --network my_net1  --name  test busybox
/ # ping web
PING web (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.197 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.096 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.087 ms

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

bash 复制代码
#在rhel7中使用的是iptables进行网络隔离,在rhel9中使用nftpables
[root@docker ~]# nft list ruleset可以看到网络隔离策略

3.如何让不同的自定义网络互通

bash 复制代码
[root@docker ~]# docker run -d  --name web1 --network my_net1 nginx
[root@docker ~]# 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.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:36 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:5244 (5.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: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 172.18.0.2
PING 172.18.0.2 (172.18.0.2): 56 data bytes

[root@docker ~]# docker network connect my_net1 test

#在上面test容器中加入网络eth1
/ # 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.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:45 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:5879 (5.7 KiB)  TX bytes:602 (602.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: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:2016 (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:4 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:212 (212.0 B)  TX bytes:212 (212.0 B)

4.joined容器网络

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

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

bash 复制代码
[root@docker ~]# docker run  -it --rm  --network container:web1 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:28 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3046 (2.9 KiB)  TX bytes:280 (280.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 ~]# docker run  -it --rm  --network container:web1 centos:7
[root@efae66874371 /]# 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>

5. joined网络企业实战

导入镜像

复制代码
[root@docker-node1 ~]# docker load  -i phpmyadmin-latest.tar.gz
[root@docker-node1 ~]# docker load  -i  mysql-8.0.tar

运行php-myadmin容器

bash 复制代码
[root@docker-node1 ~]# docker run -d --name phpmyadmin \
> -e PMA_ARBITRARY=1 \        #在web页面中可以手动输入数据库地址和端口
> -p 80:80 phpmyadmin:latest
cd77f19777c887fb6161fbe7282ca14d8765b0befd9a135663d97694a6c59d76

运行mysql数据库

bash 复制代码
[root@docker-node1 ~]# docker run -d --name mysql \
> -e MYSQL_ROOT_PASSWORD='lee' \            #设定数据库密码
> --network container:phpmyadmin mysql:8.0  #把数据库容器添加到phpmyadmin容器中
eaf63bbf26d6fa00bf3083b9fda96c535d9fc3c559a7382c81b5a1478846b556

访问phpmyadmin

http://192.168.131.10

注意:

开启的phpmyadmin容器中是没有数据库的

这里填写的localhost:3306是因为mysql容器和phpmyadmin容器公用一个网络站

5 容器内外网的访问

1.容器访问外网

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

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

    bash 复制代码
    [root@docker ~]# iptables -t nat -nL
    Chain PREROUTING (policy ACCEPT)
    target     prot opt source               destination
    
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination
    
    Chain OUTPUT (policy ACCEPT)
    target     prot opt source               destination
    
    Chain POSTROUTING (policy ACCEPT)
    target     prot opt source               destination
    MASQUERADE  6    --  172.17.0.2           172.17.0.2         tcp dpt:80  
    #内网访问外网策略
    
    Chain DOCKER (0 references)
    target     prot opt source               destination
    DNAT       6    --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:80

2.外网访问docker容器

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

bash 复制代码
#通过docker-proxy对数据包进行内转
[root@docker ~]# docker run  -d --name webserver -p 80:80 nginx
[root@docker ~]# ps ax
 133986 ?        Sl     0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.2 -container-port 80
 133995 ?        Sl     0:00 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 80 -container-ip 172.17.0.2 -container-port 80
 134031 ?        Sl     0:00 /usr/bin/containerd-shim-runc-v2 -namespace moby -id cae79497a01c0b8c488c7597b43de4a43f361f21a398ff423b4504c0905db143 -address /run/containerd/containerd.sock
 134059 ?        Ss     0:00 nginx: master process nginx -g daemon off;
 134099 ?        S      0:00 nginx: worker process
 134100 ?        S      0:00 nginx: worker process

#通过dnat策略来完成浏览内转
[root@docker ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  6    --  172.17.0.2           172.17.0.2           tcp dpt:80

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

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

6 docker跨主机网络

设定硬件

两台主机添加网卡并设定为host-only #跨主机必须直连,不能设定NAT模式

开启新加网卡的混杂模式

bash 复制代码
[root@docker-node1 ~]# ip link set eth1 promisc on
[root@docker-node1 ~]# ip a show eth1
16: eth1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:21:54:2f brd ff:ff:ff:ff:ff:ff
    altname enp19s0
    altname ens224

[root@docker-node2 ~]# ip link set eth1 promisc on
[root@docker-node2 ~]# ip a show eth1
4: eth1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:59:09:d6 brd ff:ff:ff:ff:ff:ff
    altname enp19s0
    altname ens224

配置docker自建网络

bash 复制代码
node1中
[root@docker-node1 ~]# docker network create -d macvlan --subnet 1.1.1.0/24 --gateway 1.1.1.1 -o parent=eth1 lee
[root@docker-node1 ~]# docker network ls
NETWORK ID     NAME            DRIVER    SCOPE
5fdfe12f1cdb   bridge          bridge    local
e17576648810   host            host      local
ee8b5b77a4a0   lee             macvlan   local
bb17b3835ebe   none            null      local

node2中
[root@docker-node2 ~]# docker network create  \
-d macvlan \
--subnet 1.1.1.0/24 \
--gateway 1.1.1.1 \
-o parent=eth1 lee
dd43a311079fa7547251393990d6fbab1542971ee115a85dd5a16f6b76d04bab
[root@docker-node2 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
333ffef20591   bridge    bridge    local
445ab16ba8d8   host      host      local
dd43a311079f   lee       macvlan   local
1f317daed145   none      null      local

测试跨主机docker是否可以通信

bash 复制代码
[root@docker-node1 ~]# docker run -it --name busybox --rm --network lee --ip 1.1.1.100 --rm busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
17: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 52:41:c3:ab:bf:a0 brd ff:ff:ff:ff:ff:ff
    inet 1.1.1.100/24 brd 1.1.1.255 scope global eth0
       valid_lft forever preferred_lft forever


[root@docker-node2 ~]# docker run -it --name busybox --rm --network lee --ip 1.1.1.200 --rm busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
6: eth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether b2:62:8b:ab:e0:2a brd ff:ff:ff:ff:ff:ff
    inet 1.1.1.200/24 brd 1.1.1.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping 1.1.1.100        #在node2开启的容器中ping node1主机中开启容器的地址
PING 1.1.1.100 (1.1.1.100): 56 data bytes
64 bytes from 1.1.1.100: seq=0 ttl=64 time=1.397 ms
64 bytes from 1.1.1.100: seq=1 ttl=64 time=0.829 ms
64 bytes from 1.1.1.100: seq=2 ttl=64 time=0.844 ms

Docker 数据卷管理及优化

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

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

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

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

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

1 为什么要用数据卷

docker分层文件系统

  • 性能差

  • 生命周期与容器相同

docker数据卷

  • mount到主机中,绕开分层文件系统

  • 和主机磁盘性能相同,容器删除后依然保留

  • 仅限本地磁盘,不能随容器迁移

docker提供了两种卷:

  • bind mount

  • docker managed volume

2 bind mount 数据卷

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

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

  • 使用 -v 选项指定路径,格式 <host path>:<container path>

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

示例:

bash 复制代码
[root@docker ~]# 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
lee:x:1000:1000:lee:/home/lee:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
nginx:x:1001:1001::/home/nginx:/sbin/nologin
/ # touch  /data1/leefile1
/ # touch /data2/leefile1
touch: /data2/leefile1: Read-only file system

3 docker managed 数据卷

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

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

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

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

示例:

bash 复制代码
[root@docker volumes]# docker run  -d --name mysql -e  MYSQL_ROOT_PASSWORD='lee' mysql:5.7
[root@docker volumes]# ls -l /var/lib/docker/volumes
总用量 0
drwx-----x 3 root root 19  8月 20 16:34 ad74662b8d6bb6fdcc6e82925ae9942b94bac5f9da4bd52b0a14ac451ae9ef75

[root@docker volumes]# touch ad74662b8d6bb6fdcc6e82925ae9942b94bac5f9da4bd52b0a14ac451ae9ef75/_data/leefile

[root@docker volumes]# docker exec  -it mysql  bash
bash-4.2# cd /var/lib/mysql
bash-4.2# ls
auto.cnf    client-cert.pem  ib_logfile0  ibtmp1   mysql.sock          public_key.pem   sys
ca-key.pem  client-key.pem   ib_logfile1  leefile  performance_schema  server-cert.pem
ca.pem      ib_buffer_pool   ibdata1      mysql    private_key.pem     server-key.pem
bash-4.2# pwd

清理未使用的 Docker 数据卷

root@docker \~\]# docker volume prune 注意: 1. 在执行 `docker volume prune` 命令之前,请确保你确实不再需要这些数据卷中的数据,因为该操作是不可逆的,一旦删除数据将无法恢复。 2. 如果有重要的数据存储在数据卷中,建议先进行备份,或者确保数据已经被妥善保存到其他地方。 **建立数据卷** \[root@docker \~\]# docker volume create leevol1 \[root@docker \~\]# ls -l /var/lib/docker/volumes/leevol1/_data/ **查看卷** \[root@docker \~\]# docker volume ls DRIVER VOLUME NAME local leevol1 **使用建立的数据卷** \[root@docker _data\]# docker run -d --name web1 -p 80:80 -v leevol1:/usr/share/nginx/html nginx e76706848323d6c329c41c4140903f8cc441458daf1459d9016bd1ed0ab3360a root@docker _data\]# cd /var/lib/docker/volumes/leevol1/_data \[root@docker _data\]# ls \[root@docker _data\]# echo leevol1 \> index.html \[root@docker _data\]# curl 172.25.254.100 leevol1

4数据卷容器(Data Volume Container)

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

建立数据卷容器

root@docker \~\]# docker run -d --name datavol \\ -v /tmp/data1:/data1:rw \\ -v /tmp/data2:/data2:ro \\ -v /etc/resolv.conf:/etc/hosts busybox **使用数据卷容器** \[root@docker \~\]# docker run -it --name test --rm --volumes-from datavol busybox / # ls bin data1 data2 dev etc home lib lib64 proc root sys tmp usr 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 timinglee.org # Based on host file: '/etc/resolv.conf' (legacy) # Overrides: \[

/ # touch data1/leefile1

/ # touch /data2/leefile1

touch: /data2/leefile1: Read-only file system

/ #

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

**相同点:**两者都是 host 文件系统中的某个路径

不同点:

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

6 备份与迁移数据卷

备份数据卷

bash 复制代码
#建立容器并指定使用卷到要备份的容器
[root@docker ~]# docker run --volumes-from datavol  \
-v `pwd`:/backup busybox \					#把当前目录挂在到容器中用于和容器交互保存要备份的容器
tar zcf /backup/data1.tar.gz  /data1		#备份数据到本地

数据恢复

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

Docker 的安全优化

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

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

  • Linux内核的命名空间机制提供的容器隔离安全
  • Linux控制组机制对容器资源的控制能力安全
  • Linux内核的功能机制所带来的操作权限安全
  • Docker程序(特别是服务端)本身的抗攻击性
  • 其他安全增强机制对容器安全性的影响
bash 复制代码
#在rhel9中默认使用cgroup-v2 但是cgroup-v2中不利于观察docker的资源限制情况,所以推荐使用cgroup-v1
[root@docker ~]#  grubby --update-kernel=/boot/vmlinuz-$(uname -r) \
--args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"

1.命名空间隔离的安全

  • 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的命名空间。命名空间提供了最基础也最直接的隔离。
  • 与虚拟机方式相比,通过Linuxnamespace来实现的隔离不是那么彻底。
  • 容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就还是同一个宿主机的操作系统内核。
  • 在Linux内核中,有很多资源和对象是不能被Namespace 化的,比如:磁盘
bash 复制代码
[root@docker ~]# docker run -d --name web nginx
3c6b649a200fc56afafe9f47494903fe56e71cabcd534d6c9e6f8b5854f29cac

[root@docker ~]# docker inspect web  | grep Pid
            "Pid": 4328,
            "PidMode": "",
            "PidsLimit": null,



[root@docker ~]# cd /proc/4328/ns/			#进程的namespace
[root@docker ns]# ls
cgroup  ipc  mnt  net  pid  pid_for_children  time  time_for_children  user  uts


[root@docker ns]# ls -d /sys/fs/cgroup/memory/docker/3c6b649a200fs省略部分854f29cac/ 		#资源隔离信息
/sys/fs/cgroup/system.slice/docker-ecb8abbbfc85bf3d62fc82afb3950ab6b6a2e80092738274a233bbb8db0c5ce2.scope
/sys/fs/cgroup/system.slice/docker.service
/sys/fs/cgroup/system.slice/docker.socket

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

  • 当docker run启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。
  • Linux Cgroups提供了很多有用的特性,确保各容器可以公平地分享主机的内存、CPU、磁盘IO等资源。
  • 确保当发生在容器内的资源压力不会影响到本地主机系统和其他容器,它在防止拒绝服务攻击(DDoS攻击)方面必不可少
bash 复制代码
[root@docker ~]# docker run  -it --name test busybox			#内存资源默认没有被隔离
/ # free -m
              total        used        free      shared  buff/cache   available
Mem:           3627         648         516          16        2463        2678
Swap:          2063           1        2062
/ # exit
[root@docker ~]# free  -m
               total        used        free      shared  buff/cache   available
Mem:            3627         907         557          15        2463        2719
Swap:           2062           1        2061

3.内核功能机制

  • 使用Docker容器的核心是Docker服务端,确保只有可信的用户才能访问到Docker服务。
  • 将容器的root用户映射到本地主机上的非root用户,减轻容器和主机之间因权限提升而引起的安全问题。
  • 允许Docker 服务端在非root权限下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。这些子进程只允许在特定范围内进行操作。

4.Docker服务器防护

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

1 Docker的资源限制

Linux Cgroups 的全称是 Linux Control Group。

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

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

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

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

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

bash 复制代码
[root@docker ~]# 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/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/misc type cgroup (rw,nosuid,nodev,noexec,relatime,misc)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
  • 在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。

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

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

1.限制cpu使用

限制cpu的使用量

bash 复制代码
[root@docker ~]# docker run  -it --rm --name test \
--cpu-period 100000 \					#设置 CPU 周期的长度,单位为微秒(通常为 100000,即 100 毫秒)
--cpu-quota 20000 ubuntu				#设置容器在一个周期内可以使用的 CPU 时间,单位也是微秒。
root@5797d76b20f5:/# dd if=/dev/zero of=/dev/null &
[1] 8
root@5797d76b20f5:/# top
top - 11:53:22 up 1 day,  1:58,  0 user,  load average: 0.00, 0.00, 0.00
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  4.4 us,  6.0 sy,  0.0 ni, 89.5 id,  0.0 wa,  0.2 hi,  0.0 si,  0.0 st
MiB Mem :   3627.1 total,    558.1 free,    899.4 used,   2471.0 buff/cache
MiB Swap:   2063.0 total,   2062.0 free,      1.0 used.   2727.7 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
      8 root      20   0    2736   1536   1536 R  20.0   0.0   0:00.92 dd			#使用cpu的百分比
      1 root      20   0    4588   3968   3456 S   0.0   0.1   0:00.03 bash
      9 root      20   0    8856   5248   3200 R   0.0   0.1   0:00.00 top
 
#在cgroup中查看docker的资源限制
[root@docker ~]# cat /sys/fs/cgroup/cpu/docker/"docker id(所要查看容器的id)"/cpu.cfs_period_us       #cpu总量划分

[root@docker ~]# cat /sys/fs/cgroup/cpu/docker/"docker id(所要查看容器的id)"/cpu.cfs_quota_us       #cpu限制

限制cpu的优先级

bash 复制代码
#关闭cpu的核心,当cpu都不空闲下才会出现争抢的情况,为了实验效果我们可以关闭一个cpu核心
root@docker ~]# echo 0 > /sys/devices/system/cpu/cpu1/online
[root@docker ~]# cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 58
model name      : Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
stepping        : 9
microcode       : 0x21
cpu MHz         : 3901.000
cache size      : 8192 KB
physical id     : 0
siblings        : 1
core id         : 0
cpu cores       : 1		##cpu核心数为1
apicid          : 0
initial apicid  : 0
fpu             : yes
fpu_exception   : yes
cpuid level     : 13
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust smep arat md_clear flush_l1d arch_capabilities
bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit srbds mmio_unknown
bogomips        : 7802.00
clflush size    : 64
cache_alignment : 64
address sizes   : 45 bits physical, 48 bits virtual
power management:

#开启容器时如果指定了cpu使用优先级,那么设定文件为
[root@docker ~]# cat /sys/fs/cgroup/cpu/docker/"docker id(所要查看容器的id)"/cpu.shares


#开启容器并限制资源
[root@docker ~]# docker run -it  --rm --cpu-shares 100 ubuntu		#设定cpu优先级,最大为1024,值越大优先级越高
root@dc066aa1a1f0:/# dd if=/dev/zero of=/dev/null &
[1] 8
root@dc066aa1a1f0:/# top
top - 12:16:56 up 1 day,  2:22,  0 user,  load average: 1.20, 0.37, 0.20
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s): 37.3 us, 61.4 sy,  0.0 ni,  0.0 id,  0.0 wa,  1.0 hi,  0.3 si,  0.0 st
MiB Mem :   3627.1 total,    502.5 free,    954.5 used,   2471.7 buff/cache
MiB Swap:   2063.0 total,   2062.3 free,      0.7 used.   2672.6 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
      8 root      20   0    2736   1536   1536 R   3.6   0.0   0:16.74 dd			#cpu有限制被限制
      1 root      20   0    4588   3968   3456 S   0.0   0.1   0:00.03 bash
      9 root      20   0    8856   5248   3200 R   0.0   0.1   0:00.00 top


#开启另外一个容器不限制cpu的优先级
root@17f8c9d66fde:/# dd if=/dev/zero of=/dev/null &
[1] 8
root@17f8c9d66fde:/# top
top - 12:17:55 up 1 day,  2:23,  0 user,  load average: 1.84, 0.70, 0.32
Tasks:   3 total,   2 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s): 36.2 us, 62.1 sy,  0.0 ni,  0.0 id,  0.0 wa,  1.3 hi,  0.3 si,  0.0 st
MiB Mem :   3627.1 total,    502.3 free,    954.6 used,   2471.7 buff/cache
MiB Swap:   2063.0 total,   2062.3 free,      0.7 used.   2672.5 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
      8 root      20   0    2736   1408   1408 R  94.0   0.0   1:09.34 dd			#cpu为被限制
      1 root      20   0    4588   3968   3456 S   0.0   0.1   0:00.02 bash
      9 root      20   0    8848   5248   3200 R   0.0   0.1   0:00.01 top

2.限制内存使用

bash 复制代码
#开启容器并限制容器使用内存大小
[root@docker system.slice]# docker run -d --name test --memory 200M --memory-swap 200M nginx

#查看容器内存使用限制
[root@docker ~]# cd /sys/fs/cgroup/memory/docker/d09100472de41824bf0省略部分id96b977369dad843740a1e8e599f430/

[root@docker d091004723d4de41824f6b38a7be9b77369dad843740a1e8e599f430]# cat memory.limit_in_bytes
209715200
[root@docker d091004723d4de41824f6b38a7be9977369dad843740a1e8e599f430]# cat memory.memsw.limit_in_bytes
209715200


#测试容器内存限制,在容器中我们测试内存限制效果不是很明显,可以利用工具模拟容器在内存中写入数据
#在系统中/dev/shm这个目录被挂在到内存中

[root@docker cgroup]# docker run  -d --name test --rm --memory 200M --memory-swap 200M  nginx                     f5017485d69b50cf2e294bf6c65fcd5e679002e25bd9b0eaf9149eee2e379eec
[root@docker cgroup]# cgexec -g memory:docker/f5017485d69b50cf2e294bf6c65fcd5e679002e25bd9b0eaf9149eee2e379eec  dd if=/dev/zero of=/dev/shm/bigfile  bs=1M count=150
记录了150+0 的读入
记录了150+0 的写出
157286400字节(157 MB,150 MiB)已复制,0.0543126 s,2.9 GB/s
[root@docker cgroup]# cgexec -g memory:docker/f5017485d69b50cf2e294bf6c65fcd5e679002e25bd9b0eaf9149eee2e379eec  dd if=/dev/zero of=/dev/shm/bigfile  bs=1M count=180
记录了180+0 的读入
记录了180+0 的写出
188743680字节(189 MB,180 MiB)已复制,0.0650658 s,2.9 GB/s
[root@docker cgroup]# cgexec -g memory:docker/f5017485d69b50cf2e294bf6c65fcd5e679002e25bd9b0eaf9149eee2e379eec  dd if=/dev/zero of=/dev/shm/bigfile  bs=1M count=120
记录了120+0 的读入
记录了120+0 的写出
125829120字节(126 MB,120 MiB)已复制,0.044017 s,2.9 GB/s
[root@docker cgroup]# cgexec -g memory:docker/f5017485d69b50cf2e294bf6c65fcd5e679002e25bd9b0eaf9149eee2e379eec  dd if=/dev/zero of=/dev/shm/bigfile  bs=1M count=200
已杀死

#也可以自建控制器
[root@docker ~]# mkdir -p /sys/fs/cgroup/memory/x1/
[root@docker ~]# ls /sys/fs/cgroup/memory/x1/
cgroup.clone_children           memory.kmem.tcp.max_usage_in_bytes  memory.oom_control
cgroup.event_control            memory.kmem.tcp.usage_in_bytes      memory.pressure_level
cgroup.procs                    memory.kmem.usage_in_bytes          memory.soft_limit_in_bytes
memory.failcnt                  memory.limit_in_bytes               memory.stat
memory.force_empty              memory.max_usage_in_bytes           memory.swappiness
memory.kmem.failcnt             memory.memsw.failcnt                memory.usage_in_bytes
memory.kmem.limit_in_bytes      memory.memsw.limit_in_bytes         memory.use_hierarchy
memory.kmem.max_usage_in_bytes  memory.memsw.max_usage_in_bytes     notify_on_release
memory.kmem.slabinfo            memory.memsw.usage_in_bytes         tasks
memory.kmem.tcp.failcnt         memory.move_charge_at_immigrate
memory.kmem.tcp.limit_in_bytes  memory.numa_stat

[root@docker ~]# echo 209715200 > /sys/fs/cgroup/memory/x1/memory.limit_in_bytes    #内存可用大小限制
[root@docker ~]# cat /sys/fs/cgroup/memory/x1/tasks			#此控制器被那个进程调用
[root@docker ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=100
记录了100+0 的读入
记录了100+0 的写出
104857600字节(105 MB,100 MiB)已复制,0.0388935 s,2.7 GB/s
[root@docker ~]# free  -m
               total        used        free      shared  buff/cache   available
Mem:            3627        1038        1813         109        1131        2589
Swap:           2062           0        2062
[root@docker ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=300
记录了300+0 的读入
记录了300+0 的写出
314572800字节(315 MB,300 MiB)已复制,0.241256 s,1.3 GB/s
[root@docker ~]# free  -m
               total        used        free      shared  buff/cache   available
Mem:            3627        1125        1725         181        1203        2501
Swap:           2062         129        1933			#内存溢出部分被写入swap交换分区

[root@docker ~]# rm -fr /dev/shm/bigfile
[root@docker ~]# echo 209715200 > /sys/fs/cgroup/memory/x1/memory.memsw.limit_in_bytes		#内存+swap控制
[root@docker ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=200
已杀死
[root@docker ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=199
已杀死
[root@docker ~]# rm -fr /dev/shm/bigfile
[root@docker ~]#
[root@docker ~]# rm -fr /dev/shm/bigfile
[root@docker ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=180
记录了180+0 的读入
记录了180+0 的写出
188743680字节(189 MB,180 MiB)已复制,0.0660052 s,2.9 GB/s
[root@docker ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=190
记录了190+0 的读入
记录了190+0 的写出
199229440字节(199 MB,190 MiB)已复制,0.0682285 s,2.9 GB/s
[root@docker ~]# cgexec -g memory:x1 dd if=/dev/zero of=/dev/shm/bigfile bs=1M count=200
已杀死

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

3.限制docker的磁盘io

bash 复制代码
[root@docker ~]# docker run -it --rm  \
--device-write-bps \			#指定容器使用磁盘io的速率
/dev/nvme0n1:30M \				#/dev/nvme0n1是指定系统的磁盘,30M即每秒30M数据
ubuntu
root@a4e9567a666d:/# dd if=/dev/zero of=bigfile		#开启容器后会发现速度和设定不匹配,是因为系统的缓存机制
^C592896+0 records in
592895+0 records out
303562240 bytes (304 MB, 289 MiB) copied, 2.91061 s, 104 MB/s

root@a4e9567a666d:/# ^C
root@a4e9567a666d:/# 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.0515779 s, 2.0 GB/s
root@a4e9567a666d:/# dd if=/dev/zero of=bigfile bs=1M count=100 oflag=direct		#设定dd命令直接写入磁盘
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 3.33545 s, 31.4 MB/s

2 Docker的安全加固

1.Docker默认隔离性

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

bash 复制代码
[root@docker ~]# free -m			#系统内存使用情况
               total        used        free      shared  buff/cache   available
Mem:            3627        1128        1714         207        1238        2498
Swap:           2062           0        2062
[root@docker ~]# docker run --rm  --memory 200M -it ubuntu
root@e06bdc13b764:/# free -m		#容器中内存使用情况
               total        used        free      shared  buff/cache   available
Mem:            3627        1211        1630         207        1239        2415
Swap:           2062  

#虽然我们限制了容器的内容使用情况,但是查看到的信息依然是系统中内存的使用信息,并没有隔离开

2.解决Docker的默认隔离性

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

主要功能:

  • 资源可见性:LXCFS 可以使容器内的进程看到准确的 CPU、内存和磁盘 I/O 等资源使用信息。在没有 LXCFS 时,容器内看到的资源信息可能不准确,这会影响到在容器内运行的应用程序对资源的评估和管理。
  • 性能监控:方便对容器内的资源使用情况进行监控和性能分析。通过提供准确的资源信息,管理员和开发人员可以更好地了解容器化应用的性能瓶颈,并进行相应的优化。
bash 复制代码
安装lxcfs
#在rhel9中lxcfs是被包含在epel源中,我们可以直接下载安装包进行安装
[root@docker ~]# ls lxcfs
lxcfs-5.0.4-1.el9.x86_64.rpm  lxc-libs-4.0.12-1.el9.x86_64.rpm  lxc-templates-4.0.12-1.el9.x86_64.rpm

[root@docker ~]# dnf install lxcfs/*.rpm

运行lxcfs并解决容器隔离性
[root@docker ~]# lxcfs /var/lib/lxcfs &
[root@docker ~]# docker run  -it -m 256m \
-v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
-v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \
-v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
-v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
-v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
-v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
ubuntu
root@69ec0c67ff04:/# free  -m
               total        used        free      shared  buff/cache   available
Mem:             256           1         254           0           0         254
Swap:            512           0         512

3.容器特权

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

bash 复制代码
[root@docker ~]# docker run --rm -it  busybox
/ # whoami
root
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ip a a 192.168.0.100/24 dev eth0
ip: RTNETLINK answers: Operation not permitted

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

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

bash 复制代码
[root@docker ~]# docker run --rm -it --privileged busybox
/ # id root
uid=0(root) gid=0(root) groups=0(root),10(wheel)
/ # ip a a 192.168.0.100/24 dev eth0
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
29: eth0@if30: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.0.100/24 scope global eth0
       valid_lft forever preferred_lft forever
/ # fdisk  -l
Disk /dev/nvme0n1: 100 GB, 107374182400 bytes, 209715200 sectors
13003 cylinders, 256 heads, 63 sectors/track
Units: sectors of 1 * 512 = 512 bytes

Device       Boot StartCHS    EndCHS        StartLBA     EndLBA    Sectors  Size Id Type
/dev/nvme0n1p1    0,0,2       1023,255,63          1  209715199  209715199 99.9G ee EFI GPT

#如果添加了--privileged 参数开启容器,容器获得权限近乎于宿主机的root用户

4.容器特权的白名单

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

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

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

容器编排工具Docker Compose

1 概述

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

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

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

主要功能

1. 定义服务:

  • 使用 YAML 格式的配置文件来定义一组相关的容器服务。每个服务可以指定镜像、端口映射、环境变量、存储卷等参数。

  • 例如,可以在配置文件中定义一个 Web 服务和一个数据库服务,以及它们之间的连接关系。

2. 一键启动和停止:

  • 通过一个简单的命令,可以启动或停止整个应用程序所包含的所有容器。这大大简化了多容器应用的部署和管理过程。

  • 例如,使用 `docker-compose up` 命令可以启动配置文件中定义的所有服务,使用 `docker-compose down` 命令可以停止并删除这些服务。

3. 服务编排:

  • 可以定义容器之间的依赖关系,确保服务按照正确的顺序启动和停止。例如,可以指定数据库服务必须在 Web 服务之前启动。

  • 支持网络配置,使不同服务的容器可以相互通信。可以定义一个自定义的网络,将所有相关的容器连接到这个网络上。

4. 环境变量管理:

  • 可以在配置文件中定义环境变量,并在容器启动时传递给容器。这使得在不同环境(如开发、测试和生产环境)中使用不同的配置变得更加容易。

  • 例如,可以定义一个数据库连接字符串的环境变量,在不同环境中可以设置不同的值。

工作原理

1. 读取配置文件:

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

2. 创建容器:

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

3. 管理容器生命周期:

  • Docker Compose 监控容器的状态,并在需要时启动、停止、重启容器。

  • 它还可以处理容器的故障恢复,例如自动重启失败的容器。

Docker Compose 中的管理层

  1. 服务 (service) 一个应用的容器,实际上可以包括若干运行相同镜像的容器实例

  2. 项目 (project) 由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义

  3. 容器(container)容器是服务的具体实例,每个服务可以有一个或多个容器。容器是基于服务定义的镜像创建的运行实例

2 常用命令参数

bash 复制代码
services:
  web:
    image: nginx
    ports:
      - "80:80"

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: lee

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

一、服务管理

  1. docker-compose up:
  • 启动配置文件中定义的所有服务。

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

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

  • 例如:docker-compose up -d

    [root@docker test]# docker compose up -d
    [+] Running 2/2
    ✔ Container test-db-1 Started 0.9s
    ✔ Container test-web-1 Started 0.9s

    [root@docker ~]# docker compose -f test/docker-compose.yml up -d
    [+] Running 3/3
    ✔ Network test_default Created 0.1s
    ✔ Container test-web-1 Started 0.9s
    ✔ Container test-db-1 Started

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

    [root@docker test]# docker compose down
    [+] Running 3/3
    ✔ Container test-db-1 Removed 1.7s
    ✔ Container test-web-1 Removed 0.3s
    ✔ Network test_default Removed 0.1s

  1. docker-compose start:
  • 启动已经存在的服务,但不会创建新的服务。

    [root@docker test]# docker compose start
    [+] Running 2/2
    ✔ Container test-db-1 Started
    ✔ Container test-web-1 Started

4.docker-compose stop:

  • 停止正在运行的服务

    [root@docker test]# docker compose stop
    [+] Stopping 2/2
    ✔ Container test-web-1 Stopped 0.4s
    ✔ Container test-db-1 Stopped 10.3s

  1. docker-compose restart:
  • 重启服务。

    [root@docker test]# docker compose restart
    [+] Restarting 2/2
    ✔ Container test-web-1 Started
    ✔ Container test-db-1 Started

二、服务状态查看

  1. docker-compose ps:
  • 列出正在运行的服务以及它们的状态,包括容器 ID、名称、端口映射等信息。
bash 复制代码
[root@docker test]# docker compose ps
NAME         IMAGE       COMMAND                   SERVICE   CREATED         STATUS          PORTS
test-db-1    mysql:5.7   "docker-entrypoint.s..."   db        2 minutes ago   Up 48 seconds   3306/tcp, 33060/tcp
test-web-1   nginx       "/docker-entrypoint...."   web       2 minutes ago   Up 50 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp
  1. docker-compose logs:
  • 查看服务的日志输出。可以指定服务名称来查看特定服务的日志。
bash 复制代码
[root@docker test]# docker compose  logs db

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

  1. docker-compose build:
  • 构建配置文件中定义的服务的镜像。可以指定服务名称来只构建特定的服务。
bash 复制代码
[root@docker test]# cat Dockerfile
FROM  busybox:latest
RUN   touch /leefile1

[root@docker test]# cat lee.Dockerfile
services:
  test1:
    image: test1					#生成镜像名称
    build:
      context: /root/test			#指定Dockerfile位置
      dockerfile: lee.Dockerfile	#指定Dockerfile名字
    command: ["/bin/sh","-c","sleep 3000"]
    restart: always
    container_name: busybox1

  test2:
    image: test2
    build:
      context: /root/test				
      dockerfile: Dockerfile
    command: ["/bin/sh","-c","sleep 3000"]
    restart: always
    container_name: busybox2


[root@docker test]# docker compose -f test.yml build			#构建services中的所有
[root@docker test]# docker compose  -f test.yml build test1		#构建services中的test1

2.docker-compose up --build:

  • 启动服务并在启动前重新构建镜像。
bash 复制代码
[root@docker test]# docker compose  -f test.yml  up -d			#会去仓库拉去镜像
[+] Running 1/1
 ! test1 Warning pull access denied for test1, repository does not exist or may require 'docker login': denied: requested acces...  
 
 	
 [root@docker test]# docker compose  -f test.yml  up --build	#会先构建镜像后启动容器

四、其他操作

  1. docker-compose exec:
  • 在正在运行的服务容器中执行命令。
bash 复制代码
services:
  test:
    image: busybox
    command: ["/bin/sh","-c","sleep 3000"]
    restart: always
    container_name: busybox1

[root@docker test]# docker compose -f test.yml  up -d
[root@docker test]# docker compose  -f test.yml  exec  test sh
/ #
  1. docker-compose pull:
  • 拉取配置文件中定义的服务所使用的镜像。
bash 复制代码
[root@docker test]# docker compose -f test.yml pull
[+] Pulling 2/2
  ✔ test Pulled
  ✔ ec562eabd705 Pull complete  
  1. docker-compose config:
  • 验证并查看解析后的 Compose 文件内容
bash 复制代码
[root@docker test]# docker compose -f test.yml  config
name: test
services:
  test:
    command:
      - /bin/sh
      - -c
      - sleep 3000
    container_name: busybox1
    image: busybox
    networks:
      default: null
    restart: always
networks:
  default:
    name: test_default
[root@docker test]# docker compose -f test.yml  config -q

3 Docker Compose 的yml文件

services部分

1.端口暴露及端口映射

将容器内部的端口映射到主机的端口,以便外部可以访问容器内的服务。

bash 复制代码
services:
  web:
    image: nginx:1.23
    container_name: webserver
    expose:						#端口暴漏

   - 1234
     4321
         ports:						#端口映射
        - "80:80"

2.环境变量设定

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

bash 复制代码
services:
  web:
    image: nginx:1.23
    container_name: webserver
    expose:

   - 1234
     4321
         ports:
        - "80:80"
  DB:
    image: mysql:8.0
    container_name: dbserver
    environment:
      MYSQL_ROOT_PASSWORD: lee

#测试
[root@docker-node1 timinglee]# docker compose  exec -it DB  /bin/sh
sh-5.1# mysql -uroot -plee
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 8
Server version: 8.0.43 MySQL Community Server - GPL

Copyright (c) 2000, 2025, 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> quit

3.存储卷(volumes)

将主机上的目录或文件挂载到容器中,以实现数据持久化或共享。

例如,`- /host/data:/container/data` 将主机上的 `/host/data` 目录挂载到容器内的 `/container/data` 路径。

bash 复制代码
services:
  test:
    image: busybox:latest
    container_name: busybox
    command:
      - /bin/sh
      - -c
      - sleep 20000
    volumes:
      - /etc/passwd:/passwd:ro

#测试:
[root@docker-node1 timinglee]# docker compose  exec -it test  /bin/sh
/ # ls
bin     dev     etc     home    lib     lib64   passwd  proc    root    sys     tmp     usr     var
/ # echo aha > passwd
/bin/sh: can't create passwd: Read-only file system
/ # exit

4.网络设定

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

bash 复制代码
services:
  test:
    image: busybox:latest
    container_name: busybox
    command:
      - /bin/sh
      - -c
      - sleep 20000
    volumes:
      - /etc/passwd:/passwd:ro
    network_mode: none					#在此参数中写入的网络是docker原生网络
#    networks:							#在networks中指定自建网络,但是mynet1需要通过项目构建
#      - mynet1


#检测
[root@docker-node1 timinglee]# docker compose  down
[+] down 1/1
 ✔ Container busybox Removed  
 
[root@docker-node1 timinglee]# docker compose  exec -it test  /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
/ # exit

项目部分

1.网络(network)

  • 定义 Docker Compose 应用程序中使用的网络。可以自定义网络名称和驱动程序等属性。
  • 默认情况下docker compose 在执行时会自动建立网路

default网络

默认容器在运行时如果没有在services部分指定网络信息,如果建立default网络,那么默认容器使用的网络为default网络

bash 复制代码
[root@docker-node1 timinglee]# docker network create  mynet1
[root@docker-node1 timinglee]# docker network create  mynet2
[root@docker-node1 timinglee]# docker network inspect mynet2
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"



[root@docker-node1 timinglee]# vim docker-compose.yml
services:
  test:
    image: busybox:latest
    container_name: busybox
    command:
      - /bin/sh
      - -c
      - sleep 20000


networks:
  default:
    external: true						#使用已经存在的docker资源
    name: mynet2

测试:
[root@docker-node1 timinglee]# docker compose  exec -it test  /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if57: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 76:17:cc:60:dc:21 brd ff:ff:ff:ff:ff:ff
    inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0
       valid_lft forever preferred_lft forever

自建网络

bash 复制代码
[root@docker-node1 timinglee]# docker network rm  mynet1
mynet1
[root@docker-node1 timinglee]# docker network rm  mynet2
mynet2

[root@docker-node1 timinglee]# vim docker-compose.yml
services:
  test:
    image: busybox:latest
    container_name: busybox
    command:
      - /bin/sh
      - -c
      - sleep 20000
    networks:
      - mynet1
      - mynet2

networks:
  default:
    external: true
    name: bridge

  mynet1:
    driver: bridge

  mynet2:
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16
          gateway: 172.28.0.254
          
#测试:
[root@docker-node1 timinglee]# docker compose  exec -it test  /bin/sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if61: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 8e:4a:6f:ef:53:15 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
3: eth1@if62: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 9a:c6:ec:7e:80:c2 brd ff:ff:ff:ff:ff:ff
    inet 172.28.0.1/16 brd 172.28.255.255 scope global eth1
       valid_lft forever preferred_lft forever
	

2.存储部分

bash 复制代码
[root@docker-node1 timinglee]# docker volume ls
DRIVER    VOLUME NAME

[root@docker-node1 timinglee]# vim docker-compose.yml
services:
  test:
    image: busybox:latest
    container_name: busybox
    command:
      - /bin/sh
      - -c
      - sleep 20000
    networks:
      - mynet1
      - mynet2
    volumes:
      - leevol1:/lee

networks:
  default:
    external: true
    name: bridge

  mynet1:
    driver: bridge

  mynet2:
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16
          gateway: 172.28.0.254

volumes:
  leevol1:
    name: timinglee


#测试:
oot@docker-node1 timinglee]# docker compose  up -d
[+] up 4/4
 ✔ Network timinglee_mynet2 Created                                                                  0.0s
 ✔ Network timinglee_mynet1 Created                                                                  0.0s
 ✔ Volume timinglee         Created                                                                  0.0s
 ✔ Container busybox        Started                                                                  0.3s
[root@docker-node1 timinglee]# docker volume ls
DRIVER    VOLUME NAME
local     timinglee


[root@docker-node1 timinglee]# touch  /var/lib/docker/volumes/timinglee/_data/file
[root@docker-node1 timinglee]# touch  /var/lib/docker/volumes/timinglee/_data/file
[root@docker-node1 timinglee]# docker compose  exec -it test  /bin/sh
/ # ls
bin    dev    etc    home   lee    lib    lib64  proc   root   sys    tmp    usr    var
/ # ls lee/
file

4 企业项目实战

bash 复制代码
[root@docker-node1 mnt]# dnf install haproxy --downloadonly  --downloaddir /mnt -y
[root@docker-node1 mnt]# cd /mnt/
[root@docker-node1 mnt]# ls
haproxy-2.4.22-4.el9.x86_64.rpm

[root@docker-node1 mnt]# rpm2cpio  haproxy-2.4.22-4.el9.x86_64.rpm  | cpio -id
13489 块
[root@docker-node1 mnt]# ls
etc  haproxy-2.4.22-4.el9.x86_64.rpm  usr  var
[root@docker-node1 mnt]# mkdir  /conf
[root@docker-node1 mnt]# vim etc/haproxy/haproxy.cfg
listen webserver_80
    bind *:80
    mode http
    server webserver1 web1:80 check inter 3s fall 3 rise 5
    server webserver2 web2:80 check inter 3s fall 3 rise 5

[root@docker-node1 mnt]# cp  etc/haproxy/haproxy.cfg  /conf/


[root@docker-node1 timinglee]# vim docker-compose.yml
services:
  web1:
    image: nginx:1.23
    container_name: web1
    networks:
      - mynet1
    volumes:
      - "webdata1:/usr/share/nginx/html"
  web2:
    image: nginx:1.23
    container_name: web2
    networks:
      - mynet1
    volumes:
      - "webdata2:/usr/share/nginx/html"

  haproxy:
    image: haproxy:2.3
    container_name: haproxy
    networks:
      - mynet1
    volumes:
      - "/conf/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg"
    ports:
      - "80:80"

networks:
  mynet1:
    driver: bridge

volumes:
  webdata1:
    name: webdata1
  webdata2:
    name: webdata2


[root@docker-node1 timinglee]# docker compose up -d

[root@docker-node1 timinglee]#  echo web1 > /var/lib/docker/volumes/webdata1/_data/index.html
[root@docker-node1 timinglee]# echo web2 > /var/lib/docker/volumes/webdata2/_data/index.html

#测试:

[root@docker-node1 timinglee]# for i in {1..10};
> do
> curl 172.25.254.10
> done
web2
web1
web2
web1
web2
web1
web2
web1
web2
相关推荐
蜡笔小新..2 小时前
Linux下Matplotlib使用Times New Roman字体的解决方案
linux·运维·matplotlib
飞yu流星2 小时前
文件压缩、文本内容、文本编辑
运维·服务器
二宝哥2 小时前
Failed connect to mirrorlist.centos.org:80; Connection refused
linux·运维·centos
Kk.08023 小时前
Linux(九)fork复制进程与写时拷贝技术
linux·运维·服务器
张3233 小时前
K8s 标签
云原生·容器·kubernetes
齐齐大魔王3 小时前
linux-进程详解
linux·运维·服务器
應呈3 小时前
Bootloader与OTA学习记录
linux·运维·服务器
H_老邪3 小时前
Docker 学习之路-从入门到放弃:7
学习·docker·容器
skywalk81633 小时前
使用官方提供的 bump-pydantic 工具 来自动化部分迁移pydantic代码
运维·自动化