最近公司在搞docket容器化部署,对镜像的制作过程比较感兴趣,因为我现在用的镜像都是现成的基础镜像在上面添砖加瓦,我看官网的镜像如mysql redis tomcat都有专门的dockerfile以及各种介质文件,entrypoint.sh,看了一下没看懂太多,请问有比较详细的介绍如何在dockerfile仿照官方镜从零开始像制作镜像的教程吗?
譬如给一个nginx的镜像如何快速的获取它的内置的环境变量,可以设置到启动命令中的env,以及解读entrypoint.sh中不同的参数有什么效果。
最近公司在搞docket容器化部署,对镜像的制作过程比较感兴趣,因为我现在用的镜像都是现成的基础镜像在上面添砖加瓦,我看官网的镜像如mysql redis tomcat都有专门的dockerfile以及各种介质文件,entrypoint.sh,看了一下没看懂太多,请问有比较详细的介绍如何在dockerfile仿照官方镜从零开始像制作镜像的教程吗?
譬如给一个nginx的镜像如何快速的获取它的内置的环境变量,可以设置到启动命令中的env,以及解读entrypoint.sh中不同的参数有什么效果。
1 回答646 阅读✓ 已解决
1 回答592 阅读
2 回答614 阅读✓ 已解决
本质上其实就是写启动脚本(ENTRYPOINT),脚本里可能做一些初始化+启动的工作。
先举个redis的例子,首先redis的dockerfile里面指定了 ENTRYPOINT,也就是容器启动时默认的执行命令。
Dockerfile
docker-entrypoint.sh
再看docker hub 上关于redis的使用说明:
这里启动一个redis实例,没有传任何参数,直接启动容器。所以docker会首先执行ENTRYPOINT的命令,并给ENTRYPOINT添加Dockerfile里面的CMD参数。
最终这个容器执行的命令就是
docker-entrypoint.sh redis-server
。然后再看
docker-entrypoing.sh
脚本的内容。第一个if块,判断CMD参数是不是-开头或conf结尾的参数,所以跳过
第二个if快,判断有没有指定用户,跳过
第三个if快,修改默认权限
最后
exec $@
启动redis-server
所以在没有加参数的时候,直接运行了redis-server。
第二个使用说明:
这里手动指定了
redis-server --save 60 1 --loglevel warning
,添加了参数,这些参数会覆盖Dockerfile里面的CMD指令。当这个容器运行的时候,仍然会去执行
docker-entrypoint.sh
,两个if还是没有匹配到,还是直接到exec $@
, 运行的命令就是redis-server --save 60 1 --loglevel warning
下面再来看一个相对比较复杂的MySQL
这里使用-e指定环境变量(
MYSQL_ROOT_PASSWORD
)和添加CMD参数(--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
)根据Dockerfile的内容,运行容器的时候,可以看到也是调用了
entrypoint.sh
文件。这里直接看
entrypoint.sh
的内容,直接跳到_main()函数,看逻辑还是比较清晰的。也有注释。读取环境变量这一步在
docker_setup_db
函数,最后如果要自己实现类似的功能,可以参考他是怎么处理的。