以cmswing为例,如何调试修改docker现有镜像?
发布于 作者:苏南大叔 来源:程序如此灵动~得到一份新的docker
镜像后,如果这个镜像不能使用,无法启动容器。该如何调试修改呢?正常情况下来说,要调试修改docker
,就必须进入相关容器,而相关容器报错,无法启动,那么就无法调试。这就成了先有鸡,还是先有蛋
的著名悖论了。
苏南大叔在本篇文章描述的内容是:如何修改调试已有的docker
镜像。友情出境的是@特总 的cmswing
的docker
镜像。在这里,对特总提供实验镜像,表示感谢。当然本篇文章,并不是讲述如何使用cmswing
的docker
镜像的,仅仅是为了说明修改调试docker
镜像的步骤而已。
调试修改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
。对于本文的特约演员cmswing
的0.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
命令,就是入口文件。
退出当前容器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 images
和docker rmi
用户查看镜像列表的辅助命令,如下所示,注意是images
,复数s
:
docker images
删除不满意的镜像的方式是:
docker rmi <镜像id>
<镜像id>来自于docker images
里面的IMAGE ID
这一列。比如:
docker rmi 515ec1cf6d92
总结
通过本文的一系列操作,就可以修改调试一个新的镜像了。是不是有些复杂了... 苏南大叔表示:如果您有更好的思路,欢迎提供给苏南大叔。谢谢。
更多苏南大叔编写的docker
相关的经验文章,请猛击下面的链接查看。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。