Docker的主要目标是“Build,Ship and Run Any App,Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到 "一次封装,到处运行"。
Linux 容器技术的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。将应用运行在 Docker 容器上面,而 Docker 容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作
解决了运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术
- 是集中存放镜像的地方
- 仓库(Repository)是仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像。每个镜像都有不同的标签(tag)
- 仓库分为公开仓库(Public)和私有仓库(Private)两种形式
- 最大的公开仓库是Docker Hub,存放着大量的镜像工用户下载
- 国内公开的仓库包括阿里云、网易云等
tip:鲸鱼背着集装箱游在大海上
- 大海:宿主机系统(如win 10)
- 鲸鱼:docker
- 集装箱:容器实例-------> from 镜像模板
Docker本身是一个容器运行载体或称之为管理引擎,我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎image镜像文件。只有通过这个镜像文件才能生成Docker容器,Image文件可以看做容器模板。Docker根据Image文件生成实例,同一个Image文件,可以同时生成多个运行的容器实例
1、安装:参考Docker官方文档进行安装(官方文档很详细)
2、使用镜像加速
(1)使用阿里云镜像加速(Centos 7 +)(只在pull下载是使用阿里云镜像)
(2)在/etc/docker下新建文件 daemon.json,内容如下:
|
(3)执行systemctl daemon -reload 以及 systemctl restart docker 命令,使配置生效
Docker是一个C/S(Client-Server)结构系统,Docker守护进程运行在主机上,然后通过Socket连接从客户端访问,守护进程从客户端接收命令并管理运行在主机上的容器。容器,是一个运行时环境,就是鲸鱼背上的集装箱
(1)Docker有比虚拟机更少的抽象层。由于Docker不需要Hypervision实现硬件资源虚拟化(Docker有一层Docker Engine),运行在Docker容器上的程序直接使用的是实际物理机的硬件源。因此在CPU、内存利用率上Docker有明显的优势
(2)Docker利用容器宿主机的内核,而不需要Guest OS。因此,当新建一个容器时,Docker不需要和虚拟机一样重新加载一个操作系统内核,从而避免引寻、加载操作系统内核这个比较浪费资源的过程。当新建一个虚拟机时,虚拟机软件需要加载Guest OS,这个过程是分钟级的。而Docker由于直接利用宿主机的操作系统,则省略了这个过程,因此新建一个Docker容器时,只需几秒钟
(1)docker version:Docker版本描述之类的信心
(2)docker info:Docker安装之后的描述信息(如镜像有多少个、容器有多少个、宿主机名……)
(3)docker --help:Docker帮助命令(类似于Linux的man命令)
(1)docker images [OPTIONS]:列出本地主机上的镜像
- REPOSITORY:表示镜像的仓库源
- TAG:镜像的标签
- IMAGE ID:镜像ID
- CREATED:镜像创建的ID
- SIZE:镜像大小
tip:同一个仓库源有多个TAG,代表仓库源的不同版本,我们使用REPOSITORY:TAG来定义不同的镜像。如果不指定一个镜像的版本标签,默认使用latest标签的镜像
OPTIONS说明:
-a:列出本地所有镜像(含中间映像层)
-q:只显示镜像ID
--digests:显示镜像的摘要信息
--no-trunc:显示完整的镜像信息(如显示完整的IMAGE ID)
(2)docker search [OPTIONS] 镜像名字:去Docker Hub上面查找镜像
*如果配置了阿里云镜像地址,是在pull时使用的
OPTIONS说明:
--no-trunc:显示完整的镜像信息
-s:列出收藏数不小于指定数值的镜像 docker search -s 30 tomact
--automated:只列出automated build(自动构建)类型的镜像
(3)docker pull 镜像名字 [:TAG]:下载镜像(不加TAG默认就是latest)
tag可以在docker hub上找到
(4)docker rmi [OPTIONS] 镜像名[:TAG]/镜像ID:删除镜像
OPTIONS说明:
-f:强制删除
docker rmi -f 镜像ID 镜像ID 镜像ID:删除多个镜像
docker rmi -f $(docker images -qa):删除全部镜像
(1)docker run [OPTIONS] 镜像ID/镜像名[:TAG] [COMMAND] [ARG…]:新建并启动容器
OPTIONS说明:
--name="容器的新名字":为容器指定一个名字
-d:后台运行容器并返回容器ID,也即启动守护式容器
-i(interact):以交互模式运行容器,通常与-t同时使用(启动容器就要进入容器跟容器交互)
-t:为容器重新分配一个伪输入终端,通常与-i同时使用
-P:随机端口映射
-p:指定端口映射,有以下四种格式
ip:hostPort:containerPort docker运行的主机访问端口:docker容器端口
ip::containerPort
hostPort:containerPort
containerPort
启动交互式容器:docker run -it 镜像ID/镜像名[:TAG]
启动守护式容器:docker run -d 镜像ID/镜像名[:TAG]
使用镜像centos:latest以交互模式启动一个容器,在容器内执行/bin/bash命令 docker run -it centos /bin/bash,默认就是/bin/bash命令登录
eg:docker run -it centos(启动docker上的centos并登陆进去,-t代表的伪终端就是在客户端界面的命令行)
(2)docker ps [OPTIONS]:列出当前所有正在运行的容器
OPTIONS说明:
-a:列出当前所有正在运行的容器 + 历史上运行过的
-l:显示上一个启动的容器
-n:显示最近创建的n各容器
-q:静默模式,只显示容器编号
--no-trunc:不截断输出
(3)退出容器
两种退出方式:
① exit:容器停止退出
② ctrl+p+q:容器不停止退出(p和q按顺序)
(4)docker start 容器ID/容器名:启动容器
(5)docker restart 容器ID/容器名:重启容器
(6)docker stop 容器ID/容器名:停止容器(温柔停止)
(7)docker kill 容器ID/容器名:强制停止容器
(8)docker rm 容器ID:删除已经停止的容器
(9)一次性删除多个容器:docker rm -f $(docker ps -a -q) docker ps -a -q | xargs docker rm
(1)启动守护是容器:docker run -d 镜像ID/镜像名[:TAG]
#使用镜像centos:latest以后台模式启动一个容器
docker run -d centos
问题:docker ps -a进行查看,发现容器已经退出
很重要的说明了一点,Docker容器后台运行,就必须有一个前台进程
容器运行的命令如果不是那些一直挂起的命令(比如top、tail,就是会自动退出的。)
这个是docker机制的问题,比如web容器,以nginx为例,正常情况下,我们配置启动服务只需要启动响应的service即可,例如service start nginx。但是,这样做,nginx为后台进程模式运行,就导致docker前台没有运行的应用。这样的容器后台启动后,会立即自杀因为他觉得没事可做(没有命令挂起)。所以,最佳的解决方案是,将你要运行的程序以前台进程的形式运行。
(2)docker logs [OPTIONS] 容器ID:查看容器日志
OPTIONS说明:
-t:加入时间戳
--tail 数字:显示最后多少条
-f:跟随最新的日志打印
eg:docker -t -f --tail 容器ID
docker run -d centos /bin/sh -c "while true;do echo aaa;sleep 2;done;" 以这种方式启动守护式进程,该容器就不会停止,因为有命令挂起(承上)
(3)docker top 容器ID:查看容器内进程
(4)docker inspect 容器ID:查看容器内部细节
(5)进入容器以命令交互:
- docker exec -it 容器ID /bin/bash(exec命令必须指定执行命令),使用exec命令进入容器后用exit退出容器,容器仍在运行中。
- docker attach 容器ID:重新进入docker
两者区别:
exec:在外部时即可在容器中打开新的终端,并且可以启动新的进程
attach:直接进入容器启动的命令终端,不会启动新的进程
(6)docker cp 容器ID:容器内路径 目的主机路径:从容器内拷贝文件到主机
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时 、库、环境变量和配置文件。
5.1.1、UnionFS(联合文件系统)
UnionFS(联合文件系统):Union File System(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。UnionFS是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
eg:tomcat镜像很大的原理如下:
tomcat能跑成功,需要依赖jdk8、centos、kernel等
5.1.2、Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含bootloader和kernel(内核),bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的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可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别,因此不同的发行版可以公用bootfs。
以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载
5.1.4、为什么docker镜像要采用这种分层结构呢?
最大的一个好处就是 - 共享资源
有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份base镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。
eg:当第一次下载镜像时会非常慢,后续如果删了再重新下载镜像,会下载特别快。以为第一次下载会有一个缓存,就是为了共享资源,所有的镜像都可以从主机base镜像下载而来。
Docker镜像都是只读的(镜像不可被修改)
当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
docker commit提交容器副本使之成为一个新的镜像
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]
案例演示:
① 从hub上下载tomcat并运行:docker run -it -p 8888:8080 tomcat
② 删除容器中tomcat的doc文件夹
③ 以上面的新的tomcat为模板提交一个新的镜像:docker commit -m="新的的tomcat" -a="ZHB" 上容器的ID:2.0 test/tomcat
④ 启动新的镜像和原来的对比