• docker镜像,容器,挂载卷


    文章目录

    镜像

    什么叫镜像?

    Docker镜像是一个特殊的文件系统(分层的联合文件系统),除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等信息)。

    什么叫分层的文件系统呢?

    例如我们去dockerhub上搜索centos,我这里安装的是centos8的版本,所以去看看8下面都有啥吧;

    标红的地方点进去,我们看下它的dockerfile(dockerfile是指构建docker镜像的指令脚本)


    可以看到centos8的dockerfile很简单,from是说明它基于什么构建的,可以看到centos8是基于scratch这个空镜像来构建的;add 添加一个centos的压缩包;LABEL是标签说明,CMD是运行完此镜像后默认执行的指令,可以看到启动centos8镜像后,它指定进入了bash脚本界面;

    官方说明:scratch镜像是一个空的镜像,可以用于构建busybox等超小镜像,可以说是真正的从零开始构建属于自己的镜像

    注📢:macos系统其实也采用了分层的文件系统,去dockerhub搜Ubantu也可以看到它对应的镜像;或者你在升级你的mac系统时,如果点开详情,或者看它的更新包,可以看到它的更新包中包含了基于上次安装的数据卷(volumes);

    docker镜像常用相关命令:

    docker image ls # 列出当前宿主机上所有镜像
    docker image ls ubuntu:16.04 # 列出指定的镜像
    docker pull hello-world #拉取镜像
    docker run hello-world #运行镜像
    docker rmi hello-world #删除镜像
    docker run -i -t --rm ubuntu:16.04 /bin/bash
    #-i:允许你对容器内的标准输入进行交互
    #-t:在新容器内指定一个伪终端或终端
    #–rm:容器退出后立即删除容器。一般情况下,无需指定此参数。一般我测试用的话可以加上,容器停止后立即删除容器
    # ubuntu:16.04:以此镜像为基础启动容器
    # /bin/bash:指定的交互式Shell
    docker inspect 578c3e61a98c #查看指定镜像id 镜像的详情
    docker image rm 578c3e61a98c # docker删除指定镜像Id镜像
    docker image rm $(docker image ls -q) #删除所有镜像
    docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms64m -Xmx512m" elasticsearch:7.7.1 # 后台运行名称为elasticsearch的镜像,并指定端口映射;将9300映射到9200的宿主机端口上,-e指定单机运行模式,-e指定运行的java环境配置 容器名称为elasticsearch:7.7.1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    容器

    docker的镜像启动后就是一个容器了,之前我们安装docker时,运行了HelloWorld的测试程序镜像,那么它启动后就是一个容器实例(就是我们运行的服务);

    我们看下protainerUi容器的详情:

    [
        {
            # 发现镜像Id580c0e4e98b06d 是容器id的前缀
            "Id": "sha256:580c0e4e98b06d258754cf28c55f21a6fa0dc386e6fe0bf67e453c3642de9b8b",
            # 用的是最新的版本
            "RepoTags": [
                "portainer/portainer:latest"
            ],
            "RepoDigests": [
                "portainer/portainer@sha256:fb45b43738646048a0a0cc74fcee2865b69efde857e710126084ee5de9be0f3f"
            ],
            "Parent": "",
            "Comment": "buildkit.dockerfile.v0",
            "Created": "2021-03-18T19:53:42.48462213Z",
            "Container": "",
            # 容器配置
            "ContainerConfig": {
                "Hostname": "",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": null,
                "Cmd": null,
                "Image": "",
                "Volumes": null,
                "WorkingDir": "",
                "Entrypoint": null,
                "OnBuild": null,
                "Labels": null
            },
            "DockerVersion": "",
            "Author": "",
            "Config": {
                "Hostname": "",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                # 绑定的端口
                "ExposedPorts": {
                    "9000/tcp": {}
                },
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                # 容器和宿主机文件映射
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
                ],
                "Cmd": null,
                "Image": "",
                # 数据卷为空
                "Volumes": {
                    "/data": {}
                },
                "WorkingDir": "/",
                "Entrypoint": [
                    "/portainer"
                ],
                "OnBuild": null,
                "Labels": null
            },
            "Architecture": "amd64",
            "Os": "linux",
            "Size": 79085285,
            "VirtualSize": 79085285,
            # 驱动
            "GraphDriver": {
                "Data": {
                    "LowerDir": "/var/lib/docker/overlay2/12662c46247e8aaf8712d025187a532bdc2c87d9ecdef2074deb38aaefcf0a5d/diff:/var/lib/docker/overlay2/4548e695971c596b459c5c3ef688f96b7b2b35969a109d90c21933878a052e4e/diff",
                    "MergedDir": "/var/lib/docker/overlay2/7752938c5962b1fc34cbe172f43ee485b9212ea87df836764298283ddd4c7a35/merged",
                    "UpperDir": "/var/lib/docker/overlay2/7752938c5962b1fc34cbe172f43ee485b9212ea87df836764298283ddd4c7a35/diff",
                    "WorkDir": "/var/lib/docker/overlay2/7752938c5962b1fc34cbe172f43ee485b9212ea87df836764298283ddd4c7a35/work"
                },
                "Name": "overlay2"
            },
            "RootFS": {
                "Type": "layers",
                # portainer镜像是基于以下镜像而来的,可以看到有三层
                "Layers": [
                    "sha256:8dfce63a73970a18bcc2ca447d9c252aedd3157e9ee02a88e66c53571279aee9",
                    "sha256:11bdf2a940a7eb35fe69359d45eaeb6f8553a682a19e26db49d4c924588bb6c4",
                    "sha256:658693958bcb13c9d33a49d82f1e1297073066bec8d8b07dd49357ad5c08ce58"
                ]
            },
            "Metadata": {
                "LastTagTime": "0001-01-01T00:00:00Z"
            }
        }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96

    docker容器相关命令:

    docker start|stop|restart hello-world|578c3e61a98c # 启动|停止|重启指定 容器名称|容器id的容器
    docker inspect 578c3e61a98c #查看指定容器id的详情
    docker exec -it 578c3e61a98c|hello-world /bin/sh #进入指定 容器id|容器名称 的容器
    docker rm -f 578c3e61a98c|hello-world # 强制删除指定 容器id|容器名称 的容器
    docker stats 578c3e61a98c|hello-world # 查看指定 容器id|容器名称 的容器占用资源情况
    docker top 578c3e61a98c|hello-world # 查看指定 容器id|容器名称 的容器正在运行的进程
    docker logs 578c3e61a98c|hello-world # 查看指定 容器id|容器名称 的容器的日志
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    卷挂载

    我们知道,docker是一种虚拟化的方式,根据需求将环境和配置、应用一起打包后,然后运行在宿主机上来对外提供服务的;
    docker为了数据持久化,提供了数据卷;把数据卷(文件目录)挂载到本地后,这样即使删除了容器,数据也还在本地;真正做到删库跑路;

    数据卷可以在一个或多个容器间通信,实现数据的持久化和共享;和我们将数据拷贝到另一个目录下的原理是一样的;
    示例:
    我们下载个tomcat并启动下:

    docker run -it --rm tomcat9.0 #测试运行tomcat9.0镜像 没找到默认拉取最新的并将tag命名为9.0
    
    • 1

    下载并启动完后,我们查看镜像发现确实多了个tomcat9.0,这时候由于我们没有配置端口映射,直接访问localhost:8080是在宿主机上访问的,肯定访问不到,所以我们得进入容器内访问,发现访问报404,所以服务实际上启动了的,至于为啥404我们后面再分析;

    退出,可以看到容器被删除了;接下来我们正常启动下,带上端口映射和对应镜像的tag,如果不指定tag会去下载最新的版本并启动;我们这里就使用刚下载的就好

    启动完后,我们直接在服务器上访问,发现可以连通了,但是同样报404;

    我们进入容器看到webapps下发现啥都没有,能不报404吗?一般我们用tomcat部署项目,都是放在tomcat webapps这个目录下的,如果我们后面采用集群部署项目,那么多个tomcat容器,难道我都要每次都进入容器把应用拷进来;docker其实也想到了,docker可以提供卷挂载,我们只需要将容器中指定目录挂载到我们主机上,就可以实现部署一份,多份同步了;

    同样,我们思考下容器启动了后,数据放在哪儿?放在容器中,删除容器的话是不是容器里的数据就没了,所以为了数据的同步持久化,docker提供了数据卷,我们同样可以将数据卷和一些重要信息放在本地,这样即使删除了容器,数据还在本地;卷可以在一个或多个容器间通信,提供数据的持久化和数据共享;

    测试挂载

    我们使用下载的centos镜像,运行进入容器发现容器没有运行,docker ps查看运行中的容器,docker ps -a查看所有容器;因为我们下载的centos里面啥都没有,没有做任何事情docker默认不启动;

    那我们测试挂载启动看下,我们将容器的文件目录挂载到主机的home目录下:
    我们启动centos容器后,看下是否有挂载;查看容器详情中的mounts信息,发现已经挂载上了;

    docker ps # 查看运行的容器
    docker inspect 9bdcdbaf27fa # 查看容器详情
    
    • 1
    • 2

    接着我么测试下往home目录下写东西,看容器中是否相应的文件产生,反之再试下容器中写东西,看主机是否同步;
    我们先看下主机/homr目录下是否是空的.可以看到容器和主机间通过挂载是可以实现双向同步;

    同理:我们用docker安装mysql时,挂载关键的配置文件即可,这样即使我们删除了容器,一旦重启容器,数据就会同步到容器中;实现本地-多容器同步;

    dockerhub上官方关于mysql的同步挂载的命令如下:

    # docker安装mysql 必要步骤: -e MYSQL_ROOT_PASSWORD=my-secret-p @ mysql的初始密码!
    docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    
    # mysql核心1  配置
    docker run --name some-mysql -v /my/custom:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    # mysql核心2 数据存储!
    docker run --name some-mysql -v /my/own/datadir:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    小结:至此我们关于docker的镜像容器挂载卷都有认识,通过挂载通信,可以很清晰的感受到docker的便捷;

  • 相关阅读:
    各类高危漏洞介绍及验证方式教程(一)
    《C和指针》笔记33:指针数组
    前端提交规范 ESLint + Prettier + husky + lint-staged
    SpringCloud-06-Config
    使用 ISAR 数据库提供离线 Flutter 支持
    Ranger (五) --------- 使用 Ranger 对 Hive 进行权限管理
    Vertica 向 GBase8a 迁移指南之布尔数据类型(BOOLEAN)
    Docker部署jar包
    【鸿蒙 HarmonyOS 4.0】TypeScript开发语言
    数组方法深入探究(1)--at&copyWithin
  • 原文地址:https://blog.csdn.net/iME_cho/article/details/125417709