当前位置:

docker

故人归 |  2025-07-13
 164人浏览

笔记参照:

https://blog.csdn.net/qq_21197507/article/details/115071715

https://blog.51cto.com/u_14518853/4894194

1、docker概述

1.1、docker为什么出现

工作中,经常出现“在我的机器上可正常工作”的问题

因为环境不一致等原因导致。。。

Docker的思想就来自于集装箱!

隔离:Docker核心思想!打包装箱!每个箱子是互相隔离的。

Docker通过隔离机制,可以将服务器利用到极致!

1.2、docker的历史

Docker 是基于Go 语言实现的开源容器项目,诞生于2013 年年初,最初发起者是 dotCloud 公司。Docker 自开源后受到广泛的关注和l 讨论,目前已有多个相关项目(包括 Docker 三剑客、Kubemetes 等),逐渐形成了围绕Docker 容器的生态体系。 由于Docker 在业界造成的影响力实在太大, dotCloud 公司后来也直接改名为Docker Inc ,并专注于Docker 相关技术和产品的开发。

自从dotCloud公司开源其Docker项目后,凭借其便捷的Docker镜像技术解决了当时困扰众多PaaS项目的难题:如何为应用打包,让用户将本地的应用顺利迁移到PaaS平台,而不用顾忌应用的开发语言、配置、依赖包等诸多因素,也因此开启了全新的Docker容器时代。

1.3、docker能干嘛

对开发和运维( DevOps )人员来说,可能最梦寐以求的效果就是一次创建或配置, 之后可以在任意地方、任意时间让应用正常运行。

具体说来, Docker 在开发和运维过程中,具有如下几个方面的优势:

  1. 更快速的交付和部署

    使用Docker ,开发人员可以使用镜像来快速构建一套标准的开发环境;开发完成之后,测试和运维人员可以直接使用完全相同环境来部署代码。只要开发测试过的代码,就可以确保在生产环境无缝运行。Docker 可以快速创建和删除容器,实现快速迭代,大量节约开发、测试、部署的时间。并且,整个过程全程可见,使团队更容易理解应用的创建和工作过程。

  2. 更高效的资源利用

    Docker 容器的运行不需要额外的虚拟化管理程序(Virtual Machine Manager, VMM ,以及Hypervisor)支持,它是内核级的虚拟化,可以实现更高的性能,同时对资源的额外需求很低。跟传统虚拟机方式相比,要提高一到两个数量级。

  3. 更轻松的迁移和扩展

    Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等,同时支持主流的操作系统发行版本。这种兼容性让用户可以在不同平台之间轻松地迁移应用。

  4. 更简单的更新管理

    使用Dockerfile ,只需要小小的配置修改,就可以替代以往大量的更新工作。并且所有修改都以增量的方式被分发和更新,从而实现自动化并且高效的容器管理。

Docker 和常见的虚拟化方式的不同之处

image-20230320215021162

传统方式是在硬件层面实现虚拟化,需要有额外的虚拟机管理应用和虚拟机操作系统 层。Docker 容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,因此更加 轻量级。

Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。

作为一种新兴的虚拟化方式,Docker 跟传统的虚拟化方式相比具有众多的优势。Docker 容器的启动可以在秒级实现,这相比传统的虚拟机方式要快得多;Docker 对系统资源的利用率很高,一台主机上可以同时运行数千个 Docker 容器。

2、docker安装

2.1、docker的基本组成

img

  • 镜像(Image)

    什么是 Docker 镜像?简单的理解,Docker 镜像就是一个 Linux 的文件系统(Root FileSystem),这个文件系统里面包含可以运行在 Linux 内核的程序以及相应的数据。

    通过镜像启动一个容器,一个镜像就是一个可执行的包,其中包括运行应用程序所需要的所有内容:包含代码,运行时间,库,环境变量和配置文件等。

    Docker 把 App 文件打包成为一个镜像,并且采用类似多次快照的存储技术,可以实现:

    • 多个 App 可以共用相同的底层镜像(初始的操作系统镜像)
    • App 运行时的 IO 操作和镜像文件隔离
    • 通过挂载包含不同配置/数据文件的目录或者卷(Volume),单个 App 镜像可以用来运行无数个不同业务的容器
  • 容器(container)

    镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。image-20230320220941650

  • 仓库(repository)

    仓库可看成一个代码控制中心,用来保存镜像。

    仓库分为公有仓库和私有仓库。(很类似git)

    Docker Hub是国外的。

    阿里云…都有容器服务器(配置镜像加速!)

2.2、安装docker

显示操作系统内核版本号

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# uname -r
3.10.0-1160.81.1.el7.x86_64

查看系统信息

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# cat /etc/os-release 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

安装

#1.卸载旧版本
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
#2.需要的安装包
yum install -y yum-utils

#3.设置镜像的仓库
#上述方法默认是从国外的,不推荐
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

#推荐使用国内的
yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

#更新yum软件包索引
yum makecache fast

#4.安装docker相关的 docker-ce 社区版 而ee是企业版
yum install docker-ce docker-ce-cli containerd.io # 这里我们使用社区版即可

#5.启动docker
systemctl start docker

#6. 使用docker version查看是否按照成功
docker version

#7. 测试
docker run hello-world

docker版本

image-20230321235539361

运行hello-world

image-20230321235618931

查看镜像

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    feb5d9fea6a5   18 months ago   13.3kB
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# 

卸载docker

#1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
#2. 删除资源
rm -rf /var/lib/docker
# /var/lib/docker 是docker的默认工作路径!

2.3、阿里云镜像加速

1、找到阿里云的容器镜像服务

image-20230321235912284

2、找到镜像加速器

image-20230321235945882

3、配置使用

#1.创建一个目录
mkdir -p /etc/docker
#2.编写配置文件
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://irgp9g5e.mirror.aliyuncs.com"]
}
EOF
#3.重启服务
systemctl daemon-reload

systemctl restart docker

2.4、回滚hello-world流程

image-20230322225625935

底层原理

docker是怎么工作的

docker是一个client-server结构的系统,docker守护进程运行在主机上,然后通过socket连接从客户端访问docker守护进程。

docker守护进程从客户端接收命令,并按照命令,管理运行在主机上的容器。

一个docker容器,是一个运行时环境,可以简单理解为进程运行的集装箱。

image-20230322230258373

为什么docker比vm快

  1. Docker有这比虚拟机更少的抽象层,由于Docker不需要Hypervisor实现硬件资源虚拟化,运行在Docker上的程序直接使用的都是实际物理机上的硬件资源,因此在CPU、内存利用率上有明显的优势。
  2. **Docker利用的是宿主机的内核,而不需要使用Guest OS ** ,因此当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核,而避免引寻 ,加载操作系统内核是个比较费事费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载Guest OS,返回的新建的过程是分钟级别,而docker直接使用的是宿主机上的操作系统,则省略了返回这个的过程,因此新建一个docker容器只需要几秒钟。

虚拟机与Docker架构对比图:

image-20230322230957379

image-20230322231038848

3、docker的常用命令

官方文档常用命令地址:https://docs.docker.com/reference/

image-20230322231553441

3.1、帮助命令

#显示docker的版本信息。
docker version    
#显示docker的系统信息,包括镜像和容器的数量
docker info   
#帮助命令
docker --help
docker 命令 --help 

3.2、镜像命令

docker image 查看所有本地主机上的镜像

参数和选项

  • -a, --all 列出所有镜像
  • -q, --quiet 只显示镜像id

测试

1、查看本地主机上的镜像

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
hello-world   latest    feb5d9fea6a5   18 months ago   13.3kB
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# 

解释:

  • REPOSITORY 镜像的仓库源
  • TAG 镜像的标签(版本) latest表示最新的版本
  • IMAGE ID 镜像id
  • CREATED 镜像的创建时间
  • SIZE 镜像的大小

2、列出所有镜像的id

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker images -aq
feb5d9fea6a5

docker search 搜索镜像

镜像仓库地址:https://hub.docker.com/

参数和选项

  • -f, --filter filter 基于条件过滤

测试

1、搜索mysql镜像

在docker仓库上搜

image-20230322232956828

也可以这样搜

image-20230322233013636

2、搜索出来的镜像收藏STARS数量大于3000的

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker search mysql -f=STARS=3000

image-20230322233433247

docker pull 下载镜像

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker pull mysql
Using default tag: latest    #不如不指定tag,默认就是latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete  #分层下载,docker images的核心,联合文件系统
93619dbc5b36: Pull complete 
99da31dd6142: Pull complete 
626033c43d70: Pull complete 
37d5d7efb64e: Pull complete 
ac563158d721: Pull complete 
d2ba16033dad: Pull complete 
688ba7d5c01a: Pull complete 
00e060b6d11d: Pull complete 
1c04857f594f: Pull complete 
4d7cfa90e6ea: Pull complete 
e0431212d27d: Pull complete 
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 #签名
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址

----
#docker pull mysql
#等价于
#docker pull docker.io/library/mysql:latest
----

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker pull mysql:5.7 #指定版本下载
5.7: Pulling from library/mysql
72a69066d2fe: Already exists 
93619dbc5b36: Already exists 
99da31dd6142: Already exists 
626033c43d70: Already exists 
37d5d7efb64e: Already exists 
ac563158d721: Already exists 
d2ba16033dad: Already exists 
0ceb82207cd7: Pull complete 
37f2405cae96: Pull complete 
e2482e017e53: Pull complete 
70deed891d42: Pull complete 
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker images #查看镜像
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
mysql         5.7       c20987f18b13   15 months ago   448MB
mysql         latest    3218b38490ce   15 months ago   516MB
hello-world   latest    feb5d9fea6a5   18 months ago   13.3kB

docker rmi删除镜像

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker rmi -f 镜像id                    #删除指定镜像
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker rmi -f 镜像id1 镜像id2 镜像id3     #删除多个镜像
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker rmi -f $(docker images -aq)      #删除所有镜像 

image-20230322234619082

3.3、容器命令

我们有了镜像,才能创建容器,所以先下载一个centos镜像来学习

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker pull centos

image-20230323235321877

启动容器

docker run [可选参数] 容器名或者容器id

创建一个新的容器并运行一个命令

可选参数

  • -i: 以交互模式运行容器,通常与 -t 同时使用
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用
  • -P: 随机端口映射,容器内部端口随机映射到主机的端口
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -d: 后台运行容器,并返回容器ID;
  • --name="nginx-lb": 为容器指定一个名称
  • -e username="ritchie": 设置环境变量

测试

1、使用镜像centos以交互模式启动一个容器,在容器内执行/bin/bash命令

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -it centos /bin/bash

image-20230324000323679

退出容器

exit       #直接退出容器并关闭
快捷键:ctrl+p+q   #容器不关闭退出 注意p和q的顺序!

列出所有的容器

docker ps

可选参数

  • **-a :**显示所有的容器,包括未运行的。
  • **-n :**列出最近创建的n个容器。
  • **-q :**静默模式,只显示容器编号。
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps  #列出当前正在运行的容器
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
e769f9d12d28   centos    "/bin/bash"   16 seconds ago   Up 16 seconds             mystifying_bell
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS                        PORTS     NAMES
e769f9d12d28   centos         "/bin/bash"   25 seconds ago   Up 25 seconds                           mystifying_bell
cd2b6006d431   centos         "/bin/bash"   48 seconds ago   Exited (0) 48 seconds ago               vigorous_kilby
0fe74c1cbcf8   centos         "/bin/bash"   18 minutes ago   Exited (137) 16 minutes ago             nervous_morse
332fd2aa8995   centos         "/bin/bash"   18 minutes ago   Exited (0) 18 minutes ago               amazing_borg
b204f1dec292   5d0da3dc9764   "/bin/bash"   20 minutes ago   Exited (0) 20 minutes ago               clever_grothendieck
556e1ecba57e   feb5d9fea6a5   "/hello"      2 days ago       Exited (0) 2 days ago                   stoic_keller
93adc83b7466   feb5d9fea6a5   "/hello"      2 weeks ago      Exited (0) 2 weeks ago                  eloquent_dubinsky
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps -aq
e769f9d12d28
cd2b6006d431
0fe74c1cbcf8
332fd2aa8995
b204f1dec292
556e1ecba57e
93adc83b7466
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# 

删除容器

docker rm -f 容器id                       # 删除指定容器
docker rm -f $(docker ps -aq)       # 删除所有容器
docker ps -a -q|xargs docker rm -f  # 删除所有的容器

启动和停止容器

docker start 容器id           # 启动容器
docker restart 容器id         # 重启容器
docker stop 容器id            # 停止当前正在运行的容器
docker kill 容器id            # 强制停止当前的容器

image-20230324001216692

3.4、常用其他命令

后台启动命令

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -d centos
fcdd8111042db1bc8cdb1304910142fff5b4c2ac18e96e695d2943257e8ade89
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# 

# 问题,后端启动容器后,docker ps,发现centos停止了
# 常见的坑, docker 容器使用后台运行, 就必须要有一个前台进程,docker发现没有应用,就会自动停止
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -d -it centos #这种启动容器后就不会关闭了
0968ab2a263d41beb063e12a40a45024b749d49897f9edd6eec78828b5f0b896
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
0968ab2a263d   centos    "/bin/bash"   4 seconds ago   Up 3 seconds             admiring_boyd

查看日志

docker logs [参数与参选] 容器id

参数与选项

  • -f : 跟踪日志输出
  • -t : 显示时间戳
  • **--since :**显示某个开始时间的所有日志
  • -n或者**--tail :**仅列出最新N条容器日志
