Docker基础知识
Docker的基本组成
镜像(image):
docker镜像就好比是一个模板,可以通过这个模板来创建容器对外提供服务,如通过tomcat镜像创建一个tomcat容器,容器内的tomcat运行我们的war包对外提供服务,而一个镜像可以创建多个容器,我们不需要像传统部署一样每次都手动部署war,修改端口配置等。
容器(container):
Docker利用容器技术,独立运行一个或者一组应用,容器通过镜像来创建。对容器的基本操作有启动,停止,删除等,可以把这个容器理解为就是一个简易的Linux系统。
仓库(repository):
仓库就是存放镜像的地方,仓库分为公有仓库和私有仓库,类似GitHub,DockerHub便是镜像仓库。
Docker如何工作
Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!Docker-Server接收到Docker-Client的指令并执行。
为什么Docker比VM快
docker有着比虚拟机更少的抽象层。由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
docker利用的是宿主机的内核,而不需要Guest OS。
当docker新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核,避免了引导、加载操作系统内核返个比较费时费资源的过程。VM新建一个虚拟机时,虚拟机软件需要加载GuestOS,而docker由于直接利用宿主机的操作系统,则省略了这个复杂的过程
- Hypervisor:虚拟机监视器(virtual machine monitor,缩写为 VMM),是用来建立与执行虚拟机器的软件、固件或硬件。
- GuestOS: VM(虚拟机)里的的系统(OS)
- HostOS:物理机里的系统(OS)
Docker安装
Docker的安装要求Linux在内核3.0以上
官方安装文档:https://docs.docker.com/engine/install/
帮助命令
1 | 显示docker版本 |
docker全部命令官方文档:https://docs.docker.com/reference/
操作镜像
docker images
作用:查看镜像
docker images
查看当前系统的镜像(默认隐藏中间的镜像)docker images -a
查看全部镜像,包括中间层的镜像docker images -q
查看镜像,仅显示镜像iddocker images -f <key=valu>
查看镜像,根据条件过滤key的范围:
- dangling:显示标记为
<none>
的镜像,取值范围:true | false,如:docker images -f dangling=true
- label:根据标签进行过滤,其中lable的值,是docker在编译的时候配置的或者在Dockerfile中配置的
- before:根据某个镜像的构建时间进行过滤,before的value表示某个镜像构建时间之前的镜像列表,如:
docker images -f before=mysql
- since:跟before正好相反,表示的是在某个镜像构建之后构建的镜像
- reference:添加正则进行匹配,如:
docker images -f reference="*:latest"
(查询版本为最新版本的镜像)
- dangling:显示标记为
docker search
作用:搜索远程仓库的镜像
如:docker search mysql -f STARS=3000
(查询远程仓库镜像,查询mysql的镜像,且stars数量大于等于3000)
docker pull
作用:从远程仓库拉取镜像
格式docker pull <镜像名[:版本]>
,等价于docker image pull <镜像名[:版本]>
,如docker pull mysql
(拉取mysql镜像,默认拉取最新版,latest),docker pull mysql:5.7
(拉取mysql5.7镜像)
docker rmi
作用:删除镜像
格式:docker rmi <镜像名或镜像ID>
,等价于docker image rm <镜像名或镜像ID>
。镜像删除时,docker默认不允许删除正在运行的容器所引用的镜像,除非指定-f选项。
docker rmi mysql
(删除mysql的镜像)- 删除时可通过
镜像名:tag
指定版本(标签)。如:docker rmi mysql:5.7
这实际上只会删除mysql镜像为5.7的标签,除非该镜像仅有此标签,那么镜像就真的被删除 docker rmi -f mysql
:强制删除镜像docker rmi -f $(docker images -aq)
(强制删除全部镜像,先查出id后删除)docker images -q|xargs docker rmi
:使用管道符传参进行删除docker rmi -no-prune
:不移除该镜像的过程镜像,默认移除- 同一镜像有多个tag情况下,执行
docker rmi <镜像ID>
指令无法删除
操作容器
扫盲:容器通过镜像创建而来,镜像与容器为1对多的关系。
docker run
作用:新建并运行容器
docker run
等价于docker container run
常见命令格式:docker run [option1][option2] <镜像id或名称>
,如:docker run --name=mysql-test mysql:5.7
(使用mysql5.7镜像新建并运行一个容器,容器名为“mysql-test”)。
docker run 命令支持的option非常多,介绍部分option:
- –name:指定容器名称
- -i:以交互模式运行容器,通常与 -t 同时使用
- -t:为容器重新分配一个伪终端,通常与 -i 使用
- -d:以后台模式运行容器,并返回容器id,即启动守护式容器
- -v:挂载卷(此处不展开讲,见下文)
- -P:随机映射宿主机一个端口到容器内的一个端口
- -p:指定端口映射,模式如下:
ip:<宿主机端口>:<容器端口>
:宿主机IP+端口映射到容器内端口(如多网卡时)ip::<容器端口>
:自动选择宿主机端口(包含宿主机所有IP)映射到容器内端口<宿主机端口>:<容器端口>
:宿主机端口映射到容器内端口
- –rm:容器停止时删除容器
docker create
作用:新建容器,但不启动
常见命令格式:docker create[option1][option2] <镜像id或名称>
,option选项参数含义与run类似但不是全都支持
docker ps
作用:查看容器的运行状况,类似linux的ps命令查看进程的运行状态
docker ps
等价于docker container list
等价于docker container ls
docker ps
:列出正在运行的容器docker ps -a
:列出全部容器,包括历史记录中已经停止的容器docker ps -q
:列出正在运行的容器,仅显示容器iddocker ps -n=?
:列出最近创建的?个容器docker ps -l
:列出最近创建的上个容器,即docker ps -n=1
docker stop
作用:停止正在运行的容器
常见命令格式:docker stop <容器id或容器名>
,如:
docker stop mysql-test
:停止容器名为mysql-test的容器docker stop d29f876f66d5
:停止容器id为d29f876f66d5的容器
docker kill
作用:强制停止正在运行的容器,类似linux的kill命令
常见命令格式:docker kill <容器id或容器名>
,如:
docker kill mysql-test
:强制停止容器名为mysql-test的容器
docker start
作用:启动容器
常见命令格式:docker start <容器id或容器名>
,如:
docker start mysql-test
:启动容器名为mysql-test的容器
docker restart
作用:重启容器
常见命令格式:docker restart <容器id或容器名>
,如:
docker restartmysql-test
:重启容器名为mysql-test的容器
docker rm
作用:删除容器
正常情况下正在运行的容器不可删除。
常见命令格式:docker rm <容器id或容器名>
,如:
docker rm mysql-test
:删除容器名为mysql-test的容器docker rm -f mysql-test
:强制删除容器名为mysql-test的容器,即使该容器正在运行
与容器交互
docker attach
常见命令格式:docker attach <容器id或容器名>
,此命令将进入容器正在执行的终端,如容器启动的前台进程是SpringBoot的jar(以前台模式启动),那么此方式进入容器后看到的就是SpringBoot应用的控制台打印的日志。
docker exec
常见命令格式:docker exec [option] <容器id或容器名>
,进入当前容器后开启一个新的终端,option选项常用有:
- -i:即使没有附加也保持STDIN(标准输入)打开
- -t:分配一个伪终端
- -d:分离模式: 在后台运行
选项意义与run命令的选项类似,如:
docker exec -it mysql-test /bin/bash
:我们想进入容器,执行任何命令,就像平时使用linux那样,可同时指定-it
选项。docker exec -t mysql-test ls /
:我们想查看某一目录下的文件信息,可以仅指定-t
选项来进行回显,执行完毕后就退出了容器。docker exec -i mysql-test /bin/bash
:当使用-i
选项执行/bin/bash
时,由于标准输入打开,我们可以输入其它命令,但是此时是没有回显的。正常情况下只能用Ctr+C结束与之的交互,此时容器内由”/bin/bash”命令创建的进程不会被结束。docker exec mysql-test ls
:不带option,有回显,命令执行完毕后,docker发现没有前台进程,退出容器。
单独使用-i
的场景不多,更多使用的是-t
和-it
。笔者这里对这几个选项的描述可能并不是特别准确,心里明白但无法用文字完美诠释,读者还是自己实操理解会好些。
退出容器
- docker attach方式进入容器:按下Ctrl+P+Q退出,如果使用exit退出终端或Ctrl+c方式结束当前前台进程,会导致容器停止!如果使用
docker attach --sig-proxy=false <容器id或容器名>
进入容器,则可以使用Ctrl+c方式退出 - docker exec方式进入容器:按下Ctrl+P+Q退出,或以exit命令退出当前终端以退出容器。
两种进入容器的方式使用Ctrl+P+Q退出时,容器不会停止,因为此种方式会保留进入容器时的执行该命令的进程,容器不会退出,如果一个容器已经后台运行,我们以docker exec -it
进入容器时,最好以exit命令退出,容器不会保留终端进程。如果是以docker attach方式进入,此时我们来到了容器守护的前台进程,一定要以Ctrl+P+Q方式退出,否则容器会停止。
容器内外的文件传输
docker cp
作用:从容器内拷贝文件(文件夹也是文件)到宿主机上
常见命令格式:docker cp [option] <srcPath> <destPath>
- option选项:-L,以保持源目标中的链接
- srcPath与destPath分两种情况:
- 容器内拷贝文件到容器外:
docker cp <容器id或容器名>:<容器内路径> <主机路径>
- 容器外拷贝文件到容器内:
docker cp <主机目的路径> <容器id或容器名>:<容器内路径>
,容器内的路径不存在则创建,即重命名
- 容器内拷贝文件到容器外:
容器数据卷
容器内外的网络连通
端口映射
使用run命令时指定端口映射,前文提到过,见docker run
命令的-p
与-P
选项。
Docker网络
容器的日志
docker logs
作用:查看容器运行产生的日志
命令格式:docker logs [oprion1][option2] <容器id或容器名>
,常用option:
docker logs mysql-test
:查看容器名为mysql-test的日志docker logs -f mysql-test
:查看且跟踪容器名为mysql-test的日志docker logs -f mysql-test
:查看且跟踪容器名为mysql-test的日志docker logs -n=100 mysql-test
:查看容器名为mysql-test的最后100行日志docker logs --since=2021-02-01 mysql-test
:查看容器名为mysql-test自2021年2月1日以来的日志docker logs --since=2021-02-01T00:00 mysql-test
:查看容器名为mysql-test自2021年2月1日00:00以来的日志docker logs --since=2021-02-01T00:00:00 mysql-test
:查看容器名为mysql-test自2021年2月1日00:00:00以来的日志
查看镜像或容器元数据
镜像或容器元数据:镜像或容器的详细信息,镜像元数据包括镜像完整id、构建时间等,容器元数据包括数据卷、网络等信息。
docker inspect
docker inspect <镜像名或镜像ID>
(查看镜像元数据)docker inspect java
:查看java(latest版本)的镜像元数据docker inspect java:7
:查看java7的镜像元数据
docker inspect <容器名或容器ID>
(查看容器元数据)docker inspect mysql-test
:查看容器名为mysql-test的容器元数据
Docker镜像原理
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。
镜像加载原理
UnionFS(联合文件系统)
复制粘贴一下概念:Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。Union文件系统是 Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
UFS可以类比git的commit进行理解。
docker的镜像实际上由一层一层的联合文件系统组成。
boots(boot file system):主要包含 bootloader和 Kernel, bootloader主要是引导加 kernel, Linux刚启动时会加bootfs文件系统,在Docker镜像的最底层是 boots。这一层与我们典型的Linux/Unix系统是一样的,包含boot加載器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。
rootfs(root file system):在 bootfs之上。包含的就是典型 Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。 rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等。
平时我们安装进虚拟机的CentOS都是好几个G,为什么Docker这里才200M?
对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用宿主机的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版, boots基本是一致的,rootfs会有差別,因此不同的发行版可以公用bootfs。
镜像的分层
基于UFS的特点,大多数docker镜像都是由多层镜像“叠加”而来的,所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层,为什么Docker镜像要采用这种分层的结构呢?
最大的好处,莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。类似于面向对象多态的体现之一:类的继承。
镜像与容器的联系
Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部,这一层就是我们通常说的容器层,容器之下的都叫镜像层。
如果想要保存当前容器的状态,就可以通过docker commit
来提交(此处不将commit命令),获得一个镜像,就好比我们我们使用虚拟机的快照。
本文参考B站UP主“狂神说Java”https://space.bilibili.com/95256449/的docker教学视频进行整理。
感谢成长路上为在下传道受业解惑之人