提交Docker容器为新镜像后CMD丢失,如何无需重建设置CMD?
首先得说清楚你遇到的问题:当你用docker run -it stock_image sh启动容器时,其实已经覆盖了原镜像的默认CMD(比如php:7.2.5-fpm-alpine3.6的默认CMD是["php-fpm"]),容器的启动命令变成了sh。当你提交这个容器为新镜像时,Docker会默认把容器最后运行的命令作为新镜像的CMD,所以原有的php-fpm CMD就丢失了。
下面给你几个不用重新写Dockerfile也能设置CMD的方法:
1. Commit时直接用--change参数指定CMD
这是最适合你场景的方法,在docker commit的时候直接修改镜像的CMD(或者ENTRYPOINT),不用额外构建步骤:
# 替换成你的容器ID/名称,指定原镜像的CMD docker commit --change='CMD ["php-fpm"]' [容器ID/名称] new_image
这样生成的new_image就会保留php-fpm作为默认启动命令,和原镜像一致。你也可以用这个参数修改ENTRYPOINT,比如--change='ENTRYPOINT ["php-fpm"]',根据原镜像的配置来选择。
2. 启动容器时临时覆盖CMD
如果只是临时启动容器时需要指定命令,不用修改镜像本身,可以在docker run时直接追加命令:
docker run -d new_image php-fpm
这个命令会覆盖镜像的默认CMD,直接运行php-fpm。但缺点是每次启动都要手动添加,适合临时测试场景。
3. 在docker-compose.yml中用command字段设置
完全可以!docker-compose的command字段就是用来覆盖镜像默认CMD的,写法很简单:
version: '3' services: php-fpm: image: new_image command: php-fpm # 其他配置比如端口、挂载等可以按需添加
这样每次执行docker-compose up都会自动运行php-fpm,不管镜像本身的CMD是什么,完美适配你修改后提交镜像的场景。
最后补充一句:虽然commit加--change能快速解决问题,但如果你的扩展安装步骤固定,还是建议写成Dockerfile,这样镜像构建过程可重复、可维护,下次需要更新的时候直接重新构建就行,比手动修改容器再提交更可靠。不过如果只是临时修改测试,上面的方法完全够用。
内容的提问来源于stack exchange,提问作者rho

