1. docker镜像加载原理
Docker的镜像实际上是由一层一层的文件系统组成,这种层级的文件系统叫做UnionFS.
bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统。在Docker镜像的最底层是bootfs,这一层与我们典型的Liunx/Unix系统是一样的,包含boot加载器和内核,当boot加载完成之后整个内核就在内存中了,此时内存的使用权已由bootfs装交给内核,此时系统也会卸载bootfs。
rootfs(root file system),在bootfs之上,包含的就是典型的Linux系统中的/dev/,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu、CentOS等。
平时我们安装的虚拟机的CentOS都是好几个G,为什么Docker这里才200M?
对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了。因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以共用bootfs。
虚拟机是分钟级启动,容器是秒级启动。
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。举一个简单的例子,例如基于Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层,如果在该镜像中添加python包,就会在基础镜像层之上创建第二个镜像层。如果继续添加一个安全补丁,就会创建第三个镜像层。
特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部,这一层就是我们通常说的容器层,容器之下的都叫镜像层。我们所有的操作都是基于容器层。
2. 常用命令
docker version
docker info
docker <命令> --help
docker images -aq #只显示所有镜像的ID
docker ps -aq #只显示所有容器的ID
Ctrl + P + Q #容器不停止退出
docker rm -f $(docker ps -aq) #删除所有的容器
docker logs -tf --tail 10 <容器ID> #查看日志
docker run -it --rm <容器ID> #用完即删(容器),一般用于测试
3. 进入正在运行的容器
#容器在数据就存在,跟容器是否在运行无关
#方式一
docker exec -it <容器ID> bashShell
#方式二
docker attach <容器ID>
#docker exec #进入容器后开启一个新的终端,可以在里面操作(常用)
#docker attach #进入容器正在执行的终端,不会启动新的进程
4. 容器与宿主机数据传输
docker cp 容器ID:容器内路径 宿主机路径
5. 运维命令
docker top <容器ID>
docker inspect <容器ID>
docker stats
#启动es,限制内存消耗
docker run -d --name es02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
6. 网络
docker network ls
7. 可视化
portainer
docker的图形化界面管理工具,提供了一个后台面板供我们操作。
docker run -d -p 8088:9000
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
rancher(CI/CD在用)
8. commit镜像
#如果想要保存当前容器的状态,可以通过commit来提交,获得一个镜像。就好比VM中的快照。可以根据tag回滚到之前的版本。
docker commit #提交容器成为一个新的镜像
docker commit -m='提交信息' -a="提交作者" <容器ID> 目标镜像名:[tag]
9. 匿名挂载和具名挂载
匿名挂载
docker run -d -P --name nginx01 -v /etc/nginx nginx:latest
docker volume ls
docker volume inspect <容器ID/名称>
# 匿名挂载:-v 后面只写了容器内的路径,没有写容器外宿主机的路径。
具名挂载
docker run -d -P --name nginx02 -v etc_nginx:/etc/nginx nginx:latest
docker volume inspect <容器ID/名称>
# 具名挂载:-v 卷名:容器内路径,所有docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data
# 通过具名挂载可以方便的找到我们的一个卷,大多数情况使用具名挂载,不建议使用匿名挂载。
# 如何确定是具名挂载还是匿名挂载,还是指定参数挂载?
总结
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /宿主机路径:/容器内路径 # 指定路径挂载
# 不管是匿名挂载还是具名挂载,所有docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data
# 通过 -v 容器内路径:ro、rw改变读写权限
docker run -d -P --name nginx03 -v etc_nginx:/etc/nginx:ro nginx:latest
# 一旦这个设置了容器权限,容器对我们挂载出来的内容就有限定了
# ro 这个路径的内容只能通过宿主机来操作,容器内部无法操作
# rw 默认权限
10. 容器间数据共享
docker run -it --name docker01 -v /data/etc:/etc centos:8
# docker01的目录卷共享给docker02
docker run -it --name docker02 --volume-from docker01 centos:8
# 类似于java中的子类继承父类
# docker01其实就是数据卷容器的角色,而且该容器被删除后,不影响其他容器对该共享卷的使用(拷贝机制)
# 结论:
# 容器之间数据的共享,数据卷容器的生命周期一直持续到没有容器使用为止。
# 但是一旦持久化到了本地,这个时候,本地的数据是不会删除的。
上一条:Docker与容器技术
下一条:5种方法解决docker无法使用的问题,带着你的NAS终极突围