14
容器命令(上)
可以看到,docker pull centos
下来的centos镜像只有不到200MB,而虚拟机用的centos镜像文件有4G,这就是区别 图1、2、3
1、新建并启动容器 docker run [OPTIONS]IMAGE[COMMAND][ARG...]
图4
-i -t
可以和起来 i是交互,t代表伪终端
root@
后面已经发生改变,现在已经进入到虚拟机centos里面的docker里面的centos命令行终端 图5
2、列出当前所有正在运行的容器 docker ps [OPTIONS]
图10
鲸鱼背上有几个集装箱
docker images
命令下,是IMAGE ID镜像ID,docker ps
命令下是CONTAINER ID容器ID,且它的模板IMAGE镜像
注意到 docker现在正在运行的容器ID是4d56fa33ac08,对应的镜像ID是88ec626ba223,打开的交互式命令终端(伪终端)也是root@4d56fa33ac08
意思就是通过run -it创建了一个容器且进入该容器打开了一个交互式伪终端 图6
这个NAME属于docker给这个容器起的一个名字
3、退出容器 两种退出方式
–》exit
容器停止退出 可见伪终端已关闭,且当前正在运行的容器为空 图7、8 、11
–》ctrl+P+Q
容器不停止退出 可见容器实例仍在运行中 图13、11
大海就是宿主机,鲸鱼就是docker,容器实例就是鲸鱼背上的集装箱
4、启动容器 docker start 容器ID或者容器名
鲸鱼背上的集装箱,一个一个的容器可以关可以开,可以退出可以进入,可以删除可以增加
5、重启容器 docker restart 容器ID或者容器名
6、停止容器(温柔) docker stop 容器ID或者容器名
7、强制停止容器 docker kill 容器ID或者容器名
8、删除已停止的容器 docker rm 容器ID或者容器名
(对比 docker rmi
是删除镜像,docker rm
是删除容器)
删除没有停止的容器(强制删除) docker rm -f
只显示两个当前正在运行容器 docker ps -n 2
一次性删除多个容器 ->docker rm -f $(docker ps -a -q)
->docker ps -a -q |xargs docker rm
linux可变参数,管道符,上一个操作的命令的结果直接作为参数传递给下一个命令 上一个命令查出来的容器ID传给xargs
15
容器命令(下)
上一节讲的是交互式启动容器,就是会开一个伪终端来交互,当我们不需要交互,也就是守护式启动,只在后台运行着
1、启动守护式容器 docker run -d 容器名
图14
但是会发现,在当前正在运行的容器中看不到守护式启动的容器 图15、原因 16
之前是前台有一个交互式终端,后台有一个进程,现在前台没有应用了,后台进程觉得没有用就停了。这是docker的机制。
2、查看容器日志 docker logs -f -t --tail 容器ID
图17
图18
docker run -d centos /bin/sh -c "while true;do echo hello zzyy;sleep 2;done"
以后台的形式运行centos,当true的时候bin/sh(脚本编程)循环的echo打印这句话hello……到控制台上面,这就会使前台有一个响应,后台也不会关闭 图19
3、查看容器内运行的进程 docker top 容器ID
还是因为容器是个简易版的linu环境,大部分linux的命令,容器一样 图20
4、查看容器内部细节 docker inspect 容器ID
5、进入正在运行的容器并以命令行交互 图21
docker run -it centos
等价于 docker run -it centos /bin/bash
因为它默认的方式就是/bin/bash
退出了一个容器后又重新进入 docker attach 容器ID或容器名
在宿主机里面,也就是docker外面就执行容器里面的操作而不进入容器,直接将执行结果返回给宿主机
docker exec -t 容器ID或容器名
命令行操作 图22
所以,退出了一个容器后又重新进入的命令也等价于 图23、24
6、从容器内拷贝文件到主机上 docker cp 容器ID:容器内路径 目的主机路径
图25
有时候想把容器里应用的数据结果保留
16
镜像原理
回到之前讲的问题:tomcat这里的镜像为什么会这么大,460多MB;镜像是一层一层包裹着的
**1)镜像是什么:**图26 整体打包
1、UnionFS(联合文件系统) 图27
2、Docker镜像加载原理
容器就是一个个精简版的linux,bootfs实际上就相当于linux的内核,它是镜像的最底层,就是引导型file system,
rootfs就是linux里面的各种标准文件结构 这就是为什么它那么小,因为内核共用宿主机,硬件不加载,只有bootfs、rootfs这两个,并且自己只需要提供rootfs,即,centos就是centos的文件系统,ubuntu就是ubuntu的文件系统 图28、29
3、分层镜像 图30
pull一个镜像,最终的结果是你看到你pull的镜像名字,但其包含多层镜像,如hello-world包含两层镜像,总共pull了两个镜像 图31
为什么tomcat那么大:实际上pull下来的tomcat有这样的文件层级结构,方框是集装箱 图32
460多MB有jdk等等,构成一个精简版的基于linux平台的tomcat(因为容器是一个精简版的linux)这也就是联合文件系统
4、为什么Docker镜像要采用这种分层结构呢 图33
感受就是第一次下载一个镜像很慢,删掉后第二次下载很快。因为有缓存,又可以共享资源
2)特点 图34
镜像不可改
3)Docker镜像commit操作补充
17
镜像commit
3)Docker镜像commit操作补充
1、docker commit提交容器副本使之成为一个新的镜像
2、docker commit -m=“提交的描述信息”-a=“作者”容器ID 要创建的目标镜像名:[标签名]
3、案例演示: ->从Hub上下载tomcat镜像到本地并成功运行
docker run -it -p 8080:8080 tomcat
(小写p指定端口port)
docker run -it -P tomcat
(大P随机分配)
tomcat端口是8080,冒号前面的是docker对外暴露的端口,不一定是8080,也可以写8888,用小p来指定端口 图35、36
->故意删除上一步镜像生产tomcat容器的文档 图37、38、39
删除的tomcat的说明文档Document
->也即当前的tomcat运行实例是一个没有文档内容的容器,以它为模板commit一个没有doc的tomcat新镜像atguigu/tomcat02 (前面是前缀,命名空间,也就是包名)图40 含义依次是 作者 标准信息 容器名 名字(含包名 版本)
由当前正在运行的容器生成一个对应的新镜像
->启动新镜像和原来的对比 图41、42
区别就是一个有文档一个没文档doc
小结:可以由镜像生成运行的容器实例,也可以由容器实例生成新的自定义的镜像,得到需要的镜像,类似于Java中的反射概念(类和实例之间的信息可以相互得到)
**后台访问tomcat:**结果就没有那么多日志了 图43 与前台交互式运行容器相比 图45 可见两个进程都开启 图44
这就是 -d(后台)和-it(前台)
18
docker容器数据卷
1、是什么 图46 类似于Redis里面的rdb和aof(先不管)主要就是数据共享和数据持久化
容器一旦关闭,容器内的数据就没了,当希望保存部分数据时(持久化)(相当于电脑内存和磁盘之间的关系),用容器数据卷来保存
2、能干什么 容器的持久化+容器间继承+容器间共享数据 图47
补充:docker cp(从容器内拷贝文件到主机上),容器卷就可以实现从容器到主机和从主机到容器的互通
19
docker容器数据卷
3、数据卷 容器内添加
->直接命令添加
1、命令 docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
图48
在docker run -it 镜像名
交互式启动容器,的基础上,加上-v(volum卷的缩写),-v具有新建的功能相当于makdir,能够在宿主机和容器内直接新建不存在的文件夹 宿主机根目录下的myDatVolume,容器根目录下的dataVolumeContainer,两个文件夹数据互通 图49
2、查看数据卷是否挂载成功 docker inspect 容器ID或者容器名
图50 以json串的形式看容器,里面有绑定bind的语句,挂载成功,且可读可写 图51
3、容器和宿主机之间数据共享
效果 图52、53
4、容器停止退出后,主机修改后数据是否同步 图54
容器停止退出后,主机又在互通卷中修改了数据,当再次进入容器之后,容器内的互通卷是否同步了,完全同步。
5、命令(带权限)图55 docker run -it -v/宿主机绝对路径目录:/容器内目录:ro镜像名
read only只读ro
效果 图56、57
20
docker容器数据卷
类比思想:
JavaEE Hello.java–编译---------->Hello.class
docker images镜像-源码级描述-----> DockerFile
就像tomcat运行离不开jdk,所以它还包着一层jdk,这就是它为什么460多MB
例 图58
->DockerFile添加
1、(宿主机)根目录下新建mydocker文件夹并进入
2、可在Dockerfile中使用VOLUME指令来给镜像添加一个或多个数据卷 图59 数组型的json串
这个宿主机上的目录是自定义的,并不是所有的电脑上都有这样一个目录,如果dockerfile允许该操作,反而影响了它的迁移性(就要求使用的电脑都创建一个要求的目录)
3、File构建 图60 先构建一个可执行的shell脚本(可执行的dockerfile脚本)
dockerfile来自于一个父类镜像centos
根目录下面新建两个容器卷
打印这句话,类似于日志,堆?
方式是/bin/bash
翻译成之前的docker命令 类似于 docker run -it -v /host1:/dataVolumeContainer1 -v /host2:/dataVolumeContainer2 centos /bin/bash
,又由于之前讲的迁移性的问题,不支持这个语句,所以现在就是 图60 的命令,在跑起来之后,在当前生成两个数据卷1、2
4、build后生成镜像 获得一个新镜像zzyy/centos 图61、62
-f文件,指明dockerfile在哪儿,-t 命名空间/镜像名字 .在当前目录下面
5、run容器 用自己创建的新镜像交互式启动容器 图66
6、通过上述步骤,容器内的卷目录地址已经知道,对应的主机目录地址哪?
现在是用dockerfile的方式在容器里面建立的容器,宿主机的目录要么是自己指定,要么是使用默认创建
7、主机对应默认地址 在你没有指定宿主机绝对路径时 图64、65
->备注
自己创建的容器卷不能写等出了问题 图63
给权限为true
21
docker容器数据卷
4、数据卷容器
1、是什么 图67
类似于 活动硬盘上面挂活动硬盘,实现数据的传递依赖(起初是宿主机和u盘之间的传递,现在是u盘之间的数据传递)
2、总体介绍
–>以上一步新建的镜像zzyy/centos为模板并运行容器dc01/dc02/dc03
2来自于1,3来自于2
–>它们已经具有容器卷 /dataVolumeContainer1 /dataVolumeContainer2(就是之前自己新建的镜像,规则是运行后自动在容器的根目录生成两个容器卷,名字叫/dataVolumeContainer1 /dataVolumeContainer2)
(就是总共有三个运行起来的容器dc1、2、3,每个容器的根目录都有自己的数据卷/dataVolumeContainer1、2)
3、容器间共享传递(–columes-from)
1、先启动一个父容器dc01 图68 在(容器dc01的)数据卷dataVolumeContainer2新增内容(dc01_add.txt)图73
2、dc02/dc03继承自dc01
->volumes-from 图70
->命令 dc02/dc03分别在dataVolumeContainer2各自新增内容
(dc02_add.txt,dc03_add.txt) 图71
3、回到dc01可以看到02/03各自添加的都能共享了 (即儿子的操作,在父会有) 图74
(且子之间也互通有 图75)(蓝色为ctrl+P……以前的命令,不停止退出容器,再接着进入attach容器dc02)
4、删除dc01,dc02修改后dc03可否访问 (即父不存在,子之间是否互通) 图76、77
(别忘了ctrl+P……,不停止退出容器,再接着进入attach容器dc03)图78
5、删除dc02后dc03可否访问
6、新建dc04继承dc03后再删除dc03 图79、80
结论:容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止
22
DockerFile解析
有linux基础,懂git和mavon的理念 ,mavon也是 mavon build,然后编译成一个jar包,然后java -jar ms……运行微服务
异曲同工之妙
用DockerFile写容器卷的时候主流步骤 图81
1、是什么 图82、83、84
scratch类似于java的Object类,所有镜像的祖先base image基础镜像,MAINTAINER作者加邮箱,LABEL标签,说明的意思,CMD默认运行命令
23
2、DockerFile构建过程解析
图86
红字后面的内容不能为空,相当于空指针,就是语法格式有问题的报错。
保留字指令就是红色的字。
所以说镜像是一层层的
图87
24
3、Dockerfile体系结构 图90、91、92、93
继承的镜像,作者的名字和邮箱,构建时需要执行的额外的一些命令,创建容器(镜像变成运行实例)运行时对外的端口号, 一进来之后是在哪个目录(不特殊指明就是根目录),像设置环境变量一样,copy就是copy(shell脚本的写法和json串的写法),add就是copy+自解压功能,
经典的考题:CMD和ENTRYPOINT是什么意思-->第一句都一样;区别是,CMD最后一条命令会覆盖上面的命令,ENTRYPOINT最后一条命令是追加,最后一个是留了一手的触发器
25
4、案例 就是对从Hub上拉下来的镜像增加了vim和ifconfig命令的配置做成新的镜像图95、96、99、98、100、101、102、103、104
复习一个批量删除的操作,把小括号里的结果传给括号外面的命令,类似于linux的管道操作 图97
图104可见 顺着加载,倒着执行,类似于栈
26
图105、106
图106 相当于CMD ls -l命令(现在执行结果 图109)将CMD[“catalina.sh”,“run”]命令(原本执行结果 图110、108)覆盖了,
等于登陆了以后就执行了一个ls -l /usr/local/tomcat操作 图107
所以说最后就成了现在的这个tomcat根本就没有启起来(因为CMD[“catalina.sh”,“run”]命令没有执行)图111
图112、113
CMD版本的一旦做出来,无法灵活的增加新命令,ENTRYPOINT版本可以,更优 图113
图114、115 curl会返回对应网址的表单,curl命令解释 图116,加i 图117 为什么 图119、118、120
把之前的CMD写成ENTRYPOINT,命令覆盖变成了命令追加,docker run myip -i就可以使用了 图121
27
图122、123
有哪个子镜像继承了,父镜像就会打印这句话 图124、125、126,现在继承最新的这个会打印这句话的镜像 图127、128、129 红色句执行了一个build触发器Trigger0 图130、131 是父类的被执行
28
并且和连接符,写的是一行 图132 不是dockerfile是linux脚本编程shell 图133
图134 目录内容 图135 dockerfile内容 图136、137
拷贝且重命名成cincontainer.txt
加载的最底层是centos,接着装jdk,tomcat,add是解压缩以后拷贝,启动时运行tomcat的三种写法对比,CMD的json串形式,ENTRYPOINT的json串形式,tail -F 追加,读日志
构建(且是在当前路径,和上面的操作不一样,因为上面的是为了提示路径是什么docker -f ……) 图139 构建完成 图138
run 图140 -d后台,-p指定容器暴露端口,name容器名,-v添加了两个容器卷,且现在宿主机目录和容器目录是多对多,也就是多个一对一,tomecat的webapps是发布web工程的,里面的test文件内容,宿主机和容器会共享,那么容器里的tomcat可以跑微服务和各种工程(感觉讲的不是很好),写权限为true
现在是后台运行,所以要进行一切操作要通过docker exec命令从外面对容器进行操作。
验证 图141
将test发布
29
将test发布
图142 概述图143 一个标准的web工程 需要的配置文件web.xml 图144 a.jsp 图145 "i am……"在前台,"System.……"在后台,根据之前的描述,宿主机建立的web工程,在容器里面也会有,容器重启一下看 图146
在tomcat下面布了test工程,而且可以访问a.jsp 图147 现在宿主机修改a.jsp内容,数据卷数据共享,容器内容可直接改变 图148 且访问了三次,docker后台都可以查到日志 图150、149
30
小总结
图151 dockerfile是在宿主机编写的,dockerfile经过build形成本地镜像,run镜像变成具体的容器实例,容器commit形成新的镜像,各种版本标签号tag,pull拉镜像,上传镜像push(后提)
31
Docker常用安装 图152
以前连本机数据库,现在是连docker上面的数据库,再后面连阿里云,就再也不用装本地的了
总体步骤 图153 安装tomcat 图154 是否成功拉取到tomact
使用tomcat镜像创建容器(也叫运行镜像) docker run -it -p 8080:8080 tomcat
图156
安装mysql 图157
1、 图158
2、 图159
3、 图160
->使用mysql镜像 图161 mysql端口是3306,容器暴露端口是12345,-d后台运行,版本5.6,name容器名字,-v容器卷 配置、日志、data存在哪儿,配置环境root密码是123456,开始交互运行 图162、163 已经进入到对应容器,且进入到容器里面的数据库 图164 现在数据库db01里有表t_book 图166
->外部win10(宿主机)也来连接运行在docker上的mysql服务 查看宿主机ip,sql数据库软件连接ip 图168、167 增加内容且保存 图169 进docker查看 图170
->数据备份小测试(可以不做) 通过docker操作docker上面的mysql完成数据的备份 图171、172 用docker执行这个容器且该容器上装了mysql,执行mysql dump命令,所有数据库按照用户名和密码,导出到宿主机的zzyyuse/all……这个路径下面形成这个文件
32
(Redis是一个key-value存储系统,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、key-value数据库,并提供多种语言的API)
安装Redis 图174
1、 图175
2、 图176
1、 图177 -p宿主机容器暴露端口,Redis端口,Redis配置文件的文件夹,叫redis.conf
2、 redis.conf文件夹里有着redis.conf文件,如 希望docker上的redis端口不是6379,需要主机上提供一个configure文件,映射到容器里面,然后改主机的,容器的也作用了以后,再重新修改(感觉讲得不好) 图178
注意不要绑定到主机,注释掉(就像容器卷讲过没有绑死这种说法,迁移性) 图179
-d后台,启动命令中已经把 redis-server 写进去了,否则redis服务就不会up
3、 redis client连上redis erver 图180、181
4、 针对appendly 有data文件 图182 对应这一句 图183 查看有文件 图184
33
本地镜像推送到阿里云
图185
1、 图186、187
2、 图188