# docker logs -tf -n=10 容器id
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker logs -tf -n=10 a72f233b693f
# 这里没有日志,我们自己编写一段shell脚本
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -d -it centos /bin/bash -c "while true;do echo zyy hello;sleep 1;done"
a72f233b693f204e78a94671df7060de418cf03d3f7c9bdc6c224fc3a5fc2c05
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS     NAMES
a72f233b693f   centos    "/bin/bash -c 'while…"   4 seconds ago   Up 3 seconds             hopeful_wescoff
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker logs -tf -n=10 a72f233b693f
2023-03-26T02:36:20.853549289Z zyy hello
2023-03-26T02:36:21.855575170Z zyy hello
2023-03-26T02:36:22.857717770Z zyy hello
2023-03-26T02:36:23.859828174Z zyy hello
2023-03-26T02:36:24.861974759Z zyy hello
2023-03-26T02:36:25.864026002Z zyy hello
2023-03-26T02:36:26.866091408Z zyy hello
2023-03-26T02:36:27.868137295Z zyy hello
2023-03-26T02:36:28.870218421Z zyy hello
2023-03-26T02:36:29.872311002Z zyy hello
2023-03-26T02:36:30.874521421Z zyy hello
2023-03-26T02:36:31.876815315Z zyy hello
2023-03-26T02:36:32.878998053Z zyy hello
2023-03-26T02:36:33.880995085Z zyy hello
2023-03-26T02:36:34.883166453Z zyy hello
2023-03-26T02:36:35.885199608Z zyy hello
...

命令docker run -d -it centos /bin/bash -c "while true;do echo zyy hello;sleep 1;done"解释:

该命令会不停地输出字符串 "zyy hello",每隔 1 秒钟输出一次,直到容器被停止。

其中,各个参数的含义如下:

  • docker run 是 Docker 命令的基本语法,用于启动一个新的容器。
  • -d 参数表示在后台运行容器。
  • centos 参数表示使用的镜像名称,这里使用的是 CentOS 镜像。
  • /bin/bash -c "while true;do echo zyy hello;sleep 1;done" 参数表示在容器内部执行的 shell 命令。其中 /bin/bash 是 shell 的路径,-c 参数表示在 shell 中执行指定的命令。这里的命令是一个无限循环,不停地输出字符串 "zyy hello"。

查看容器中的进程信息

docker top 容器id

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
8f02758fe0db   centos    "/bin/bash"   3 seconds ago   Up 3 seconds             compassionate_poincare
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker top 8f02758fe0db
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                17764               17743               0                   10:48               ?                   00:00:00            /bin/bash
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# 

查看镜像的元数据

docker inspect 容器id 元数据 (meta data)——"data about data" 描述数据的数据,一般是结构化数据

