我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

得到一份新的docker镜像后,如果这个镜像不能使用,无法启动容器。该如何调试修改呢?正常情况下来说,要调试修改docker,就必须进入相关容器,而相关容器报错,无法启动,那么就无法调试。这就成了先有鸡,还是先有蛋的著名悖论了。

苏南大叔在本篇文章描述的内容是:如何修改调试已有的docker镜像。友情出境的是@特总 的cmswingdocker镜像。在这里,对特总提供实验镜像,表示感谢。当然本篇文章,并不是讲述如何使用cmswingdocker镜像的,仅仅是为了说明修改调试docker镜像的步骤而已。

苏南大叔:以cmswing为例,如何调试修改docker现有镜像? - docker-family
以cmswing为例,如何调试修改docker现有镜像?(图3-1)

调试修改docker镜像的整体思路

书接前文,苏南大叔实例化了cmswing的官方0.4版本镜像,但是失败了。docker ps -a的结果,显示Exited (1) 24 seconds ago。那么,如何查找docker的具体失败报错信息呢?又如何修改docker内的逻辑呢?

这个部分比较复杂了,是一系列docker命令的反复组合。基本的思路是这样的:

  • docker run或者docker start一个容器,容器报错。
  • 使用docker logs -f查看报错信息。
  • 使用docker ps -a查看入口文件地址。
  • 删除当前报错的容器,docker rm
  • 使用新的命令参数docker run -it进入新的测试容器,查看入口文件的逻辑,然后修改保存容器内的入口文件逻辑,尽量调试完整,没有错误之后,退出当前容器。
  • 可能需要使用docker start或者docker restart或者docker stop来操作容器,调整运行状态查看效果。
  • 使用docker commit把当前容器,提交为一个新的镜像版本。
  • 删除实验用的的容器,docker rm
  • 重复第一步。docker run一个新的容器,看看效果。

整体的思路有了之后,苏南大叔来分步骤说明一下。docker run或者docker start在上一篇文章里面,已经描述过了。

查看docker日志 ,docker logs -f

因为对应镜像的实例对象,start失败了。在docker ps -a里面显示为:Exited (1)。也就是异常退出的意思。所以,需要仔细查看一下报错信息。

请使用docker ps -a找到对应实例的container id或者names,传递到下一句命令里面。命令行如下:

docker logs -f <containerid>

在本次的实验demo中,这个命令就是:

docker logs -f cms_server

或者

docker logs -f a6a513140715

就可以看到一些报错信息的线索了。对于本文来说,报错信息,并不重要,只要是能看到由报错消息即可。

Error: Cannot find module '/web/cmswing/www/production.js'
    at Function.Module._resolveFilename (module.js:469:15)
    at Function.Module._load (module.js:417:25)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3

查看docker镜像入口文件,docker ps -a

每个镜像或者说容器,都是有个入口文件(命令)的。调试镜像或者容器错误的时候,这个入口文件地址是很重要的。所以,首要的问题,就是要弄清,异常退出的容器的入口文件命令是什么。

当然,这个信息,还是由docker ps -a来查看,这次我们查看的列信息是:COMMAND。对于本文的特约演员cmswing0.4版本镜像来说,这个入口命令是:sh /run.sh
记住这个入口命令,以后会用得到。

删除无用容器,docker rm

既然是容器,理论上来说,这容器里面就是没有重要数据的。如果您的容器里面有重要数据,请不要执行本步骤。通过containerid或者names可以删除掉这个容器。基本命令是这样的:

docker rm <name>

docker run -it,实例化一个新的容器

此步骤就是属于调试的步骤了,对比一下普通的docker run命令。

docker run --name cms_server -v /home/www:/web -p 6080:80 -d registry.cn-hangzhou.aliyuncs.com/docker_open/cmswing:0.4

调试版的docker run -it之最基础版本,命令仅仅多了一个-it,而且没有-v目录映射部分,没有-p端口映射部分,没有-d参数。如下:

