文章目录
- 镜像
- 容器
- 卷挂载
镜像
什么叫镜像?
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
容器
docker的镜像启动后就是一个容器了,之前我们安装docker时,运行了HelloWorld的测试程序镜像,那么它启动后就是一个容器实例(就是我们运行的服务);
[
{
# 发现镜像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我们后面再分析;
退出,可以看到容器被删除了;接下来我们正常启动下,带上端口映射和对应镜像的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 # 查看容器详情
接着我么测试下往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
小结:至此我们关于docker的镜像容器挂载卷都有认识,通过挂载通信,可以很清晰的感受到docker的便捷;