二、Docker基本操作
目录
镜像操作
docker –help可以看到所有命令
镜像命令练习
网站: Docker Hub Container Image Library | App Containerization
镜像命令练习
docker save让镜像变成压缩包
下面我们删除镜像,然后重新加载镜像
容器操作
暂停和停止的差别在于操作系统的处理方式,如果容器进入暂停状态,操作系统会将容器内的进程挂起,容器关联的内存暂存下来。CPU不再执行这个进程。但是如何把它恢复了呢?内存空间恢复,程序接着运行,那么我们这个容器不就进入运行状态了吗?但是停止不同,停止意味着你不想玩了呀,那么我们的操作系统可就不客气了,他直接把你这个进程杀死,容器所占的内存回收。那保留下来的仅剩容器的文件系统了,也就是一些静态的东西,这就是暂停和停止的差别了,因此一旦停止,它是没有办法恢复的,因为进程经常已经被杀死了呀,人死了还怎么复活了?那你能做的是干什么呀?还是重新生一个,怎么生?docker start,那么这个时候,它会创建一 个全新的进程,就等于你投胎了。这就是容器的三种状态了。
还有一个命令是叫docker rm删除容器,注意了,docker rm可不是docker rmi,我们上节课讲的rmi是指删除镜像,因为那个i指的是images,而这一个没有i,所以他删的是容器,删容器,它不仅仅是把进程干掉,内存回收,包括硬盘上的文件系统,彻底给你干掉。也就是说干干净净的,再也没有这个东西了,毁尸灭迹,永远见不到了。
docker run --name containerName -p 80:80 -d nginx
nginx后面没有跟版本,其实就是默认最新版
docker ps
docker ps命令用来展示所有运行中的容器
docker ps -a
docker ps -a命令是用来展示所有所有的容器,包括未运行的容器
它我们访问宿主机,宿主机和docker容器之间有映射关系。
#带 -f 持续查看日志,最后面是容器的名称 docker logs -f myContainer
容器操作案例
回车,可以看到我们的后面发生了变化,你可以看到后面,原来是localhost,现在变成了这么一串数字,你发现跟这个容器的ID是完全一样,这证明我们确实是进入容器的内部了。那我现在在容器内部的哪个地方呢?我们既然能用bash命令,那咱们以前的一些命令应该都能用吧?比方说pwd,竟然是在/,根目录吗?那我再来个ls试试,你可以看到这里边儿有lib 、root,var,tmp等等各种各样的目录,这些大家都见过,是我们Linux系统的跟目录结构,没错,这个我以前给他讲过容积的内部它其实会有自己的一套文件系统,当然你看起来好像跟Linux系统的目录一样,但其实是一个阉割版的系统,那里只有nginx运行它自己需要的。
那我现在想找找nginx在哪个目录。我也不知道啊,那只有谁知道啊?是不是只有nginx的这个镜像的作者啊?因为他在创建镜像的过程中他需要去安装nginx,指定nginx的运行目录,这些事情是不是都是他自己决定的呀?那因此我必须得问它的作者。那它的作者是谁呀?是不是dockerhub的官方啊,那怎么去找呢?大家来看这里有这么一段儿啊。Hosting some simple static content就是去设置一些静态内容,怎么去设置?看这一句话,static-html-directory静态页面的文件夹,在哪儿呢?/usr/share/nginx/html这个目录下,那也就是说静态文件应该是放到这儿来了,
那我们回到控制台来试一试呗,采用一个cd命令,到这个目录下,ls查看一下,有没有看到两个文件呀?一个是50x.ml,一个是index.html,index.html显然就是我们要修改的那个首页了。
我们可以先看一眼index.html,可以看到这个显示Welcome to nginx!,而我现在就要把它改成“传智教育欢迎您”,我该怎么样修改一个文件?vi命令吧,命令找不到,为什么找不到的?
刚才我还在说呢,我们讲镜像封装时只是应用能力所需要的必备的函数库和一些命令,那vi跟我们nginx有什么关系啊?所以我们镜像根本就没有封装这个命令,并向内部的文件系统还有函数库都是阉割版,它需要什么呢?那现在完了。没有vi命令,我还怎么修改这个文件,修改页面除了进入页面。
还有一个办法的是通过一个命令直接去替换,这个命令的作用就是利用 “传智教育欢迎您” 去替换Welcome to nginx。而第二行的是利用这个<meta charset="utf-8">,替换原始<head>#<head>的标签,这样可以让我们的编码支持中文。
怎么知道是否修改了呢?通过浏览器在试一下就知道了,我们打开浏览器,我在这儿刷新一下,“传着教育欢迎”您终于见到了,证明我们这个修改他成功了,我们这个案例他就实现了。
那现在我们的案例也做完了,这个容器啊,我想把它停掉,我该怎么做?大家还记得我们之前聊过这个命令吗?我们来试一下。
首先我们先退出容器啊,exit命令退出来,然后docker ps,看到它正在运行中,我们的命令叫docker stop后边跟着容器名称,那是不是真的停掉了?docker ps看一下?没有了。
docker ps默认只能查看运行中的容器,挂掉的容器看不到。除非你加上 -a 。
现在我想把它再启动呢,我可以通过docker start加上容器名称,回车再来看看docker ps,是不是活过来了。
咱们把这容器删了,还记得那个命令吗?docker rm 加上容器名称,不能删?说你不能删除一运行中的容器。这不行啊,你得先让他停下来才能删,运行不能删啊,不停就不能删了吗?那这么说有点儿麻烦,我每次删我得先停stop再删,能不能强制删呀?咱们来了解一下docker rm吧,–help查看文档,-f强制删除删除运行中的容器,docker rm -f 加上 容器名称吧,再来docker ps -a 看一下,这是真的没有了,他真的被删掉了。好,那么到这里我就演示完了docker容器操作的见命令了,剩下没有演示的,没有讲的都是不太常用的命令啊
看这里有说了一句话,说这个命令虽然可以让我们进入容器修改文件,但是在容器修改文件是不推荐的。为什么不推荐呢?有这么几个原因啊,如果你进入容器内去修改,首先第一点是不方便,你看我们刚才进行修改的时候连vi命令都没有,太麻烦了。第二个原因是你在容器里做的修改其实是没有记录的,就是任何人都不知道,包括你自己。你现在可能知道,你随着时间的推移,过了几个月了,你之前修改过什么?你还有印象吗?而且如果你改的东西多了,是不是更容易忘掉了?所以说,我们不推荐大家在容器内做修改。那我到底应该怎么样去修改其中的文件呢?我们在下节课当中,会给大家去讲解文件修改的正确姿势啊。
数据卷(容器数据管理)
我们发现有一个问题啊,那就是我们的docker容器,它里边的所有文件也好,数据也好,都是跟容器耦合在一起的,因此,给我们带来了很多问题,第一个问题就是不便修改,如果我要去修改数据我不得不进入到docker容器的内部,而里面又没有什么高级的编辑工具,修改起来非常麻烦,第二个问题呢,数据不可复用的问题,这容器内的所有修改都是对可见的,那么你在容器里面一顿改,而且随着时间的迁移,你改的越来越多,可能你自己都不知道改了什么。将来又创建了新的容器,也希望与原来容器达到相同效果时,你会发现呀,也要把原来的所有动作重复的做一遍,也就是说你所说的那些修改对其他的容器是不可能复用的,你不得不重复劳动。第三个问题呢是升级维护困难的问题,数据全部存在容器的内部,如果有一天我们要对容器的版本进行升级,那老的容器是不是必须在删掉啊?容器一旦删掉,容器里面数据也都全跟着删了。所以,我们必须得想办法解决容器与数据耦合的问题,就是我们这节课要学习的数据卷。
数据卷是一个虚拟目录啊,它指向的是宿主机文件系统中的一个真实的目录。比如说,我这里有一个docker的主机,那么在这个主机上,就会由docker去管理很多很多的数据,而所有的这些数据卷一定会指向宿主机文件系统上的一目录,这个目录是谁呢?就是/var/lib/docker/volumes。
比如我现在利用docker创建了一个新的数据卷,这个数据的名字叫 html,那么我们的docker一定会在这个指定的宿主机文件系统下创建出一个html的真实的目录,比方说我又创建了一个新的数据卷,那么它同样会在/volumes目录下再创建一个真实的目录,然后每一个数据卷都是那一个真实的目录进行映射。你可以认为数据卷,它是一个虚拟的用的,不是存在的,只是一个概念,而真正指向的是这硬盘上的一个真实文件夹。
那我们的容器在创建以后,它就可以使用这个数据卷,比方说我现在有一个容器是nginx容器,我们知道nginx它的目录是在 /usr/share/nginx/html 中,这是容器内的目录。将来,我们如果放任不管,nginx它的所有的html文件,还有一些静态资源文件,都会放到这个目录下,它的所有配置都会放到目录下/etc/nginx/conf,那么就是数据与容器耦合了。
那现在我们可以怎么办呢?我们可以让nginx的内部目录与数据卷进行关联,而当它与数据卷进行关联时,那么这个时候它的本质其实是在跟宿主机文件系统上的这个真实目录进行关联。那么这个时候docker就会去管理这个东西了,比方说我现在在这个容器的目录里写了点儿什么东西,那么这些东西会立即写到宿主机文件系统里面,而反过来如果说我在宿主机文件系统里对还是html文件夹里面的某一个文件进行了修改,那么这种修改也立即会反映到容器内的这样一个目录。也就是说你可以认为他俩就通过html这样一个数据卷,是不是搭起了桥,建立起了联系了。
我们之前所说的几个问题是不是由此就解决了。第一个问题,我们讲的是修改不方便。那现在修改是不是很方便啊?为什么?因为你对宿主机文件系统的一个任意修改,比如html目录下的任意修改,那么一定会立即反映到跟这个对应数据卷关联的容器内部,别说你在这儿改了,容器里面马上就可以看到,你再也不用进入容器内去修改了呀,我们直接在宿主机上面通过高级编辑工具任意修改,是不是很方便?
第二个问题,这个共享的问题吧,现在你对这个容器一顿改,比如说我改了好多好多的配置。那我又创建了一个新的东西,我希望这个配置能够共享过来,那怎么办呀?我可以让这个容器的config目录也来挂载config数据卷,也就是说两个容器是不是可以挂在同一个卷儿啊。那这个时候呢,原来你在这个config目录做的一切修改,那我这个新的容器是不是也能看到。这就是容器共享。
还有第三个,数据的安全删除的问题,将来有一天你要升级版本,结果你把这个容器给删了,没关系啊,因为你容器删了,但数据卷不会跟着被删,数据卷是挂载在容器的那个目录,容器删了,我卷还在,硬盘目录也在,我这边所有数据也都还在。将来你又来了一个新的容器,新版本的,你只要接着挂载这两个数据卷上,那是不是可以共享以前旧的数据了。
操作数据卷
挂载数据卷
如果没有创建数据卷,会不会也会成功
刚刚我们给大家演示了一下怎么样将数据卷挂载到容器目录,而事实上,不仅仅是数据卷,我们的宿主机目录可以直接与容器挂载。所以这节课,我们就会通过案例给大家演示一下这种玩法,那我们的案例要求我们创建并运行一个MySQL的容器,然后,完成宿主机目录的发展,那他的挂载语法和数据卷挂载语法有什么区别呢?
带数据卷模式:宿主机目录 –> 数据卷 —> 容器内目录
直接挂载模式:宿主机目录 —> 容器内目录
可以看到了这种挂载的语法都是以当 -v 开头,然后跟上宿主机目录:容器内目录。我们之前数据卷挂载前半部分数据卷名称,而现在改成了宿主机目录了,因为你是直接将目录与容器内目录挂载的。除了这个差别以外,目录挂载还允许将宿主机文件与容器文件挂载,这种情况下宿主机文件的内容会直接覆盖容器内文件的内容,这可是数据卷当中没有的功能啊。