docker run -it --name cms_server registry.cn-hangzhou.aliyuncs.com/docker_open/cmswing:0.4 /bin/bash
  • -it,其实是-i-t,大家理解为进入容器的意思,就可以了。
  • -d,容器运行于前台还是后台,加了这个参数后,-it参数基本上就废了,因为进入后台运行了。我们也进不了容器,看不到容器内的情况了。所以,绝对不能加-d参数。
  • -v <宿主路径>:<容器路径>,可以多次调用。因为会影响容器内容逻辑,视情况添加。
  • -p <宿主端口>:<容器端口>,可以多次调用。因为会影响容器内容逻辑,视情况添加。
  • 最后的参数是:<镜像地址/名称>:<版本号>,镜像地址pull回来后,就变成了镜像的名字了。不明白的话,可以使用docker images查看所有镜像信息。
  • <初始命令>。其中<初始命令>这个比较重要,不填的话,就是执行镜像里面默认的。如果定义的话,建议设置为:/bin/bash。就是说进入命令行的意思。

这个多次docker run --name <name>的过程中,因为会创建不同容器并启动,所以很有可能需要配合的命令是docker stop <name>docker rm <name>

通过这种新的docker run -it命令就可以进入到容器内部,进行调试了。可能需要:辅助添加一个或者多个-v-p参数。

docker run -it --name <name> <镜像名称>:<镜像版本> /bin/bash

进入容器后,苏南大叔推荐您:先从入口文件入手,开始调试就行了。docker ps -a可以查看command命令,就是入口文件。

苏南大叔:以cmswing为例,如何调试修改docker现有镜像? - docker_ps_a
以cmswing为例,如何调试修改docker现有镜像?(图3-2)

退出当前容器exit,进入宿主机

退出当前容器的命令是:

exit

退出容器后,如果想再次进入这个运行中的容器的话,使用这样的命令即可:

docker exec -it  <containerid>  /bin/bash

提交为一个新的镜像版本,docker commit

如果反复实验调试,确认无误完毕后,就需要把当前的容器,commit为一个新的镜像版本。基本套路是这样的:

docker commit <container_id> <image_name>:<tag>

比如:使用docker ps得到当前令人满意的容器的id是4ce44545cfd71。苏南大叔把他定义为cmswing镜像的0.5版本。

docker commit 4ce44545cfd7 registry.cn-hangzhou.aliyuncs.com/docker_open/cmswing:0.5

这里值得说明的是:<image_name>:<tag>这个组合是可以随意覆盖的。并没有重名提示。而且,这个提交的话,也仅仅保存在宿主机上面,并不影响其他人。

commit的时候,要注意一个重要事项,就是当前的入口文件是什么。因为默认的调试情况下,入口文件是/bin/bash。而commit之后,再run出来的镜像,默认的入口地址,也会是/bin/bash

所以,很有可能发生的操作是:

docker run -it .... /bin/bash
exit
docker commit .....
docker stop ...
docker start ...
docker rm ... (-f)
docker run ..... sh run.sh
docker commit .....
docker stop ...
docker rm ...  

这个时候得到的镜像,才是最符合要求的.... 有点复杂对吧....加油!

镜像调试步骤补充docker imagesdocker rmi

用户查看镜像列表的辅助命令,如下所示,注意是images,复数s

docker images

苏南大叔:以cmswing为例,如何调试修改docker现有镜像? - docker-images
以cmswing为例,如何调试修改docker现有镜像?(图3-3)

删除不满意的镜像的方式是:

docker rmi <镜像id>

<镜像id>来自于docker images里面的IMAGE ID这一列。比如:

docker rmi 515ec1cf6d92

总结

通过本文的一系列操作,就可以修改调试一个新的镜像了。是不是有些复杂了... 苏南大叔表示:如果您有更好的思路,欢迎提供给苏南大叔。谢谢。

更多苏南大叔编写的docker相关的经验文章,请猛击下面的链接查看。

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   docker    cmswing