当前位置: 首页 > 科技观察

如何优雅地使用Docker?请收下这15条快速有效的小窍门

时间:2023-03-14 17:42:09 科技观察

获取最近运行的容器id这是我们经常用到的操作。根据官方的例子,你可以这样做,但是这种方法需要你给ID赋值,如果你直接输入命令,这样做不是很方便。Tip1获取最近运行的容器的id这个是我们经常用到的操作,按照官方的例子,可以这样做(环境ubuntu):这个方法在写脚本的时候很有用,比如你想获取batchesin脚本ID,然后继续。但是这个方法需要你给ID赋值。如果直接键入命令,这样做不是很方便。这时候可以换一种方式:dockerps-l-q命令会返回最近运行的容器的id,通过设置别名(alias),dl命令是获取最近的容器的id。这样,就不需要再输入冗长的dockerps-l-q命令了。通过两个斜引号",可以得到dl命令的值,即最近运行的容器的id。Tip2尽量在Dockerfile中指定要安装的软件,而不是直接在容器的shell中安装软件Docker容器。说实话,有时候我也喜欢在shell中安装软件,也许你也一样。我喜欢把所有的软件都安装在shell中。但是,经过一番努力,我终于发现你仍然需要在Dockerfile中指定安装文件。要在shell中安装软件,您必须这样做:然后输入以下命令来安装文件:然后调用exit:退出docker容器,然后将一个复杂的JSON字符串传递给dockercommit命令以提交新镜像:太麻烦了,不是吗?下面我们在Dockerfile中指定安装文件,只需两步:1.在一个小的Dockerfile中,指定当前运行的镜像作为FROM命令的参数2.然后在Dockerfile中指定一些docker命令,比如CMD,ENTERPOINT,VOLUME等等来指定安装的软件Tip3Super-Super-SuperUser你可能需要一直使用超级用户来操作docker,就像早期的例子一直提示:哇!连续三个sudo!三次成为“超级用户”,才是真正的“超级超级超级用户”!别着急,设置好之后,以后就不用敲那么多sudo了!Tip4清理垃圾如果要删除所有停止的容器,使用这个命令:对了,dockerps命令很慢,不知道为什么这么慢,按理说Go语言很快速地。dockerps-a-q命令列出所有容器的id,然后根据id删除容器。dockerrm命令遇到运行中的容器就会失败,所以这个命令完美的删除了所有没有运行的容器。Tip5分析dockerinspect输出的利器:jq要过滤dockerinspect的输出,一般情况下,配合grep命令,需要这样做:哦!看起来比较复杂,我们用jq专业分析一下dockerinspect的输出结果,更易读易用:第一个'.'代表所有结果。'[0]'表示数组的第一个元素。就像JavaScript访问JSON对象一样简单方便。Tip6镜像有哪些环境变量?有时,您需要知道您创建的图像具有哪些环境变量。简单的!就这样:输出结果如下:调用env查看环境变量,这对后面要说的“链接”(-link)很有用。连接两个容器时需要这些环境变量。详情请看最后一点“链接”。Tip7RUN命令vsCMD命令Docker的新手用户更容易混淆RUN和CMD这两个命令。RUN命令在构建(Build)Docker时执行,CMD命令此时不执行。CMD命令只有在执行RUN命令时才会执行。理清关系,假设Dockerfile的内容如下:我们要在系统中安装一些软件,那么:构建时执行RUN,运行时执行CMD,也就是说CMD是最后执行的命令通过图像。Tip8CMD命令与ENTRYPOINT命令又是两个容易混淆的命令!我们不会谈论具体的细节。例如,假设一个容器的Dockerfile指定了CMD命令,如下:另一个容器的Dockerfile指定了ENTRYPOINT命令,如下:运行第一个容器:Result:运行第二个容器:Result:看出区别了吗?其实CMD命令是可以改写的。当dockerrun后输入的命令与CMD指定的命令相匹配时,CMD指定的命令将替换为dockerrun中的命令。ENTRYPOINT指定的命令只是一个“入口”,dockerrun之后的所有内容都会传递给这个“入口”,而不是替换命令,所以结果是“echohello”。Tip9Docker容器有自己的IP地址吗?刚接触Docker的人可能会有这样的疑问:Docker容器有自己的IP地址吗?Docker容器是一个进程吗?还是虚拟机?嗯……也许两者兼而有之?哈哈,其实Docker容器确实有自己的IP,就像进程有IP一样。只要执行命令查看宿主机和Docker容器中的ip就知道了。查看宿主机的ip:得到结果:查看Docker容器的ip:得到结果:两者不一样,说明Docker容器有自己的ip。Tip10是一个基于命令行的瘦客户端,使用UNIXSocket和Docker后台服务的REST接口进行通信。默认情况下,Docker使用UNIX套接字进行通信。一直到0.5、0.6左右的版本,还是使用端口进行通信,但现在改为UNIXsockets,所以外部无法控制Docker容器的内部细节。接下来我们来做点有意思的事情,从宿主机链接到docker的UNIXsocket:连接成功后,输入:回车然后按两个回车,第二个回车表示输入结束。那么,结果应该是:有一天,我不小心把commit的名字打错了,名字是以“-xxx”开头的(我把命令和选项的顺序搞混了),所以我删除的时候出现了问题,dockerrm-xxx会将-xxx作为参数而不是图像的名称。所以只好直接通过socket连接容器调用RESTServer来删除错误的东西。Tip11将镜像的依赖关系绘制成图dockerimages命令有一个很酷的选项:-viz,可以将镜像的依赖关系绘制成图,并通过管道符号保存到镜像文件中:这样,生成宿主机当前路径创建一个png图片,然后用python启动一个微型HTTP服务器:然后在另一台机器上用浏览器打开:OK,依赖关系一目了然!(译者注:要使用dot命令,宿主机必须安装graphviz包。另外,如果宿主机ip没有绑定域名,只需将machinename替换为宿主机的ip即可。)Docker实际上把所有东西都放在/var/lib/docker路径下。切换到超级用户,查看/var/lib/docker下,可以学到很多有趣的东西。执行如下命令:可以看到很多目录,containers目录当然是存放容器(container),graph目录存放image,filesystem层(文件系统层)存放在graph/imageid/layer路径,所以你可以看到文件层中有什么。使用这种层次结构,你可以清楚地看到文件层是如何一层层叠加的。Tip13Docker源代码:Go,Go,Go,Golang!Docker的源代码全部是用Go语言编写的。Go是一种非常酷的语言。其实不仅仅是Docker,很多优秀的软件都是用Go写的。对我来说,在Docker源文件中,有4个是我非常喜欢阅读的:commands.godocker的命令行界面,是对RESTAPI的轻量级封装。Docker团队不希望命令中有逻辑,因此commands.go只是将指令发送到RESTAPI,使其粒度更小。api.goRESTAPI路由(在commands.go中接受请求,转发到server.go)server.go大部分RESTAPI实现buildfile.goDockerfileparser有小伙伴惊叹“哇!Docker是怎么实现的?!我可以”不懂!”没关系,Docker是开源软件,看看它的源码就知道了。如果不知道Dockerfile中的命令是什么,直接去buildfile.go了解一下。Tip14运行几个Docker后台程序,然后退出容器,会发生什么?好的,倒数第二个要点。如果在Docker中运行多个守护进程并退出Docker容器,会发生什么情况?答案是:不要这样做!因为这样做,所有后台程序都丢失了。使用Dockerfile中的RUN命令启动后台程序,如:这样的话,RUN命令启动的后台程序就会丢失。调用容器的bash连接容器的shell:然后调用psaux查看进程,会发现postgres进程还没有启动。RUN命令影响文件系统。因此,不要启动Dockerfile中的后台程序,而是将后台程序作为前台进程启动。或者按照一些专家的建议,写一个启动脚本,在脚本中启动这些后台程序或进程。Tip15容器之间的友好交流:链接这是最酷的功能!我把它留到结局了!这是0.6.5中最重要的新特性,我们之前已经提到过两次。运行一个容器并给它一个名字。在下面的示例中,我们使用-name参数为容器指定名称“oldb”:运行另一个容器并添加-link参数以连接到第一个容器(别名是loldb),并为第二个容器分配一个别名容器(这里用的是cheez):顺便获取cheez的环境变量:这样我们就在两个容器之间建立了一个网络通道(桥)。基于此,我们可以创建一个类似rails的程序:一个容器可以访问数据库容器而不暴露其他接口。很酷!数据库容器只需要知道第一个容器的别名(在本例中为cheez)和要打开的端口号。所以数据库容器也可以使用env命令查看这个端口是否开放。