docker镜像容器挂载卷

437次阅读
没有评论

接上篇这个5.1继续肝docker;

镜像

什么叫镜像?

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

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

例如我们去dockerhub上搜索centos,我这里安装的是centos8的版本,所以去看看8下面都有啥吧; docker镜像容器挂载卷 标红的地方点进去,我们看下它的dockerfile(dockerfile是指构建docker镜像的指令脚本)

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

容器

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

我们看下protainerUi容器的详情: docker镜像容器挂载卷

[
    {
        # 发现镜像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"
        }
    }
]

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|容器名称 的容器的日志

卷挂载

我们知道,docker是一种虚拟化的方式,根据需求将环境和配置、应用一起打包后,然后运行在宿主机上来对外提供服务的;

docker为了数据持久化,提供了数据卷;把数据卷(文件目录)挂载到本地后,这样即使删除了容器,数据也还在本地;真正做到删库跑路;

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

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

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

退出,可以看到容器被删除了;接下来我们正常启动下,带上端口映射和对应镜像的tag,如果不指定tag会去下载最新的版本并启动;我们这里就使用刚下载的就好 docker镜像容器挂载卷 启动完后,我们直接在服务器上访问,发现可以连通了,但是同样报404; docker镜像容器挂载卷 我们进入容器看到webapps下发现啥都没有,能不报404吗?一般我们用tomcat部署项目,都是放在tomcat webapps这个目录下的,如果我们后面采用集群部署项目,那么多个tomcat容器,难道我都要每次都进入容器把应用拷进来;docker其实也想到了,docker可以提供卷挂载,我们只需要将容器中指定目录挂载到我们主机上,就可以实现部署一份,多份同步了;

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

测试挂载

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

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

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

docker镜像容器挂载卷

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

同理:我们用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

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

viEcho
版权声明:本站原创文章,由viEcho2021-05-04发表,共计5537字。
转载提示:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
载入中...