元数据是指从信息资源中抽取出来的用于说明其特征、内容的结构化的数据(如题名,版本、出版数据、相关说明,包括检索点等),用于组织、描述、检索、保存、管理信息和知识资源

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker inspect 8f02758fe0db
[
    {
        "Id": "8f02758fe0db015c95ea2d2c61806573bce8d7cb80cecd3bcc5378d340a0cb4a",
        "Created": "2023-03-26T02:48:59.227650262Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 17764,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2023-03-26T02:48:59.520077966Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "ResolvConfPath": "/var/lib/docker/containers/8f02758fe0db015c95ea2d2c61806573bce8d7cb80cecd3bcc5378d340a0cb4a/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/8f02758fe0db015c95ea2d2c61806573bce8d7cb80cecd3bcc5378d340a0cb4a/hostname",
        "HostsPath": "/var/lib/docker/containers/8f02758fe0db015c95ea2d2c61806573bce8d7cb80cecd3bcc5378d340a0cb4a/hosts",
        "LogPath": "/var/lib/docker/containers/8f02758fe0db015c95ea2d2c61806573bce8d7cb80cecd3bcc5378d340a0cb4a/8f02758fe0db015c95ea2d2c61806573bce8d7cb80cecd3bcc5378d340a0cb4a-json.log",
        "Name": "/compassionate_poincare",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "ConsoleSize": [
                50,
                174
            ],
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": [],
            "BlkioDeviceWriteBps": [],
            "BlkioDeviceReadIOps": [],
            "BlkioDeviceWriteIOps": [],
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/6a2de276a5a9415b776293e5ec786fa5c0f43bcc35d937b9726eee76d5d3d92d-init/diff:/var/lib/docker/overlay2/a88c68da7a2c4a3390c008afd816a4c718160bff2eb70f1de8987209ad34a7ba/diff",
                "MergedDir": "/var/lib/docker/overlay2/6a2de276a5a9415b776293e5ec786fa5c0f43bcc35d937b9726eee76d5d3d92d/merged",
                "UpperDir": "/var/lib/docker/overlay2/6a2de276a5a9415b776293e5ec786fa5c0f43bcc35d937b9726eee76d5d3d92d/diff",
                "WorkDir": "/var/lib/docker/overlay2/6a2de276a5a9415b776293e5ec786fa5c0f43bcc35d937b9726eee76d5d3d92d/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [],
        "Config": {
            "Hostname": "8f02758fe0db",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "centos",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {
                "org.label-schema.build-date": "20210915",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            }
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "907d78b2abf5b30265866452bd753e6a66458c0daed56e9aab5d145f9fa95c0a",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/907d78b2abf5",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "0638f1bce8b8c03e725ea034d4067876afab4c0030414fa9cb0aa7058cd4a51e",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "a3187499d9b1427eb9dcaa7901657d42964c2997c434e765caeb3d126d1eeba3",
                    "EndpointID": "0638f1bce8b8c03e725ea034d4067876afab4c0030414fa9cb0aa7058cd4a51e",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

进入当前正在运行的容器

方式一:docker exec

docker exec -it 容器id /bin/bash

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS              PORTS     NAMES
8f02758fe0db   centos    "/bin/bash"   18 minutes ago   Up About a minute             compassionate_poincare
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker exec -it 8f02758fe0db /bin/bash
[root@8f02758fe0db /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 03:05 pts/0    00:00:00 /bin/bash
root        15     0  0 03:08 pts/1    00:00:00 /bin/bash
root        29    15  0 03:08 pts/1    00:00:00 ps -ef
[root@8f02758fe0db /]# 

方式二:docker attach

docker attach 容器id

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker attach 8f02758fe0db
[root@8f02758fe0db /]# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 03:05 pts/0    00:00:00 /bin/bash
root        15     0  0 03:08 pts/1    00:00:00 /bin/bash
root        31     1  0 03:10 pts/0    00:00:00 ps -ef
[root@8f02758fe0db /]# 

区别

# docker exec       # 进入容器后开启一个新的终端,可以在里面操作
# docker attach     # 进入容器正在执行的终端,不会启动新的进程
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
356ee5e84d55   centos    "/bin/bash"   15 seconds ago   Up 15 seconds             cranky_wilson
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker exec -it 356ee5e84d55 /bin/bash #进入容器
[root@356ee5e84d55 /]# exit #退出容器
exit
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps #发现容器依然运行
CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS              PORTS     NAMES
356ee5e84d55   centos    "/bin/bash"   About a minute ago   Up About a minute             cranky_wilson
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker attach 356ee5e84d55 #进入容器
[root@356ee5e84d55 /]# exit  #退出容器
exit
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps #发现容器停止
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# 

从容器拷贝到主机上、从主机拷贝到容器上

docker cp 容器id:容器文件 主机路径

docker cp 主机文件 容器id:容器路径

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
45ee18e9901f   centos    "/bin/bash"   23 seconds ago   Up 23 seconds             xenodochial_hellman
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker exec -it 45ee18e9901f /bin/bash #进入容器
[root@45ee18e9901f /]# cd /home/
[root@45ee18e9901f home]# ls
[root@45ee18e9901f home]# touch hello.java #/home/下新建一个文件hello.java
[root@45ee18e9901f home]# ls
hello.java
[root@45ee18e9901f home]# exit #退出容器,并不会关闭容器
exit
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS              PORTS     NAMES
45ee18e9901f   centos    "/bin/bash"   About a minute ago   Up About a minute             xenodochial_hellman
[root@iZwz9bo1dt9faz5t06j6ijZ home]# cd /home/zyy #进去主机指定目录
[root@iZwz9bo1dt9faz5t06j6ijZ zyy]# ls
[root@iZwz9bo1dt9faz5t06j6ijZ zyy]# docker cp 45ee18e9901f:/home/hello.java /home/zyy #从容器拷贝到主机上
Successfully copied 1.536kB to /home/zyy
[root@iZwz9bo1dt9faz5t06j6ijZ zyy]# ls #发现拷贝成功
hello.java
[root@iZwz9bo1dt9faz5t06j6ijZ zyy]# touch zyy.java #主机上创建一个文件zyy.java
[root@iZwz9bo1dt9faz5t06j6ijZ zyy]# ls
hello.java  zyy.java
[root@iZwz9bo1dt9faz5t06j6ijZ zyy]# docker cp zyy.java 45ee18e9901f:/home #主机拷贝到容器上
Successfully copied 1.536kB to 45ee18e9901f:/home
[root@iZwz9bo1dt9faz5t06j6ijZ zyy]# docker exec -it 45ee18e9901f /bin/bash #进入容器
[root@45ee18e9901f /]# cd /home/
[root@45ee18e9901f home]# ls  #发现拷贝成功
hello.java  zyy.java

3.5、命名大全

https://pythondjango.cn/python/tools/2-docker-dockerfile/

image-20230326113219905

4、练习

4.1、docker安装nginx

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker search nginx #1.查找nginx镜像
NAME                                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                                             Official build of Nginx.                        18287     [OK]       
bitnami/nginx                                     Bitnami nginx Docker Image                      155                  [OK]
bitnami/nginx-ingress-controller                  Bitnami Docker Image for NGINX Ingress Contr…   23                   [OK]
ubuntu/nginx                                      Nginx, a high-performance reverse proxy & we…   83                   
kasmweb/nginx                                     An Nginx image based off nginx:alpine and in…   4                    
rancher/nginx-ingress-controller                                                                  11  
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker pull nginx #2.下载nginx镜像
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete 
a9edb18cadd1: Pull complete 
589b7251471a: Pull complete 
186b1aaa4aa6: Pull complete 

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker images #3.查看nginx镜像
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        latest    605c77e624dd   15 months ago   141MB
centos       latest    5d0da3dc9764   18 months ago   231MB

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -it -d --name nginx02 -p 3344:80 nginx #4.启动nginx镜像
756a17e3d66eec7cc89fe68b5090473f976f1afacc8048b4564bb3e7854d27ef
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps  #5.查看nginx容器
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                   NAMES
756a17e3d66e   nginx     "/docker-entrypoint.…"   6 seconds ago   Up 5 seconds   0.0.0.0:3344->80/tcp, :::3344->80/tcp   nginx02
45ee18e9901f   centos    "/bin/bash"              3 hours ago     Up 3 hours   

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# curl localhost:3344 #6.访问nginx容器
<!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>

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker exec -it nginx02 /bin/bash #7.进入容器

root@756a17e3d66e:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx

docker run -it -d --name nginx02 -p 3344:80 nginx解释

  • docker run:启动一个新的容器
  • -it:表示启用交互式终端并分配一个伪终端,这样我们可以在容器中交互式地执行命令。
  • -d:表示将容器运行在后台(守护进程)。
  • --name nginx02:给容器起一个名字叫做 nginx02。
  • -p 3344:80:将主机的 3344 端口映射到容器的 80 端口,这样我们就可以通过主机的 3344 端口来访问容器内的 Nginx 服务。
  • nginx:表示要启动的镜像名称为 nginx。

因此,这个命令的作用是在 Docker 中启动一个名为 nginx02 的容器,运行 Nginx 服务,并将容器的 80 端口映射到主机的 3344 端口,以便我们可以通过访问主机的 3344 端口来访问 Nginx 服务。容器会在后台运行,并启用交互式终端。

登录阿里云,开启3344端口

image-20230326144619895

浏览器可以直接访问

image-20230326144633750

4.2、docker安装一个tomcat

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker pull tomcat  # 下载镜像
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker images  #查看镜像
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        latest    605c77e624dd   15 months ago   141MB
tomcat       9.0       b8e65a4d736d   15 months ago   680MB
tomcat       latest    fb5657adc892   15 months ago   680MB
centos       latest    5d0da3dc9764   18 months ago   231MB

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -d -p 3355:8080 --name tomcat01 tomcat  #启动容器

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps #查看容器
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                       NAMES
39c699abdaf2   tomcat    "catalina.sh run"        18 seconds ago   Up 17 seconds   0.0.0.0:3355->8080/tcp, :::3355->8080/tcp   tomcat01
756a17e3d66e   nginx     "/docker-entrypoint.…"   43 minutes ago   Up 43 minutes   0.0.0.0:3344->80/tcp, :::3344->80/tcp       nginx02
45ee18e9901f   centos    "/bin/bash"              4 hours ago      Up 4 hours                                                  xenodochial_hellman

启动容器后,开通阿里云服务的3355端口

image-20230326152528344

访问服务

image-20230326153054253

发现服务可以访问,但是没有页面

进入服务

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker exec -it 39c699abdaf2 /bin/bash

root@39c699abdaf2:/usr/local/tomcat/webapps# ls
root@39c699abdaf2:/usr/local/tomcat/webapps# 

发现webapp下为空

# 原因:阿里云镜像的原因,阿里云默认是最小的镜像,所以不必要的都剔除掉
# 保证最小可运行的环境!

解决方案:将webapps.dist下的文件都拷贝到webapps下即可

root@39c699abdaf2:/usr/local/tomcat# cp -r webapps.dist/* webapps
root@39c699abdaf2:/usr/local/tomcat# cd webapps
root@39c699abdaf2:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager

刷新一下服务,就页面了

image-20230326153842469

问题:我们以后要部署项目,如果每次都要进入容器是不是十分麻烦?要是可以在容器外部提供一个映射路径,比如webapps,我们在外部放置项目,就自动同步内部就好了!

4.3、docker安装elasticsearch

elasticsearch暴露的端口很多

十分耗内存(所以体现测试的时候可以提前把其他docker容器先停止,启动时可以限制堆内存大小)

es 的数据一般需要放置到安全目录!挂载

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
Unable to find image 'elasticsearch:7.6.2' locally
7.6.2: Pulling from library/elasticsearch
ab5ef0e58194: Pull complete 
c4d1ca5c8a25: Pull complete 
941a3cc8e7b8: Pull complete 
43ec483d9618: Pull complete 
c486fd200684: Pull complete 
1b960df074b2: Pull complete 
1719d48d6823: Pull complete 
Digest: sha256:1b09dbd93085a1e7bca34830e77d2981521a7210e11f11eda997add1c12711fa
Status: Downloaded newer image for elasticsearch:7.6.2
47f6fe60c0f9ce6e88f3c9ece266e3ede8b849f57a4d1c1aa3f515ffec72a38d
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# curl localhost:9200
{
  "name" : "47f6fe60c0f9",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "bbkkYZB3SdepgzEV_-B-AQ",
  "version" : {
    "number" : "7.6.2",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
    "build_date" : "2020-03-26T06:34:37.794943Z",
    "build_snapshot" : false,
    "lucene_version" : "8.4.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker stats   #查看cpu状态

image-20230326162833498

image-20230326163159354

docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2命令解释

这是一个使用 Docker 命令行工具来启动一个 Elasticsearch 版本为 7.6.2 的容器,并设置了一些选项和参数。

具体来说,这些选项和参数的含义如下:

  • -d 表示在后台运行容器,即以“守护进程”模式运行,不会占用当前终端的控制台;
  • --name es 表示给容器起一个名称为 "es";
  • -p 9200:9200 -p 9300:9300 表示将容器内部的 9200 端口和 9300 端口映射到主机的 9200 和 9300 端口上,以便在主机上通过浏览器或客户端连接 Elasticsearch;
  • -e "discovery.type=single-node" 表示设置 Elasticsearch 的节点类型为 "single-node",即单节点模式,这是一个简单的运行 Elasticsearch 的方式,适用于测试或开发环境;
  • -e ES_JAVA_OPTS="-Xms64m -Xmx512m" 表示设置 Elasticsearch 的 Java 虚拟机参数,其中 "-Xms64m" 表示设置初始堆大小为 64MB,"-Xmx512m" 表示设置最大堆大小为 512MB;
  • elasticsearch:7.6.2 表示要运行的容器镜像名称和版本号,这里是 Elasticsearch 官方提供的 7.6.2 版本。

总体来说,这个命令的作用是在 Docker 中启动一个 Elasticsearch 7.6.2 的容器,并将容器内部的端口映射到主机上,以便在主机上访问 Elasticsearch。其中的选项和参数可以根据需要进行修改或调整。

5、portainer可视化面板安装

  • portainer(先用这个)
  • rancher(CI/DI再用)
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
ce7fe4df829ef8d8a9bc31297008102481a0e2b7b09e619b8eb5caec3a5fcd85
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# 

docker run -d -p 8088:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer解释

这是一个用于运行 Docker 容器的 Docker 命令。具体来说,该命令启动了一个名为 Portainer 的 Docker 容器,并将容器的 9000 端口映射到主机的 8088 端口,以便在主机上通过浏览器访问 Portainer。

以下是各个参数的含义:

  • -d:表示以后台模式运行容器。
  • -p 8088:9000:表示将容器的 9000 端口映射到主机的 8088 端口。
  • --restart=always:表示容器在停止后总是会自动重启。
  • -v /var/run/docker.sock:/var/run/docker.sock:表示将主机的 Docker 守护进程的 Unix 套接字文件(/var/run/docker.sock)挂载到容器的同一位置,从而让 Portainer 可以管理主机上的其他 Docker 容器。
  • --privileged=true:表示在容器中开启特权模式,以便 Portainer 能够访问主机上的 Docker 守护进程。

总之,这个命令的作用是在主机上启动一个 Portainer 容器,以便通过 web 界面来管理和监控其他 Docker 容器。

阿里云服务端开启端口8088

image-20230326203112531

登录:http://120.79.234.62:8088/#/init/admin

image-20230326203033831

进入面板

image-20230326203142825

image-20230326203221658

image-20230326203443725

6、docker镜像

6.1、镜像是什么?

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含

运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。

6.2、docker镜像加载原理

UnionFS(联合文件系统)

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,

它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系

统下(unite several directories into a single virtual fifilesystem)。Union 文件系统是 Docker 镜像的基

础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件

系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

bootfs(boot fifile system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启

动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是

一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已

由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root fifile system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标

准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

image-20230327222722084

平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?

image-20230327223033421

对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直

接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一

致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

6.3、分层理解

我们可以去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker pull redis
Using default tag: latest
latest: Pulling from library/redis
a2abf6c4d29d: Already exists 
c7a4e4382001: Pull complete 
4044b9ba67c9: Pull complete 
c8388a79482f: Pull complete 
413c8bb60be2: Pull complete 
1abfd3011519: Pull complete 
Digest: sha256:db485f2e245b5b3329fdc7eff4eb00f913e09d8feb9ca720788059fdc2ed8339
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# 

思考:为什么Docker镜像要采用这种分层的结构呢?

最大的好处,我觉得莫过于是资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机

只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服

务了,而且镜像的每一层都可以被共享。

查看镜像分层的方式可以通过 docker image inspect 命令!

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker image inspect redis:latest
[
    {
        //....
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f",
                "sha256:9b24afeb7c2f21e50a686ead025823cd2c6e9730c013ca77ad5f115c079b57cb",
                "sha256:4b8e2801e0f956a4220c32e2c8b0a590e6f9bd2420ec65453685246b82766ea1",
                "sha256:529cdb636f61e95ab91a62a51526a84fd7314d6aab0d414040796150b4522372",
                "sha256:9975392591f2777d6bf4d9919ad1b2c9afa12f9a9b4d260f45025ec3cc9b18ed",
                "sha256:8e5669d8329116b8444b9bbb1663dda568ede12d3dbcce950199b582f6e94952"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

理解:

所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之

上,创建新的镜像层。

举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果

在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就

会创建第三个镜像层。

该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

image-20230327224822853

在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了

一个简单的例子,每个镜像层包含 3 个文件,而镜像包含了来自两个镜像层的 6 个文件。

image-20230327224942247

上图中的镜像层跟之前图中的略有区别,主要目的是便于展示文件。

下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有 6 个文件,这是因为最上层中的文件

7 是文件 5 的一个更新版本。

image-20230327225036434

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新

镜像层添加到镜像当中。

Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统

一的文件系统。

Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储

引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。

Docker 在 Windows 上仅支持 windowsfifilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分

层和 CoW。

下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

image-20230327225127839

特点

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!

这一层就是我们通常说的容器层,容器之下的都叫镜像层!

6.4、镜像commit

docker commit 从容器创建一个新的镜像。

docker commit 提交容器副本使之成为一个新的镜像!

# 语法 
docker commit -m="提交的描述信息" -a="作者" 容器id 要创建的目标镜像名:[标签名]
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -it -p 3355:8080 tomcat #1.启动tomcat

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                                       NAMES
33ed62665435   tomcat    "catalina.sh run"   32 seconds ago   Up 31 seconds   0.0.0.0:3355->8080/tcp, :::3355->8080/tcp   wonderful_sinoussi

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker exec -it 33ed62665435 /bin/bash  #2.进入容器

root@33ed62665435:/usr/local/tomcat# cp -r webapps.dist/* webapps  #3.把webapps.dist下的所有文件拷贝到webapps.dist下

root@33ed62665435:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  manager

root@33ed62665435:/usr/local/tomcat/webapps# exit  #4.退出但是不关闭容器

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED         STATUS         PORTS                                       NAMES
33ed62665435   tomcat    "catalina.sh run"   3 minutes ago   Up 3 minutes   0.0.0.0:3355->8080/tcp, :::3355->8080/tcp   wonderful_sinoussi

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker commit -a="zyy" -m "add webapps app" 33ed62665435 mytomcat:1.0 #5.commit  注意:commit的时候,容器的名字不能有大写,否则报错:invalid reference format
sha256:0863ecb3b8ee295f8a3e8a3dc678dcdaa5cd8fd9bb329b0f302cb4b3c056178f

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker images  #6.查看镜像,发现我们提交的镜像已经ok
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
mytomcat              1.0       0863ecb3b8ee   8 seconds ago   684MB
nginx                 latest    605c77e624dd   15 months ago   141MB
tomcat                latest    fb5657adc892   15 months ago   680MB
redis                 latest    7614ae9453d1   15 months ago   113MB
centos                latest    5d0da3dc9764   18 months ago   231MB
portainer/portainer   latest    580c0e4e98b0   2 years ago     79.1MB
elasticsearch         7.6.2     f29a1ee41030   3 years ago     791MB


[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker stop 33ed62665435 #7.停止之前的tomcat容器
33ed62665435

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -it -p 3355:8080 mytomcat:1.0 #8.用我们自己制作的镜像启动容器

[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
CONTAINER ID   IMAGE          COMMAND             CREATED          STATUS          PORTS                                       NAMES
eca87c7626a1   mytomcat:1.0   "catalina.sh run"   49 seconds ago   Up 48 seconds   0.0.0.0:3355->8080/tcp, :::3355->8080/tcp   laughing_liskov
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker exec -it eca87c7626a1 /bin/bash #9.进入容器

root@eca87c7626a1:/usr/local/tomcat# cd webapps
root@eca87c7626a1:/usr/local/tomcat/webapps# ls  #10.直接进去webapps路径,发现已经有数据了 
ROOT  docs  examples  host-manager  manager

如果你想要保存你当前的状态,可以通过commit,来提交镜像,方便使用,类似于 VM 中的快照!

image-20230327232508887

7、容器数据卷

7.2、什么是容器数据卷

docker的理念回顾:

将应用和运行的环境打包形成容器运行,运行可以伴随着容器,但是我们对于数据的要求,是希望能够

持久化的!

就好比,你安装一个MySQL,结果你把容器删了,就相当于删库跑路了,这TM也太扯了吧!

所以我们希望容器之间有可能可以共享数据,Docker容器产生的数据,如果不通过docker commit 生成

新的镜像,使得数据作为镜像的一部分保存下来,那么当容器删除后,数据自然也就没有了!这样是行

不通的!

为了能保存数据在Docker中我们就可以使用卷!让数据挂载到我们本地!这样数据就不会因为容器删除

而丢失了!

作用:

卷就是目录或者文件,存在一个或者多个容器中,由docker挂载到容器,但不属于联合文件系统,因此

能够绕过 Union File System , 提供一些用于持续存储或共享数据的特性

卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂

载的数据卷

特点:

  1. 数据卷可在容器之间共享或重用数据
  2. 卷中的更改可以直接生效
  3. 数据卷中的更改不会包含在镜像的更新中
  4. 数据卷的生命周期一直持续到没有容器使用它为止

所以:总结一句话: 就是容器的持久化,以及容器间的继承和数据共享!

7.2、使用数据卷

方式一:容器中直接使用命令来添加

挂载

命令
# docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名
测试
# docker run -it -v /home/test:/home centos /bin/bash

查看数据卷是否挂载成功docker inspect 容器id

image-20230328232945629

测试容器和宿主机之间数据共享:可以发现,在容器中,创建的会在宿主机中看到!

image-20230328233259640

测试容器停止退出后,主机修改数据是否会同步!

  1. 停止容器
  2. 在宿主机上修改文件
  3. 启动刚才停止的容器
  4. 然后查看对应的文件,发现数据依旧同步
[root@iZwz9bo1dt9faz5t06j6ijZ home]# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS          PORTS     NAMES
ecbd16b1e5dd   centos    "/bin/bash"   4 minutes ago   Up 12 seconds             infallible_elion

[root@iZwz9bo1dt9faz5t06j6ijZ home]# docker stop ecbd16b1e5dd  #停止容器
ecbd16b1e5dd
[root@iZwz9bo1dt9faz5t06j6ijZ home]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@iZwz9bo1dt9faz5t06j6ijZ test]# vim test.java #修改宿主机文件
[root@iZwz9bo1dt9faz5t06j6ijZ test]# cat test.java   
hello linux update2
[root@iZwz9bo1dt9faz5t06j6ijZ test]# 
[root@iZwz9bo1dt9faz5t06j6ijZ home]# docker start ecbd16b1e5dd  #启动容器
ecbd16b1e5dd
[root@iZwz9bo1dt9faz5t06j6ijZ home]# docker attach ecbd16b1e5dd #进入容器
[root@ecbd16b1e5dd /]# cd /home/
[root@ecbd16b1e5dd home]# ls
test.java
[root@ecbd16b1e5dd home]# cat test.java #发现数据也同步过来了
hello linux update2

实战:使用docker安装mysql

思考:mysql 数据持久化的问题!

  1. 下载镜像

    [root@iZwz9bo1dt9faz5t06j6ijZ home]# docker pull mysql:5.7
    5.7: Pulling from library/mysql
    72a69066d2fe: Pull complete 
    93619dbc5b36: Pull complete 
    99da31dd6142: Pull complete 
    626033c43d70: Pull complete 
    37d5d7efb64e: Pull complete 
    ac563158d721: Pull complete 
    d2ba16033dad: Pull complete 
    0ceb82207cd7: Pull complete 
    37f2405cae96: Pull complete 
    e2482e017e53: Pull complete 
    70deed891d42: Pull complete 
    Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
    Status: Downloaded newer image for mysql:5.7
    docker.io/library/mysql:5.7
    
  2. 启动容器

    [root@iZwz9bo1dt9faz5t06j6ijZ home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
    888477fe44cd759f7b9d06a37f2b8235de89a9eb4cff21f004dd56ca9ac60e6d
    
  3. 阿里云服务器开通3310端口

    image-20230329000018027

  4. sqlyog连接数据库

    image-20230329000057753

  5. 用sqlyog新建数据库

    image-20230328235726344

  6. 查看宿主机目录

    image-20230329000216996

    已同步成功

    就算删除了容器,宿主机的数据也依然存在

docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7命名解释

这个命令使用 Docker 运行 MySQL 5.7 容器,并做出以下配置:

  • -d 表示容器在后台运行(即“守护进程”模式)。
  • -p 3310:3306 将容器内的 MySQL 端口 3306 映射到主机的端口 3310 上,这样你就可以通过主机上的端口 3310 访问 MySQL 服务。
  • -v /home/mysql/conf:/etc/mysql/conf.d 将主机上的目录 /home/mysql/conf 挂载到容器的 /etc/mysql/conf.d 目录中,这样你可以在主机上编辑 MySQL 配置文件,并且它们会在容器内生效。
  • -v /home/mysql/data:/var/lib/mysql 将主机上的目录 /home/mysql/data 挂载到容器的 /var/lib/mysql 目录中,这样你可以在主机上保存 MySQL 数据文件,并且它们会在容器内生效。
  • -e MYSQL_ROOT_PASSWORD=123456 设置 MySQL root 用户的密码为 123456。
  • --name mysql01 指定容器的名称为 mysql01,以便于管理和查找。
  • mysql:5.7 指定使用官方提供的 MySQL 5.7 镜像。

这个命令的作用是在 Docker 中创建并运行一个 MySQL 容器,同时将主机上的目录挂载到容器中,以便于配置和保存数据。

7.3、匿名和具名挂载

# 匿名挂载
# -v的时候只写了容器内的路径看,而没有写容器外的路径
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -d -P --name nginx01 -v /etc/nginx nginx
4395837576fc8fa113c4cdbe3dfbda68636c257124a068c88fc5c33c88581978
# 匿名挂载的缺点,就是不好维护,通常使用命令 docker volume维护
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker volume ls
DRIVER    VOLUME NAME
local     3badcf7f3b6ee71096cbaa41109f036a34d79b010cd75f6a356dc1b66d9a3e1f
local     430769043b687eaa8601a3b80a07193ac7198e50ca254d540c01e5147c5e4ce3
local     b4ae158430f3bc4b4ae1fbaf686fbe2285707c411befff02c068f7501b8e72ae

# 具名挂载
# -v 卷名:容器内路径
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx
915190c2b532a10ce05ed34cc76bd2cf79d56216ad65d4c9d2952306ecfb954e

# 查看挂载的路径
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker volume inspect nginxconfig
[
    {
        "CreatedAt": "2023-03-29T23:32:53+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginxconfig/_data",
        "Name": "nginxconfig",
        "Options": null,
        "Scope": "local"
    }
]
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker volume ls
DRIVER    VOLUME NAME
local     3badcf7f3b6ee71096cbaa41109f036a34d79b010cd75f6a356dc1b66d9a3e1f
local     430769043b687eaa8601a3b80a07193ac7198e50ca254d540c01e5147c5e4ce3
local     b4ae158430f3bc4b4ae1fbaf686fbe2285707c411befff02c068f7501b8e72ae
local     nginxconfig

# 怎么判断挂载的是卷名而不是本机目录名?
# --不是/开始就是卷名,是/开始就是目录名

# 改变文件的读写权限 
# ro: readonly 
# rw: readwrite 
# 指定容器对我们挂载出来的内容的读写权限
# docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:ro nginx
# docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:rw nginx

  • -v 容器内路径 #匿名挂载
  • -v 卷名:容器内路径 #具名挂载
  • -v /宿主机路径:容器内路径 #指定路径挂载

7.4、初始dockerfile

DockerFile 是用来构建Docker镜像的构建文件,是由一些列命令和参数构成的脚本。

我们在这里,先体验下,后面我们会详细讲解 DockerFile !

#1.进入宿主机/home目录,在/home目录下再创建一个目录docker-test-volume,在这个新建目录下新建一个文件dockerfile1
[root@iZwz9bo1dt9faz5t06j6ijZ ~]# cd /home/
[root@iZwz9bo1dt9faz5t06j6ijZ home]# mkdir docker-test-volume
[root@iZwz9bo1dt9faz5t06j6ijZ home]# cd docker-test-volume/
[root@iZwz9bo1dt9faz5t06j6ijZ docker-test-volume]# touch dockerfile1

#2.编辑dockerfile1这个文件
#说明:在编写DockerFile文件中使用 VOLUME 指令来给镜像添加一个或多个数据卷
#出于可移植和分享的考虑,我们之前使用的 -v 主机目录:容器目录 这种方式不能够直接在 DockerFile中实现
#由于宿主机目录是依赖于特定宿主机的,并不能够保证在所有宿主机上都存在这样的特定目录
[root@iZwz9bo1dt9faz5t06j6ijZ docker-test-volume]# vim dockerfile1 
[root@iZwz9bo1dt9faz5t06j6ijZ docker-test-volume]# cat dockerfile1 
FROM centos
VOLUME ["datavolume1","datavolume2"]
CMD echo "-----end-----"
CMD /bin/bash

#3.build后生成镜像,获得一个新镜像 zyy-centos
[root@iZwz9bo1dt9faz5t06j6ijZ docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t zyy-centos .  #注意最后有一个.
[+] Building 0.1s (5/5) FINISHED                                                                                                                                              
 => [internal] load build definition from dockerfile1                                                                                                                    0.1s
 => => transferring dockerfile: 126B                                                                                                                                     0.0s
 => [internal] load .dockerignore                                                                                                                                        0.1s
 => => transferring context: 2B                                                                                                                                          0.0s
 => [internal] load metadata for docker.io/library/centos:latest                                                                                                         0.0s
 => [1/1] FROM docker.io/library/centos                                                                                                                                  0.0s
 => exporting to image                                                                                                                                                   0.0s
 => => exporting layers                                                                                                                                                  0.0s
 => => writing image sha256:e9fd2eb8a2cf3173deb865b3b85bb2cc9314b61ea8c233eb1a789479115239d6                                                                             0.0s
 => => naming to docker.io/library/zyy-centos                                                                                                                            0.0s
[root@iZwz9bo1dt9faz5t06j6ijZ docker-test-volume]# docker images
REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
mytomcat              1.0       0863ecb3b8ee   2 days ago      684MB
nginx                 latest    605c77e624dd   15 months ago   141MB
tomcat                latest    fb5657adc892   15 months ago   680MB
redis                 latest    7614ae9453d1   15 months ago   113MB
mysql                 5.7       c20987f18b13   15 months ago   448MB
zyy-centos            latest    e9fd2eb8a2cf   18 months ago   231MB
centos                latest    5d0da3dc9764   18 months ago   231MB
portainer/portainer   latest    580c0e4e98b0   2 years ago     79.1MB
elasticsearch         7.6.2     f29a1ee41030   3 years ago     791MB
#4.启动容器 发现数据卷目录datavolume1和datavolume2
[root@iZwz9bo1dt9faz5t06j6ijZ docker-test-volume]# docker run -it e9fd2eb8a2cf /bin/bash
[root@b71e1178705e /]# ls
bin  datavolume1  datavolume2  dev  etc  home  lib  lib64  lost+found  media  mnt  opt	proc  root  run  sbin  srv  sys  tmp  usr  var
#5.进入容器,进入datavolume1目录,创建一个container.txt文件,然后退出容器
[root@b71e1178705e /]# cd datavolume1
[root@b71e1178705e datavolume1]# ls
[root@b71e1178705e datavolume1]# touch container.txt
[root@b71e1178705e datavolume1]# ls
container.txt
[root@b71e1178705e datavolume1]# exit
#问题:通过上述步骤,容器内的卷目录地址就已经知道了,但是对应的主机目录地址在哪里呢?
#6.查看容器信息
[root@iZwz9bo1dt9faz5t06j6ijZ docker-test-volume]# docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED              STATUS                      PORTS     NAMES
b71e1178705e   e9fd2eb8a2cf   "/bin/bash"   About a minute ago   Exited (0) 23 seconds ago             pensive_greider
[root@iZwz9bo1dt9faz5t06j6ijZ docker-test-volume]# docker inspect b71e1178705

image-20230330001512920

#8、发现宿主机文件
[root@iZwz9bo1dt9faz5t06j6ijZ docker-test-volume]# cd /var/lib/docker/volumes/b12b129396e69019665a1263d0f126fb4ee1d76db953f8c18365396d466b2ba4/_data
[root@iZwz9bo1dt9faz5t06j6ijZ _data]# ls
container.txt

注意:如果访问出现了 cannot open directory: Permission denied

解决办法:在挂载目录后多加一个 --privileged=true参数即可

7.5、数据卷容器

命名的容器挂载数据卷,其他容器通过挂载这个(父容器)实现数据共享,挂载数据卷的容器,称之为

数据卷容器。

我们使用上一步的镜像:zyy-centos 为模板,运行容器 docker01,docker02,docker03,他

们都会具有容器卷datavolume1和datavolume2

我们来测试下,容器间传递共享

  1. 用zyy-centos镜像,启动容器docker01,在datavolume2目录下新建一个文件from_docker01.txt

    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -it --name docker01 zyy-centos
    
    [root@9d46172d421f /]# ls
    bin  datavolume1  datavolume2  dev  etc  home  lib  lib64  lost+found  media  mnt  opt	proc  root  run  sbin  srv  sys  tmp  usr  var
    [root@9d46172d421f /]# cd datavolume2
    [root@9d46172d421f datavolume2]# ls    
    [root@9d46172d421f datavolume2]# touch from_docker01.txt
    [root@9d46172d421f datavolume2]# ls
    from_docker01.txt
    

    退出不停止容器:ctrl+p+q

    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
    CONTAINER ID   IMAGE        COMMAND                  CREATED              STATUS              PORTS     NAMES
    9d46172d421f   zyy-centos   "/bin/sh -c /bin/bash"   About a minute ago   Up About a minute             docker01
    
  2. 用zyy-centos镜像,启动容器docker02,让docker02继承docker01 --volumes-from

    在datavolume2目录下新建一个文件from_docker02.txt

    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -it --name docker02 --volumes-from docker01 zyy-centos
    [root@943bcccfd0b7 /]# cd datavolume2
    [root@943bcccfd0b7 datavolume2]# ls
    from_docker01.txt
    [root@943bcccfd0b7 datavolume2]# touch from_docker02.txt
    [root@943bcccfd0b7 datavolume2]# ls
    from_docker01.txt  from_docker02.txt
    

    退出不停止容器:ctrl+p+q

  3. 用zyy-centos镜像,启动容器docker02,让docker02继承docker01 --volumes-from

    在datavolume2目录下新建一个文件from_docker03.txt

    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -it --name docker03 --volumes-from docker01 zyy-centos
    [root@82261b446201 /]# cd datavolume2
    [root@82261b446201 datavolume2]# ls
    from_docker01.txt  from_docker02.txt
    [root@82261b446201 datavolume2]# touch from_docker03.txt
    [root@82261b446201 datavolume2]# ls
    from_docker01.txt  from_docker02.txt  from_docker03.txt
    

    退出不停止容器:ctrl+p+q

  4. 进入容器docker01,发现三个文件均可以看到

    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker attach docker01
    [root@9d46172d421f datavolume2]# ls
    from_docker01.txt  from_docker02.txt  from_docker03.txt
    

    退出不停止容器:ctrl+p+q

  5. 停止容器docker01,并删除docker01

    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
    CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS         PORTS     NAMES
    82261b446201   zyy-centos   "/bin/sh -c /bin/bash"   2 minutes ago   Up 2 minutes             docker03
    943bcccfd0b7   zyy-centos   "/bin/sh -c /bin/bash"   3 minutes ago   Up 3 minutes             docker02
    9d46172d421f   zyy-centos   "/bin/sh -c /bin/bash"   6 minutes ago   Up 6 minutes             docker01
    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker stop 9d46172d421f
    9d46172d421f
    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker ps
    CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS         PORTS     NAMES
    82261b446201   zyy-centos   "/bin/sh -c /bin/bash"   2 minutes ago   Up 2 minutes             docker03
    943bcccfd0b7   zyy-centos   "/bin/sh -c /bin/bash"   4 minutes ago   Up 4 minutes             docker02
    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker rm -f docker01
    docker01
    
  6. 进入容器docker02,发现三个文件仍存在

    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker attach docker02
    [root@943bcccfd0b7 datavolume2]# ls
    from_docker01.txt  from_docker02.txt  from_docker03.txt
    

得出结论:

容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。

存储在本机的文件则会一直保留!

8、dockerfile

大家想想,Nginx,tomcat,mysql 这些镜像都是哪里来的?官方能写,我们不能写吗?

我们要研究自己如何做一个镜像,而且我们写的微服务项目以及springboot打包上云部署,Docker就是

最方便的。

微服务打包成镜像,任何装了Docker的地方,都可以下载使用,极其的方便。

流程:开发应用=>DockerFile=>打包为镜像=>上传到仓库(私有仓库,公有仓库)=> 下载镜像 => 启动

运行。

还可以方便移植!

8.1、什么是dockerfile

dockerfifile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。

构建步骤:

  1. 编写DockerFile文件
  2. docker build 构建镜像
  3. docker run

dockerfifile文件我们刚才已经编写过了一次,这里我们继续使用 centos 来看!

https://hub.docker.com/_/centos

image-20230330230817934

image-20230330230954682

8.2、dockerfile构建过程

基础知识

  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. # 表示注释
  4. 每条指令都会创建一个新的镜像层,并对镜像进行提交

流程:

  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器做出修改
  3. 执行类似 docker commit 的操作提交一个新的镜像层
  4. Docker再基于刚提交的镜像运行一个新容器
  5. 执行dockerfifile中的下一条指令直到所有指令都执行完成!

说明:

从应用软件的角度来看,DockerFile,docker镜像与docker容器分别代表软件的三个不同阶段。

  • DockerFile 是软件的原材料 (代码)
  • Docker 镜像则是软件的交付品 (.apk)
  • Docker 容器则是软件的运行状态 (客户下载安装执行)

DockerFile 面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可!

image-20230330231658785

DockerFile:需要定义一个DockerFile,DockerFile定义了进程需要的一切东西。DockerFile涉及的内容

包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进

程和内核进程(当引用进行需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace的权

限控制)等等。

Docker镜像:在DockerFile 定义了一个文件之后,Docker build 时会产生一个Docker镜像,当运行

Docker 镜像时,会真正开始提供服务;

Docker容器:容器是直接提供服务的。

8.3、dockerfile指令

关键字:

FROM        # 基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER  # maintainer 镜像维护者的姓名和邮箱地址
RUN         # 容器构建时需要运行的命令
EXPOSE      # 当前容器对外暴露出的端口
WORKDIR	    # 指定在创建容器后,终端默认登录进来的工作目录,一个落脚点
ENV         # 用来在构建镜像过程中设置环境变量
ADD         # 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY        # 类似ADD,拷贝文件和目录到镜像中!但是是不会自动解压文件,也不能访问网络资源
VLIUME      # 容器数据卷,用于数据保存和持久化工作
CMD         # 指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD指令,但只有最 后一个生效!
ENTRYPOINT  # entrypoint 指定一个容器启动时要运行的命令!和CMD一样 可以追加命令
ONBUILD     # 当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的 ONBUILD被触发

image-20230330232613902

image-20230330232749623

8.4、实战测试

Docker Hub 中99% 的镜像都是通过在base镜像(Scratch)中安装和配置需要的软件构建出来的

image-20230401145006901

自定一个centos镜像

  1. 编写dockerfile

    直接运行centos的官方镜像

    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker run -it centos /bin/bash
    [root@bc7460c8a5fe /]# pwd
    /
    [root@bc7460c8a5fe /]# vim a
    bash: vim: command not found
    [root@bc7460c8a5fe /]# ifconfig 
    bash: ifconfig: command not found
    [root@bc7460c8a5fe /]# 
    

    发现,不支持vim和ifconfig命令,登陆后的默认路径是/

    目的:使我们自己的镜像具备如下:登陆后的默认路径、vim编辑器、查看网络配置ifconfifig支持

    准备编写DockerFlie文件

    [root@iZwz9bo1dt9faz5t06j6ijZ home]# mkdir dockerfile-test
    [root@iZwz9bo1dt9faz5t06j6ijZ home]# ls
    dockerfile-test  docker-test-volume  mysql  test  www  zyy  zyy2  zyydir
    [root@iZwz9bo1dt9faz5t06j6ijZ home]# cd dockerfile-test/
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# ls
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# touch mydockerfile-centos
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# vim mydockerfile-centos 
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# cat mydockerfile-centos 
    FROM centos
    MAINTAINER zyy<123456@qq.com>
    
    ENV MYPATH /usr/local
    WORKDIR $MYPATH
    
    RUN cd /etc/yum.repos.d/
    RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
    RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
    RUN yum -y install vim
    
    RUN yum -y install net-tools
    
    EXPOSE 80
    
    CMD echo $MYPATH
    CMD echo "----end----"
    CMD /bin/bash
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# 
    

    说明:dockerfile中直接RUN yum -y install vim可能会报下面错误

    #0 1.607 Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: No URLs in mirrorlist
    

    说明下面这些,其实就是为了让RUN yum -y install vim可以执行成功

    RUN cd /etc/yum.repos.d/
    RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
    RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
    RUN yum -y install vim
    
  2. 构建

    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker build -f mydockerfile-centos -t mycentos:1.0 .
    [+] Building 17.1s (11/11) FINISHED                                                                                                                                           
     => [internal] load build definition from mydockerfile-centos                                                                                                            0.0s
     => => transferring dockerfile: 449B                                                                                                                                     0.0s
     => [internal] load .dockerignore                                                                                                                                        0.0s
     => => transferring context: 2B                                                                                                                                          0.0s
     => [internal] load metadata for docker.io/library/centos:latest                                                                                                         0.0s
     => [1/7] FROM docker.io/library/centos                                                                                                                                  0.0s
     => CACHED [2/7] WORKDIR /usr/local                                                                                                                                      0.0s
     => [3/7] RUN cd /etc/yum.repos.d/                                                                                                                                       0.3s
     => [4/7] RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*                                                                                              0.3s
     => [5/7] RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*                                                   0.3s
     => [6/7] RUN yum -y install vim                                                                                                                                        13.0s
     => [7/7] RUN yum -y install net-tools                                                                                                                                   2.6s 
     => exporting to image                                                                                                                                                   0.7s 
     => => exporting layers                                                                                                                                                  0.7s 
     => => writing image sha256:f854c594a2cf96e93d0d89e678cbfa8fdfe774e7cc0d45d53a22d80daab8dceb                                                                             0.0s 
     => => naming to docker.io/library/mycentos:1.0                                                                                                                          0.0s 
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker images
    REPOSITORY            TAG       IMAGE ID       CREATED          SIZE                                                                                                          
    mycentos              1.0       f854c594a2cf   32 seconds ago   312MB
    mytomcat              1.0       0863ecb3b8ee   4 days ago       684MB
    nginx                 latest    605c77e624dd   15 months ago    141MB
    tomcat                latest    fb5657adc892   15 months ago    680MB
    redis                 latest    7614ae9453d1   15 months ago    113MB
    mysql                 5.7       c20987f18b13   15 months ago    448MB
    zyy-centos            latest    e9fd2eb8a2cf   18 months ago    231MB
    centos                latest    5d0da3dc9764   18 months ago    231MB
    portainer/portainer   latest    580c0e4e98b0   2 years ago      79.1MB
    elasticsearch         7.6.2     f29a1ee41030   3 years ago      791MB
    

    命令:docker build -f mydockerfile-centos -t mycentos:1.0 .解释:

    这是一个Docker命令,将使用指定的Dockerfile构建一个新的Docker镜像。

    具体来说,该命令的各个部分的含义如下:

    • docker build:使用Docker命令构建新的镜像
    • -f mydockerfile-centos:指定Dockerfile的名称为mydockerfile-centos。默认情况下,Docker使用当前目录下的名为Dockerfile的文件作为Dockerfile,但是在这里我们指定了一个不同的名称。
    • -t mycentos:1.0:指定构建的镜像名称为mycentos,标签为1.0。标签可用于标识同一镜像的不同版本或变体。
    • .:指定上下文路径,即构建过程中所使用的文件路径。这里的.表示使用当前目录作为上下文路径。

    因此,该命令的含义是使用mydockerfile-centos文件作为Dockerfile,将当前目录下的文件作为上下文构建一个名为mycentos、标签为1.0的新Docker镜像。

  3. 运行

    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker run -it mycentos:1.0
    [root@2222adcdac78 local]# pwd
    /usr/local
    [root@2222adcdac78 local]# ifconfig
    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
            ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
            RX packets 8  bytes 656 (656.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            loop  txqueuelen 1000  (Local Loopback)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    [root@2222adcdac78 local]# vim a
    
    [1]+  Stopped                 vim a
    
  4. 列出镜像的变更历史

    docker history 镜像id

    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker history f854c594a2cf
    IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
    f854c594a2cf   10 minutes ago   CMD ["/bin/sh" "-c" "/bin/bash"]                0B        buildkit.dockerfile.v0
    <missing>      10 minutes ago   CMD ["/bin/sh" "-c" "echo \"----end----\""]     0B        buildkit.dockerfile.v0
    <missing>      10 minutes ago   CMD ["/bin/sh" "-c" "echo $MYPATH"]             0B        buildkit.dockerfile.v0
    <missing>      10 minutes ago   EXPOSE map[80/tcp:{}]                           0B        buildkit.dockerfile.v0
    <missing>      10 minutes ago   RUN /bin/sh -c yum -y install net-tools # bu…   14.7MB    buildkit.dockerfile.v0
    <missing>      10 minutes ago   RUN /bin/sh -c yum -y install vim # buildkit    66.3MB    buildkit.dockerfile.v0
    <missing>      10 minutes ago   RUN /bin/sh -c sed -i 's|#baseurl=http://mir…   8.8kB     buildkit.dockerfile.v0
    <missing>      10 minutes ago   RUN /bin/sh -c sed -i 's/mirrorlist/#mirrorl…   8.82kB    buildkit.dockerfile.v0
    <missing>      10 minutes ago   RUN /bin/sh -c cd /etc/yum.repos.d/ # buildk…   0B        buildkit.dockerfile.v0
    <missing>      30 minutes ago   WORKDIR /usr/local                              0B        buildkit.dockerfile.v0
    <missing>      30 minutes ago   ENV MYPATH=/usr/local                           0B        buildkit.dockerfile.v0
    <missing>      30 minutes ago   MAINTAINER zyy<123456@qq.com>                   0B        buildkit.dockerfile.v0
    <missing>      18 months ago    /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
    <missing>      18 months ago    /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
    <missing>      18 months ago    /bin/sh -c #(nop) ADD file:805cb5e15fb6e0bb0…   231MB     
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# 
    
    

CMD和ENTRYPOINT的去呗

我们之前说过,两个命令都是指定一个容器启动时要运行的命令

CMD**:**Dockerfifile 中可以有多个CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数

替换!

ENTRYPOINT**:** docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合!

测试:

  1. 新建两个dockerfile文件:mydockerfile-centos-cmd、mydockerfile-centos-entrypoint,编辑内容如下

    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# vim mydockerfile-centos-cmd
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# vim mydockerfile-centos-entrypoint
    
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# cat mydockerfile-centos-cmd 
    FROM centos
    CMD ["ls","-a"]
    
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# cat mydockerfile-centos-entrypoint 
    FROM centos
    CMD ["ls","-a"]
    
  2. 构建两个新的镜像:mydockerfile-centos-cmd、mydockerfile-centos-entrypoint

    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker build -f mydockerfile-centos-cmd -t mycentos-cmd:1.0 .
    [+] Building 0.1s (5/5) FINISHED                                                                                                                                              
     => [internal] load build definition from mydockerfile-centos-cmd                                                                                                        0.0s
     => => transferring dockerfile: 79B                                                                                                                                      0.0s
     => [internal] load .dockerignore                                                                                                                                        0.0s
     => => transferring context: 2B                                                                                                                                          0.0s
     => [internal] load metadata for docker.io/library/centos:latest                                                                                                         0.0s
     => CACHED [1/1] FROM docker.io/library/centos                                                                                                                           0.0s
     => exporting to image                                                                                                                                                   0.0s
     => => exporting layers                                                                                                                                                  0.0s
     => => writing image sha256:21164980c13c6ef0c96c355528cf73f4b9a77b257abba4336afb88538296865f                                                                             0.0s
     => => naming to docker.io/library/mycentos-cmd:1.0                                                                                                                      0.0s
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker build -f mydockerfile-centos-entrypoint -t mycentos-entrypoint:1.0 .
    [+] Building 0.0s (5/5) FINISHED                                                                                                                                              
     => [internal] load build definition from mydockerfile-centos-entrypoint                                                                                                 0.0s
     => => transferring dockerfile: 93B                                                                                                                                      0.0s
     => [internal] load .dockerignore                                                                                                                                        0.0s
     => => transferring context: 2B                                                                                                                                          0.0s
     => [internal] load metadata for docker.io/library/centos:latest                                                                                                         0.0s
     => CACHED [1/1] FROM docker.io/library/centos                                                                                                                           0.0s
     => exporting to image                                                                                                                                                   0.0s
     => => exporting layers                                                                                                                                                  0.0s
     => => writing image sha256:9f35f7608f6b68060dace86e7bbfd93750ff80067e358c829c227c97789b8579                                                                             0.0s
     => => naming to docker.io/library/mycentos-entrypoint:1.0                                                                                                               0.0s
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker images
    REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
    mycentos-entrypoint   1.0       9f35f7608f6b   18 months ago    231MB
    mycentos-cmd          1.0       21164980c13c   18 months ago    231MB
    
  3. 运行mycentos-cmd

    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker run 21164980c13c
    .
    ..
    .dockerenv
    bin
    dev
    etc
    home
    lib
    lib64
    lost+found
    media
    mnt
    opt
    proc
    root
    run
    sbin
    srv
    sys
    tmp
    usr
    var
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker run 21164980c13c -l
    docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "-l": executable file not found in $PATH: unknown.
    

    我们希望-l 列表展示信息,发现报错

    之前我们说过,跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。

    因此这里的 -l 替换了原来的 CMD,而不是添加在原来的 ls -a 后面。而 -l 根本不是命令,所

    以自然找不到。

    那么如果我们希望加入 -l 这参数,我们就必须重新完整的输入这个命令:

    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker run 21164980c13c ls -al
    total 56
    drwxr-xr-x   1 root root 4096 Apr  1 08:33 .
    drwxr-xr-x   1 root root 4096 Apr  1 08:33 ..
    -rwxr-xr-x   1 root root    0 Apr  1 08:33 .dockerenv
    lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
    drwxr-xr-x   5 root root  340 Apr  1 08:33 dev
    drwxr-xr-x   1 root root 4096 Apr  1 08:33 etc
    drwxr-xr-x   2 root root 4096 Nov  3  2020 home
    lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -> usr/lib
    lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -> usr/lib64
    drwx------   2 root root 4096 Sep 15  2021 lost+found
    drwxr-xr-x   2 root root 4096 Nov  3  2020 media
    drwxr-xr-x   2 root root 4096 Nov  3  2020 mnt
    drwxr-xr-x   2 root root 4096 Nov  3  2020 opt
    dr-xr-xr-x 108 root root    0 Apr  1 08:33 proc
    dr-xr-x---   2 root root 4096 Sep 15  2021 root
    drwxr-xr-x  11 root root 4096 Sep 15  2021 run
    lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -> usr/sbin
    drwxr-xr-x   2 root root 4096 Nov  3  2020 srv
    dr-xr-xr-x  13 root root    0 Apr  1 08:25 sys
    drwxrwxrwt   7 root root 4096 Sep 15  2021 tmp
    drwxr-xr-x  12 root root 4096 Sep 15  2021 usr
    drwxr-xr-x  20 root root 4096 Sep 15  2021 var
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# 
    
  4. 运行mycentos-entrypoint

    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker run 9f35f7608f6b
    .
    ..
    .dockerenv
    bin
    dev
    etc
    home
    lib
    lib64
    lost+found
    media
    mnt
    opt
    proc
    root
    run
    sbin
    srv
    sys
    tmp
    usr
    var
    [root@iZwz9bo1dt9faz5t06j6ijZ dockerfile-test]# docker run 9f35f7608f6b -l
    total 56
    drwxr-xr-x   1 root root 4096 Apr  1 08:25 .
    drwxr-xr-x   1 root root 4096 Apr  1 08:25 ..
    -rwxr-xr-x   1 root root    0 Apr  1 08:25 .dockerenv
    lrwxrwxrwx   1 root root    7 Nov  3  2020 bin -> usr/bin
    drwxr-xr-x   5 root root  340 Apr  1 08:25 dev
    drwxr-xr-x   1 root root 4096 Apr  1 08:25 etc
    drwxr-xr-x   2 root root 4096 Nov  3  2020 home
    lrwxrwxrwx   1 root root    7 Nov  3  2020 lib -> usr/lib
    lrwxrwxrwx   1 root root    9 Nov  3  2020 lib64 -> usr/lib64
    drwx------   2 root root 4096 Sep 15  2021 lost+found
    drwxr-xr-x   2 root root 4096 Nov  3  2020 media
    drwxr-xr-x   2 root root 4096 Nov  3  2020 mnt
    drwxr-xr-x   2 root root 4096 Nov  3  2020 opt
    dr-xr-xr-x 108 root root    0 Apr  1 08:25 proc
    dr-xr-x---   2 root root 4096 Sep 15  2021 root
    drwxr-xr-x  11 root root 4096 Sep 15  2021 run
    lrwxrwxrwx   1 root root    8 Nov  3  2020 sbin -> usr/sbin
    drwxr-xr-x   2 root root 4096 Nov  3  2020 srv
    dr-xr-xr-x  13 root root    0 Apr  1 08:25 sys
    drwxrwxrwt   7 root root 4096 Sep 15  2021 tmp
    drwxr-xr-x  12 root root 4096 Sep 15  2021 usr
    drwxr-xr-x  20 root root 4096 Sep 15  2021 var
    

    测试-l参数,发现可以直接使用,这里就是一种追加,我们可以明显的知道 CMD 和

    ENTRYPOINT 的区别了

自定义镜像tomcat

  1. 新建一个路径,并准备好tomcat和jdk的压缩包(官网下载后本地上传到服务器),并新建一个read.txt

    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# pwd
    /home/zyydir/build/tomcat
    
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# touch read.txt
    
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# ll
    -rw-r--r-- 1 root root  11625808 Apr  2 10:38 apache-tomcat-9.0.73.tar.gz
    -rw-r--r-- 1 root root 194042837 Apr  2 10:51 jdk-8u202-linux-x64.tar.gz
    -rw-r--r-- 1 root root         0 Apr  2 10:52 read.txt
    
  2. 新建一个Dockfile文件,并编辑

    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# vim Dockerfile 
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# cat Dockerfile 
    FROM centos
    
    MAINTAINER zyy<123456@qq.com>
    
    COPY read.txt /usr/local/read.txt
    
    ADD apache-tomcat-9.0.73.tar.gz /usr/local/
    ADD jdk-8u202-linux-x64.tar.gz /usr/local/
    
    RUN cd /etc/yum.repos.d/
    RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
    RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
    RUN yum -y install vim
    
    ENV MYPATH /usr/local
    
    WORKDIR $MYPATH
    
    ENV JAVA_HOME /usr/local/jdk1.8.0_202
    ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
    ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.73
    ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.73
    ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
    
    EXPOSE 8080
    
    CMD /usr/local/apache-tomcat-9.0.73/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.73/bin/logs/catalina.out
    
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# ll
    total 200856
    -rw-r--r-- 1 root root  11625808 Apr  2 10:38 apache-tomcat-9.0.73.tar.gz
    -rw-r--r-- 1 root root       828 Apr  2 10:54 Dockerfile
    -rw-r--r-- 1 root root 194042837 Apr  2 10:51 jdk-8u202-linux-x64.tar.gz
    -rw-r--r-- 1 root root         0 Apr  2 10:52 read.txt
    
  3. 构建镜像

    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker build -t diytomcat .
    [+] Building 29.0s (14/14) FINISHED                                                                                                                                           
     => [internal] load build definition from Dockerfile                                                                                                                     0.1s
     => => transferring dockerfile: 867B                                                                                                                                     0.0s
     => [internal] load .dockerignore                                                                                                                                        0.1s
     => => transferring context: 2B                                                                                                                                          0.0s
     => [internal] load metadata for docker.io/library/centos:latest                                                                                                         0.0s
     => [1/9] FROM docker.io/library/centos                                                                                                                                  0.0s
     => [internal] load build context                                                                                                                                        2.8s
     => => transferring context: 205.72MB                                                                                                                                    2.8s
     => CACHED [2/9] COPY read.txt /usr/local/read.txt                                                                                                                       0.0s
     => CACHED [3/9] ADD apache-tomcat-9.0.73.tar.gz /usr/local/                                                                                                             0.0s
     => [4/9] ADD jdk-8u202-linux-x64.tar.gz /usr/local/                                                                                                                     6.8s
     => [5/9] RUN cd /etc/yum.repos.d/                                                                                                                                       0.5s
     => [6/9] RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*                                                                                              0.3s
     => [7/9] RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*                                                   0.3s
     => [8/9] RUN yum -y install vim                                                                                                                                        13.8s
     => [9/9] WORKDIR /usr/local                                                                                                                                             0.1s
     => exporting to image                                                                                                                                                   4.3s 
     => => exporting layers                                                                                                                                                  4.3s 
     => => writing image sha256:283a8bc25a764cd5d2614b4a10a0660f330de15c1a0d4f89eeb0efc44bca3ce1                                                                             0.0s 
     => => naming to docker.io/library/diytomcat                                                                                                                             0.0s 
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker images diytomcat
    REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
    diytomcat    latest    283a8bc25a76   42 seconds ago   716MB
    
  4. 启动容器

    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker run -d -p 9090:8080 --name mydiytomcat -v /home/zyydir/build/tomcat/test:/usr/local/apache-tomcat-9.0.73/webapps/test -v /home/zyydir/build/tomcat/logs:/usr/local/apache-tomcat-9.0.73/logs diytomcat
    7794a2558b7d746b2579b48e4f6037fcca3ab7d43ae7ecab9bee3afa0984e4f2
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker ps
    CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS         PORTS                                       NAMES
    7794a2558b7d   diytomcat   "/bin/sh -c '/usr/lo…"   10 seconds ago   Up 9 seconds   0.0.0.0:9090->8080/tcp, :::9090->8080/tcp   mydiytomcat
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# ls
    apache-tomcat-9.0.73.tar.gz  Dockerfile  jdk-8u202-linux-x64.tar.gz  logs  read.txt  test
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# cd logs/
    [root@iZwz9bo1dt9faz5t06j6ijZ logs]# ls
    catalina.2023-04-02.log  catalina.out  host-manager.2023-04-02.log  localhost.2023-04-02.log  localhost_access_log.2023-04-02.txt  manager.2023-04-02.log
    [root@iZwz9bo1dt9faz5t06j6ijZ logs]# cd ..
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# ls
    apache-tomcat-9.0.73.tar.gz  Dockerfile  jdk-8u202-linux-x64.tar.gz  logs  read.txt  test
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# cd test/
    [root@iZwz9bo1dt9faz5t06j6ijZ test]# ls
    
  5. 开启阿里云9090端口

    image-20230402112308354

  6. 访问

    [root@iZwz9bo1dt9faz5t06j6ijZ test]# curl localhost:9090
    

    image-20230402112359922

    image-20230402112411977

  7. 结合前面学习的容器卷将测试的web服务test发布

    WEB-INF下新建一个web.xml

    [root@iZwz9bo1dt9faz5t06j6ijZ test]# mkdir WEB-INF
    [root@iZwz9bo1dt9faz5t06j6ijZ test]# cd WEB-INF/
    [root@iZwz9bo1dt9faz5t06j6ijZ WEB-INF]# ls
    [root@iZwz9bo1dt9faz5t06j6ijZ WEB-INF]# vim web.xml
    

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns="http://java.sun.com/xml/ns/javaee"
    	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    	id="WebApp_ID" version="2.5">
    
    	<display-name>test</display-name>
    
    </web-app>
    

    在test下新建一个a.jsp

    [root@iZwz9bo1dt9faz5t06j6ijZ WEB-INF]# cd ..
    [root@iZwz9bo1dt9faz5t06j6ijZ test]# vim a.jsp
    

    a.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    	<head>
    		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    		<title>hello,kuangshen</title>
    	</head>
    	<body>
    		-----------welcome------------
    		<%=" my docker tomcat "%>
    		<br>
    		<br>
    		<% System.out.println("-------my docker tomcat-------");%>
    	</body>
    </html>
    
  8. 直接访问这个a.jsp

    [root@iZwz9bo1dt9faz5t06j6ijZ test]# curl localhost:9090/test/a.jsp
    

    image-20230402112835568

    image-20230402112855133

    还可以查看catalina.out,可以看到服务启动和我们打印的日志

    image-20230402113009043

8.5、发布镜像

DockerHub

  1. 注册dockerhub https://hub.docker.com/,注册一个账号

    image-20230402135716924

  2. 登录

    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker login -u zyy1234
    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/#credentials-store
    
    Login Succeeded
    
  3. 修改一下tag

    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker images
    REPOSITORY            TAG       IMAGE ID       CREATED             SIZE
    diytomcat             latest    283a8bc25a76   About an hour ago   716MB
    mytomcat              1.0       0863ecb3b8ee   5 days ago          684MB
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker tag 283a8bc25a76 diytomcat:1.0
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker images
    REPOSITORY            TAG       IMAGE ID       CREATED             SIZE
    diytomcat             1.0       283a8bc25a76   About an hour ago   716MB
    diytomcat             latest    283a8bc25a76   About an hour ago   716MB
    mytomcat              1.0       0863ecb3b8ee   5 days ago          684MB
    
  4. push,发现报错

    问题:本地镜像名无帐号信息,解决加 tag即可

    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker push diytomcat:1.0
    The push refers to repository [docker.io/library/diytomcat]
    5f70bf18a086: Preparing 
    a75326eea74e: Preparing 
    15c92469e90d: Preparing 
    81cdfe5060d2: Preparing 
    7f49a14bf706: Preparing 
    9e121fd97bcc: Waiting 
    43ca038d9c37: Waiting 
    74ddd0ec08fa: Waiting 
    denied: requested access to the resource is denied
    
  5. 修复问题,修改tag

    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker tag 283a8bc25a76 zyy1234/diytomcat:1.0
    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker images
    REPOSITORY            TAG       IMAGE ID       CREATED             SIZE
    diytomcat             1.0       283a8bc25a76   About an hour ago   716MB
    diytomcat             latest    283a8bc25a76   About an hour ago   716MB
    zyy1234/diytomcat     1.0       283a8bc25a76   About an hour ago   716MB
    mytomcat              1.0       0863ecb3b8ee   5 days ago          684MB
    
  6. push

    [root@iZwz9bo1dt9faz5t06j6ijZ tomcat]# docker push zyy1234/diytomcat:1.0
    The push refers to repository [docker.io/zyy1234/diytomcat]
    5f70bf18a086: Pushed 
    a75326eea74e: Pushing [================================>                  ]  42.51MB/66.29MB
    15c92469e90d: Pushed 
    81cdfe5060d2: Pushed 
    7f49a14bf706: Pushing [=======>                                           ]  58.15MB/402.5MB
    9e121fd97bcc: Pushing [===============================>                   ]  10.27MB/16.17MB
    43ca038d9c37: Pushed 
    74ddd0ec08fa: Pushing [================>                                  ]  74.42MB/231.3MB
    

阿里云镜像服务

  1. 登录阿里云,找到容器镜像服务

    image-20230402145212628

  2. 创建个人实例(已存在可以忽略)

    image-20230402145259970

  3. 进入个人实例,创建命名空间

    image-20230402145338775

  4. 镜像仓库中,创建镜像仓库

    image-20230402145430943

    image-20230402145453913

    image-20230402145515126

  5. 打开上面新建的仓库,这里有具体push的步骤

    image-20230402145604573

  6. 操作一下

    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker login --username=大垚大摆 registry.cn-shenzhen.aliyuncs.com
    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/#credentials-store
    
    Login Succeeded
    
    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker tag 283a8bc25a76 registry.cn-shenzhen.aliyuncs.com/zyy1234/zyy-repository:1.0
    [root@iZwz9bo1dt9faz5t06j6ijZ ~]# docker push registry.cn-shenzhen.aliyuncs.com/zyy1234/zyy-repository:1.0
    

    image-20230402145922339

8.6、总结

image-20230402151003526

9、docker网络

9.1、理解docker0

准备工作:清空所有的容器,清空所有的镜像

docker rm -f $(docker ps -a -q)    # 删除所有容器 
docker rmi -f $(docker images -qa) # 删除全部镜像

先做个测试--现象

  1. 制作一个可以使用ip addr和ping命令的镜像(已经支持的,可以忽略这个步骤)

    下载tomcat原生镜像并启动tomcat容器tomcat01

    [root@iZwz9efdd2ukk4oauustczZ zyydir]# docker run -d -P --name tomcat01 tomcat
    

    查看容器tomcat01内部的ip地址,发现报错如下:

    [root@iZwz9efdd2ukk4oauustczZ zyydir]# docker exec -it tomcat01 ip addr
    OCI runtime exec failed: exec failed: unable to start container process: exec: "ip": executable file not found in $PATH: unknown
    [root@iZwz9efdd2ukk4oauustczZ zyydir]# docker exec -it tomcat01 /bin/bash
    root@de8e3961c49d:/usr/local/tomcat# ip addr
    bash: ip: command not found
    

    进入容器执行命令,即可解决

    apt update && apt install -y iproute2
    

    在容器tomcat01ping一下,发现报错如下

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat02 ping 172.17.0.2
    OCI runtime exec failed: exec failed: unable to start container process: exec: "ping": executable file not found in $PATH: unknown
    
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it 3ff487ee3a74 /bin/bash
    root@3ff487ee3a74:/usr/local/tomcat# ping 172.17.0.2
    bash: ping: command not found
    

    进入容器执行命令,即可解决

    apt-get update && apt-get install -y iputils-ping
    

    容器执行了上面两个命令后,就可以正常使用ip addr和ping这两个命令了,然后我们把容器commit一下,就有个一个新的镜像了

  2. 查看一下主机本地的ip 地址ip addr

    image-20230406222505441

    • lo 本机回环地址

    • eth0 阿里云的私有ip

    • docker0 docker网桥

  3. 启动容器tomcat01,查看一下容器的ip,然后再查一下主机本地ip

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker run -d -P --name tomcat01 mytomcat1.1
    f11117b10415507d70842a0f867e76fc90fcd9eeec3c839026dfd6deb3f04bf9
    
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat01 ip addr
    

    image-20230406223615323

    [root@iZwz9efdd2ukk4oauustczZ ~]# ip addr
    

    docker会给每个容器都分配一个ip

    image-20230406223104018

  4. 再启动容器tomcat02,查看一下容器的ip,然后再查一下主机本地ip

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker run -d -P --name tomcat02 mytomcat1.1
    242682cc4bd9c20fe6e177e7c6f4bb5d64af5432ba553500d83546149cef6903
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat02 ip addr
    

    image-20230406223751931

    [root@iZwz9efdd2ukk4oauustczZ ~]# ip addr
    

    image-20230406223402871

  5. tomcat01中是否可以ping通tomcat02的ip?

    先进入tomcat01容器

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it f11117b10415 /bin/bash 
    root@f11117b10415:/usr/local/tomcat# ping 172.17.0.3
    

    image-20230406224335589

    是可以通的

原理

  1. 每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。这是个桥接网卡,使用了veth-pair

    技术!

  2. 每启动一个容器,linux主机就会多了一个虚拟网卡。

    veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连着。

    正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备!

image-20230406225244519

结论:tomcat1和tomcat2共用一个路由器。是的,他们使用的一个,就是docker0。任何一个容器启动

默认都是docker0网络。

docker默认会给容器分配一个可用ip。

小结

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据

Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网

关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接

通信。

image-20230406225916301

Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并

让他们彼此联通(这样一对接口叫veth pair);

Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中

进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容

器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。

9.2、--link

思考一个场景,我们编写一个微服务,数据库连接地址原来是使用ip的,如果ip变化就不行了,那我们

能不能使用服务名访问呢?

jdbc:mysql://mysql:3306,这样的话哪怕mysql重启,我们也不需要修改配置了!docker提供了 --link

的操作!

# 直接用tomcat01 ping tomcat02 发现不行
[root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known
# 我们再启动一个tomcat03 并且启动的时候连接tomcat02
[root@iZwz9efdd2ukk4oauustczZ ~]# docker run -d -P --name tomcat03 --link tomcat02 mytomcat1.1
4725505179ab997453583620c1fc37e3d0ebf80ec3ffe5dd80fb16f656730c46
# 这个时候我们就可以用tomcat03 ping tomcat02了
[root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.133 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.091 ms
^Z64 bytes from tomcat02 (172.17.0.3): icmp_seq=3 ttl=64 time=0.084 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=4 ttl=64 time=0.074 ms

# 再次测试,用tomcat02 ping tomcat03 发现不行  反向ping不通
[root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
# 再次测试,用tomcat03 ping tomcat01 发现也不行 没有连接也不行
[root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat03 ping tomcat01
ping: tomcat01: Name or service not known

思考,这个原理是什么呢?我们进入tomcat03中查看下host配置文件

[root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	tomcat02 242682cc4bd9  # 发现tomcat2直接被写在这里
172.17.0.4	4725505179ab
# 所以这里其实就是配置了一个 hosts 地址而已!
# 原因:--link的时候,直接把需要link的主机的域名和ip直接配置到了hosts文件中了。

--link早都过时了,我们不推荐使用!我们可以使用自定义网络的方式

9.3、自定义网络

基本命令查看

命令如下:

[root@iZwz9efdd2ukk4oauustczZ ~]# docker network --help

Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.

查看所有网络

[root@iZwz9efdd2ukk4oauustczZ ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
ba1f42400a65   bridge    bridge    local
8b1a4e90220e   host      host      local
769e58794dd8   none      null      local
[root@iZwz9efdd2ukk4oauustczZ ~]# 

所有网络模式

网络模式 配置 说明
bridge模式 --net=bridge 默认值,在Docker网桥docker0上为容器创建新的网络栈
none模式 --net=none 不配置网络,用户可以稍后进入容器,自行配置
container模式 --net=container:name/id 容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Network namespace
host模式 --net=host 容器和宿主机共享Network namespace
用户自定义模式 --net=自定义网络 用户自己使用network相关命令定义网络,创建容器的时候可以指定为自己定义的网络

查看一个具体的网络的详情

[root@iZwz9efdd2ukk4oauustczZ ~]# docker network inspect 4725505179ab
[]
Error response from daemon: network 4725505179ab not found
[root@iZwz9efdd2ukk4oauustczZ ~]# docker network inspect ba1f42400a65
[
    {
        "Name": "bridge",
        "Id": "ba1f42400a655aeee8c305cbfd9e05c65bda93d70728a3d9334b6eab242fd9b4",
        "Created": "2023-04-05T00:31:36.123901723+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    // 默认docker0是管理这个子网范围内的
                    // docker0网络默认可以支持创建6万多个容器ip不重复 下面有解释为啥是6w多个
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "242682cc4bd9c20fe6e177e7c6f4bb5d64af5432ba553500d83546149cef6903": {
                "Name": "tomcat02",
                "EndpointID": "02c77bc16ed07d9626d6c3d0d6fc80ebf20573d624fed5418642064635698f1f",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "4725505179ab997453583620c1fc37e3d0ebf80ec3ffe5dd80fb16f656730c46": {
                "Name": "tomcat03",
                "EndpointID": "702d95da29bd806dede27c5d05fdf580398dbd9855a056fcc0de19737c1ab35f",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            },
            "f11117b10415507d70842a0f867e76fc90fcd9eeec3c839026dfd6deb3f04bf9": {
                "Name": "tomcat01",
                "EndpointID": "075900c171e9f982d38f6ccb4f069565c2e33402f62b28aaca8ac184c6b1838b",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

拓展:

  • 172.17.0.0/16 是一个 CIDR 地址,其中 /16 表示子网掩码的位数,即 255.255.0.0。这个地址范围内的 IP 地址数量是 2^16 - 2 = 65534。其中,2^16 表示该地址范围内的 IP 地址总数,而减去 2 是因为该地址范围内的第一个 IP 地址是网络地址,最后一个 IP 地址是广播地址,不能使用
  • 172.17.0.0/24 是一个 CIDR 地址,其中 /24 表示子网掩码的位数,即 255.255.255.0。这个地址范围内的 IP 地址数量是 2^8 - 2 = 254。其中,2^8 表示该地址范围内的 IP 地址总数,而减去 2 是因为该地址范围内的第一个 IP 地址是网络地址,最后一个 IP 地址是广播地址,不能使用。

自定义网卡

  1. 删除原来的所有的容器(这样干净一点)

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker rm -f $(docker ps -aq)
    4725505179ab
    242682cc4bd9
    f11117b10415
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker ps -a
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    

    这样网络就恢复最初的样子了

    [root@iZwz9efdd2ukk4oauustczZ ~]# ip addr
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 00:16:3e:06:ad:3e brd ff:ff:ff:ff:ff:ff
        inet 172.19.41.97/18 brd 172.19.63.255 scope global dynamic eth0
           valid_lft 315057909sec preferred_lft 315057909sec
    3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
        link/ether 02:42:b9:cf:20:fb brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
           valid_lft forever preferred_lft forever
    
  2. 自定义网络

    查看命令使用

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker network
    
    Usage:  docker network COMMAND
    
    Manage networks
    
    Commands:
      connect     Connect a container to a network
      create      Create a network
      disconnect  Disconnect a container from a network
      inspect     Display detailed information on one or more networks
      ls          List networks
      prune       Remove all unused networks
      rm          Remove one or more networks
    
    Run 'docker network COMMAND --help' for more information on a command.
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker network create --help
    
    Usage:  docker network create [OPTIONS] NETWORK
    
    Create a network
    
    Options:
          --attachable           Enable manual container attachment
          --aux-address map      Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
          --config-from string   The network from which to copy the configuration
          --config-only          Create a configuration only network
      -d, --driver string        Driver to manage the Network (default "bridge")
          --gateway strings      IPv4 or IPv6 Gateway for the master subnet
          --ingress              Create swarm routing-mesh network
          --internal             Restrict external access to the network
          --ip-range strings     Allocate container ip from a sub-range
          --ipam-driver string   IP Address Management Driver (default "default")
          --ipam-opt map         Set IPAM driver specific options (default map[])
          --ipv6                 Enable IPv6 networking
          --label list           Set metadata on a network
      -o, --opt map              Set driver specific options (default map[])
          --scope string         Control the network's scope
          --subnet strings       Subnet in CIDR format that represents a network segment
    
    # 自定义一个网络
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker network create --driver bridge --subnet 192.17.0.0/16 --gateway 192.17.0.1 mynet
    b39a1b5892e34105b5cfc108e25f3e811248362334896adf1430c0c2c9a06b56
    # 确认已经创建好
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker network ls
    NETWORK ID     NAME      DRIVER    SCOPE
    ba1f42400a65   bridge    bridge    local
    8b1a4e90220e   host      host      local
    b39a1b5892e3   mynet     bridge    local
    769e58794dd8   none      null      local
    # 查看一下自定义网络信息
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker network inspect mynet
    [
        {
            "Name": "mynet",
            "Id": "b39a1b5892e34105b5cfc108e25f3e811248362334896adf1430c0c2c9a06b56",
            "Created": "2023-04-08T12:19:13.011744556+08:00",
            "Scope": "local",
            "Driver": "bridge",
            "EnableIPv6": false,
            "IPAM": {
                "Driver": "default",
                "Options": {},
                "Config": [
                    {
                        "Subnet": "192.17.0.0/16",
                        "Gateway": "192.17.0.1"
                    }
                ]
            },
            "Internal": false,
            "Attachable": false,
            "Ingress": false,
            "ConfigFrom": {
                "Network": ""
            },
            "ConfigOnly": false,
            "Containers": {},
            "Options": {},
            "Labels": {}
        }
    ]
    
  3. 基于自定义网络启动2个容器

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker run -d -P --name tomcat-net-1 --net mynet mytomcat1.1
    d882ec326550e16e0196c9e3257b0a87ce185d55f35918b0211c0e43264a72e7
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker run -d -P --name tomcat-net-2 --net mynet mytomcat1.1
    43349138cfa25ef4d2fda31454dae9d783b3b029ad8eb10ebc1ddda8e9776a22
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker ps
    CONTAINER ID   IMAGE         COMMAND             CREATED          STATUS          PORTS                     NAMES
    43349138cfa2   mytomcat1.1   "catalina.sh run"   14 seconds ago   Up 12 seconds   0.0.0.0:32779->8080/tcp   tomcat-net-2
    d882ec326550   mytomcat1.1   "catalina.sh run"   19 seconds ago   Up 18 seconds   0.0.0.0:32778->8080/tcp   tomcat-net-1
    
  4. 再次查看一下网络

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker network inspect mynet
    [
        {
            //....
            //这里多了2个容器的网络信息
            "Containers": {
                "43349138cfa25ef4d2fda31454dae9d783b3b029ad8eb10ebc1ddda8e9776a22": {
                    "Name": "tomcat-net-2",
                    "EndpointID": "f508128854ce1ebb272db8c6c7b32ad5235ca6e79f262a17895a4ec43747b792",
                    "MacAddress": "02:42:c0:11:00:03",
                    "IPv4Address": "192.17.0.3/16",
                    "IPv6Address": ""
                },
                "d882ec326550e16e0196c9e3257b0a87ce185d55f35918b0211c0e43264a72e7": {
                    "Name": "tomcat-net-1",
                    "EndpointID": "a754bf88af0ceedd92a906e0e705403d940d6b5a3689c0f98ef368699a41352d",
                    "MacAddress": "02:42:c0:11:00:02",
                    "IPv4Address": "192.17.0.2/16",
                    "IPv6Address": ""
                }
            },
            "Options": {},
            "Labels": {}
        }
    ]
    
  5. 测试网络连通性

    # 直接tomcat-net-1 ping tomcat-net-2的ip  可以
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat-net-1 ping 192.17.0.3
    PING 192.17.0.3 (192.17.0.3) 56(84) bytes of data.
    64 bytes from 192.17.0.3: icmp_seq=1 ttl=64 time=0.107 ms
    64 bytes from 192.17.0.3: icmp_seq=2 ttl=64 time=0.087 ms
    64 bytes from 192.17.0.3: icmp_seq=3 ttl=64 time=0.081 ms
    64 bytes from 192.17.0.3: icmp_seq=4 ttl=64 time=0.074 ms
    64 bytes from 192.17.0.3: icmp_seq=5 ttl=64 time=0.096 ms
    64 bytes from 192.17.0.3: icmp_seq=6 ttl=64 time=0.076 ms
    
    # 直接tomcat-net-1 ping tomcat-net-2的容器名  也可以
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat-net-1 ping tomcat-net-2
    PING tomcat-net-2 (192.17.0.3) 56(84) bytes of data.
    64 bytes from tomcat-net-2.mynet (192.17.0.3): icmp_seq=1 ttl=64 time=0.079 ms
    64 bytes from tomcat-net-2.mynet (192.17.0.3): icmp_seq=2 ttl=64 time=0.075 ms
    64 bytes from tomcat-net-2.mynet (192.17.0.3): icmp_seq=3 ttl=64 time=0.075 ms
    64 bytes from tomcat-net-2.mynet (192.17.0.3): icmp_seq=4 ttl=64 time=0.086 ms
    64 bytes from tomcat-net-2.mynet (192.17.0.3): icmp_seq=5 ttl=64 time=0.081 ms
    64 bytes from tomcat-net-2.mynet (192.17.0.3): icmp_seq=6 ttl=64 time=0.114 ms
    

    发现,我们自定义的网络docker都已经帮我们维护好了对应的关系

    所以我们平时都可以这样使用网络,不使用--link效果一样,所有东西实时维护好,直接域名 ping

    通。

9.4、网络连通

  1. 启动两个容器(默认,基于docker0的网络)

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker run -d -P --name tomcat-1 mytomcat1.1 
    a4e6ece319c91eb8d67d646411f9809ffa570b8f8ff5fb020a19d813fc72952d
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker run -d -P --name tomcat-2 mytomcat1.1 
    dae040020ecc87370713a87e0f68c6d5e6e3d3df2d29e887f251f8da7766e836
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker ps
    CONTAINER ID   IMAGE         COMMAND             CREATED         STATUS         PORTS                     NAMES
    dae040020ecc   mytomcat1.1   "catalina.sh run"   4 seconds ago   Up 4 seconds   0.0.0.0:32781->8080/tcp   tomcat-2
    a4e6ece319c9   mytomcat1.1   "catalina.sh run"   8 seconds ago   Up 8 seconds   0.0.0.0:32780->8080/tcp   tomcat-1
    43349138cfa2   mytomcat1.1   "catalina.sh run"   3 hours ago     Up 3 hours     0.0.0.0:32779->8080/tcp   tomcat-net-2
    d882ec326550   mytomcat1.1   "catalina.sh run"   3 hours ago     Up 3 hours     0.0.0.0:32778->8080/tcp   tomcat-net-1
    

    image-20230408151335830

    docker0和自定义网络肯定不通,我们使用自定义网络的好处就是网络隔离:

    那关键的问题来了,如何让 tomcat-1 访问 tomcat-net-1?

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat-1 ping tomcat-net-1
    ping: tomcat-net-1: Name or service not known
    
  2. 使用network connect 命令连接

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker network connect mynet tomcat-1
    
  3. 再次验证,通了

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat-1 ping tomcat-net-1
    PING tomcat-net-1 (192.17.0.2) 56(84) bytes of data.
    64 bytes from tomcat-net-1.mynet (192.17.0.2): icmp_seq=1 ttl=64 time=0.098 ms
    64 bytes from tomcat-net-1.mynet (192.17.0.2): icmp_seq=2 ttl=64 time=0.081 ms
    64 bytes from tomcat-net-1.mynet (192.17.0.2): icmp_seq=3 ttl=64 time=0.073 ms
    64 bytes from tomcat-net-1.mynet (192.17.0.2): icmp_seq=4 ttl=64 time=0.073 ms
    64 bytes from tomcat-net-1.mynet (192.17.0.2): icmp_seq=5 ttl=64 time=0.078 ms
    64 bytes from tomcat-net-1.mynet (192.17.0.2): icmp_seq=6 ttl=64 time=0.085 ms
    64 bytes from tomcat-net-1.mynet (192.17.0.2): icmp_seq=7 ttl=64 time=0.075 ms
    64 bytes from tomcat-net-1.mynet (192.17.0.2): icmp_seq=8 ttl=64 time=0.086 ms
    64 bytes from tomcat-net-1.mynet (192.17.0.2): icmp_seq=9 ttl=64 time=0.081 ms
    
    # tomcat-net-1 ping tomcat-1也是通的
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat-net-1 ping tomcat-1
    PING tomcat-1 (192.17.0.4) 56(84) bytes of data.
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=1 ttl=64 time=0.074 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=2 ttl=64 time=0.073 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=3 ttl=64 time=0.100 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=4 ttl=64 time=0.077 ms
    ^X64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=5 ttl=64 time=0.074 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=6 ttl=64 time=0.075 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=7 ttl=64 time=0.074 ms
    
    # tomcat-net-2 ping tomcat-1 也是通的
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat-net-2 ping tomcat-1
    PING tomcat-1 (192.17.0.4) 56(84) bytes of data.
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=1 ttl=64 time=0.092 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=2 ttl=64 time=0.100 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=3 ttl=64 time=0.075 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=4 ttl=64 time=0.091 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=5 ttl=64 time=0.085 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=6 ttl=64 time=0.089 ms
    64 bytes from tomcat-1.mynet (192.17.0.4): icmp_seq=7 ttl=64 time=0.083 ms
    
    # tomcat-net-2 ping tomcat-2 不通,反之也一样,就和上面的图一样
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat-net-2 ping tomcat-2
    ping: tomcat-2: Name or service not known
    
  4. 看一下tomcat-1的网络信息(tomcat01拥有了双ip)

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker exec -it tomcat-1 ip addr
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
    49: eth0@if50: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    53: eth1@if54: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:c0:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
        inet 192.17.0.4/16 brd 192.17.255.255 scope global eth1
           valid_lft forever preferred_lft forever
    
  5. 再看一下mynet的网络信息

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker network inspect mynet
    [
        {
            //...
            //发现我们的tomcat-1就进来这里了
            "Containers": {
                "43349138cfa25ef4d2fda31454dae9d783b3b029ad8eb10ebc1ddda8e9776a22": {
                    "Name": "tomcat-net-2",
                    "EndpointID": "f508128854ce1ebb272db8c6c7b32ad5235ca6e79f262a17895a4ec43747b792",
                    "MacAddress": "02:42:c0:11:00:03",
                    "IPv4Address": "192.17.0.3/16",
                    "IPv6Address": ""
                },
                "a4e6ece319c91eb8d67d646411f9809ffa570b8f8ff5fb020a19d813fc72952d": {
                    "Name": "tomcat-1",
                    "EndpointID": "6d6118f21f6d53fa15efe96b8913036d1c731c2b2389d84e8e7d9ff4fcc49f06",
                    "MacAddress": "02:42:c0:11:00:04",
                    "IPv4Address": "192.17.0.4/16",
                    "IPv6Address": ""
                },
                "d882ec326550e16e0196c9e3257b0a87ce185d55f35918b0211c0e43264a72e7": {
                    "Name": "tomcat-net-1",
                    "EndpointID": "a754bf88af0ceedd92a906e0e705403d940d6b5a3689c0f98ef368699a41352d",
                    "MacAddress": "02:42:c0:11:00:02",
                    "IPv4Address": "192.17.0.2/16",
                    "IPv6Address": ""
                }
            },
            "Options": {},
            "Labels": {}
        }
    ]
    
    

结论:如果要跨网络操作别人,就需要使用 docker network connect [OPTIONS] NETWORK CONTAINER 连接

9.5、实战:部署一个redis集群

  1. 创建redis自定义网络

    [root@iZwz9efdd2ukk4oauustczZ ~]# docker network create redis --subnet 172.38.0.0/16
    

    image-20230409113040756

  2. 通过shell脚本创建6个redis配置

    for port in $(seq 1 6); \
    do \
    mkdir -p /mydata/redis/node-${port}/conf
    touch /mydata/redis/node-${port}/conf/redis.conf
    cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
    port 6379
    bind 0.0.0.0
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    cluster-announce-ip 172.38.0.1${port}
    cluster-announce-port 6379
    cluster-announce-bus-port 16379
    appendonly yes
    EOF
    done
    

    image-20230409113319861

  3. 启动6个redis容器

    for i in $(seq 1 6); \
    do \
    docker run -p 637${i}:6379 -p 1637${i}:16379 --name redis-${i} -v /mydata/redis/node-${i}/data:/data -v /mydata/redis/node-${i}/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.1${i} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
    done
    

    image-20230409113420400

  4. 进入一个redis,注意这里是sh命令

    [root@iZwz9efdd2ukk4oauustczZ conf]# docker exec -it redis-1 /bin/sh
    
  5. 然后在容器中创建集群

    redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
    

    image-20230409113655744

  6. 连接集群,并查看信息

    # 连接集群
    redis-cli -c
    # 查看集群信息
    cluster info
    
    # 查看节点
    cluster nodes
    

    连接集群,并查看集群信息

    image-20230409113808844

    查看节点cluster nodes

    image-20230409113941684

  7. 测试验证高可用

    # set a b
    127.0.0.1:6379> set a b
    -> Redirected to slot [15495] located at 172.38.0.13:6379
    OK
    172.38.0.13:6379> get a
    "b"
    
    # 172.38.0.13是master(主从复制模式),直接删除对应的容器redis-3
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker rm -f redis-3
    redis-3
    [root@iZwz9efdd2ukk4oauustczZ ~]# docker ps
    CONTAINER ID   IMAGE                    COMMAND                  CREATED          STATUS          PORTS                                              NAMES
    3b4a1e1eee93   redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   19 minutes ago   Up 19 minutes   0.0.0.0:6376->6379/tcp, 0.0.0.0:16376->16379/tcp   redis-6
    918432f23434   redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   19 minutes ago   Up 19 minutes   0.0.0.0:6375->6379/tcp, 0.0.0.0:16375->16379/tcp   redis-5
    5d67854fec50   redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   19 minutes ago   Up 19 minutes   0.0.0.0:6374->6379/tcp, 0.0.0.0:16374->16379/tcp   redis-4
    e74d76ad7a23   redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   19 minutes ago   Up 19 minutes   0.0.0.0:6372->6379/tcp, 0.0.0.0:16372->16379/tcp   redis-2
    e404fdbafcbc   redis:5.0.9-alpine3.11   "docker-entrypoint.s…"   19 minutes ago   Up 19 minutes   0.0.0.0:6371->6379/tcp, 0.0.0.0:16371->16379/tcp   redis-1
    [root@iZwz9efdd2ukk4oauustczZ ~]# 
    
    # 再去get a
    /data # redis-cli -c
    127.0.0.1:6379> get a
    -> Redirected to slot [15495] located at 172.38.0.14:6379
    "b"
    
    # 发现依然可以查到,我们在查一下节点,发现172.38.0.14已经变成master了
    # 这里就实现高可用
    

    image-20230409114900584

10、idea整合docker

  1. idea新建一个springboot项目,并提供一个接口/hello

    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HelloController {
        @RequestMapping("/hello")
        public String hello() {
            return "hello docker springboot web";
        }
    }
    

    image-20230409222020339

    确保本地运行可以正常访问

    image-20230409221957310

  2. 打包

    image-20230409222052980

  3. 新建一个Dockerfile,并编辑如下

    FROM java:8
    
    COPY *.jar /app.jar
    
    CMD ["--server.port=8080"]
    
    EXPOSE 8080
    
    ENTRYPOINT ["java","-jar","/app.jar"]
    

    image-20230409222144616

  4. 打开阿里云服务器,/home目录下新建一个目录/idea,并将jar包和Dockerfile文件上传到/idea目录下

    image-20230409222324684

  5. 构建镜像

    [root@iZwz9efdd2ukk4oauustczZ idea]# docker build -t idea-springboot-web .
    

    image-20230409222434072

  6. 运行容器

    [root@iZwz9efdd2ukk4oauustczZ idea]# docker run -d -P --name idea-springboot-web idea-springboot-web
    da437e54099d269a1a89d9edf7af202d662f7e2af8790b9d481d9114838fd3fa
    [root@iZwz9efdd2ukk4oauustczZ idea]# docker ps
    CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                     NAMES
    da437e54099d   idea-springboot-web   "java -jar /app.jar …"   7 seconds ago   Up 6 seconds   0.0.0.0:32783->8080/tcp   idea-springboot-web
    
  7. 验证

    [root@iZwz9efdd2ukk4oauustczZ idea]# curl localhost:32783/hello
    hello docker springboot web
    

    正常输出!

11、docker compose

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

通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

Compose 使用的三个步骤:

  • 使用 Dockerfile 定义应用程序的环境
  • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行
  • 最后,执行 docker-compose up 命令来启动并运行整个应用程序

compose安装

后续补充。。。

compose使用

后续补充。。。

12、docker swarm

官方文档位置:https://docs.docker.com/engine/swarm/

Docker Swarm 是 Docker 的集群管理工具。

swarm 集群由管理节点(manager)和工作节点(work node)构成。

  • swarm mananger:负责整个集群的管理工作包括集群配置、服务管理等所有跟集群有关的工作。
  • work node:主要负责运行相应的服务来执行任务(task)。

image-20230410234718175

这里只做了解,简单写了一下笔记!我这里没有买四台服务器

准备:先买四台阿里云服务器(可以按量付费)

[root@iZwz9efdd2ukk4oauustczZ ~]# docker swarm --help

Usage:  docker swarm COMMAND

Manage Swarm

Commands:
  init        Initialize a swarm
  join        Join a swarm as a node and/or manager

Run 'docker swarm COMMAND --help' for more information on a command.
[root@iZwz9efdd2ukk4oauustczZ ~]# 

初始化节点

[root@iZwz9efdd2ukk4oauustczZ ~]# docker swarm init --help

Usage:  docker swarm init [OPTIONS]

Initialize a swarm

Options:
      --advertise-addr string                  Advertised address (format: "<ip|interface>[:port]")
      --autolock                               Enable manager autolocking (requiring an unlock key to start a stopped manager)
      --availability string                    Availability of the node ("active", "pause", "drain") (default "active")
      --cert-expiry duration                   Validity period for node certificates (ns|us|ms|s|m|h) (default 2160h0m0s)
      --data-path-addr string                  Address or interface to use for data path traffic (format: "<ip|interface>")
      --data-path-port uint32                  Port number to use for data path traffic (1024 - 49151). If no value is set or is set to 0, the default port (4789) is used.
      --default-addr-pool ipNetSlice           default address pool in CIDR format (default [])
      --default-addr-pool-mask-length uint32   default address pool subnet mask length (default 24)
      --dispatcher-heartbeat duration          Dispatcher heartbeat period (ns|us|ms|s|m|h) (default 5s)
      --external-ca external-ca                Specifications of one or more certificate signing endpoints
      --force-new-cluster                      Force create a new cluster from current state
      --listen-addr node-addr                  Listen address (format: "<ip|interface>[:port]") (default 0.0.0.0:2377)
      --max-snapshots uint                     Number of additional Raft snapshots to retain
      --snapshot-interval uint                 Number of log entries between Raft snapshots (default 10000)
      --task-history-limit int                 Task history retention limit (default 5)


docker swarm init --advertise-addr 192.168.99.121

Swarm initialized: current node (bvz81updecsj6wjz393c09vti) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx \
    172.17.0.2:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

添加节点

# docker swarm join --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx 192.168.99.121:2377
This node joined a swarm as a worker.
# docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
7ln70fl22uw2dvjn2ft53m3q5    worker2   Ready   Active
dkp8vy1dq1kxleu9g4u78tlag    worker1   Ready   Active        Reachable
dvfxp4zseq4s0rih1selh0d20 *  manager1  Ready   Active        Leader
# docker swarm join-token worker # 生成添加worker节点的完整的命令

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx \
    172.17.0.2:2377
# docker swarm join-token manager # 生成添加manager节点的完整的命令

To add a manager to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2 \
    172.17.0.2:2377

13、docker stack

后续补充。。。

14、docker secret

后续补充。。。

15、docker config

后续补充。。。

文章评论