0
点赞
收藏
分享

微信扫一扫

docker-entrypoint.sh入口文件说明

码农K 2022-08-24 阅读 110

1、set -e

编写的每个脚本都应该在文件开头加上set -e,告诉bash如果任何语句执行结果不是true则应该退出;
也可以使用set -o errexit增加可读性,作用与set -e相同。

2、set -o pipefail

在执行错误之后立即退出,不要向下在执行了。而 -o pipefail的作用域是管道,也就是说在Linux脚本中的管道,如果前面的命令执行除了问题,应该立即退出。

3、shopt -s nullglob

在使用Linux通配符时,如果没有匹配到任何文件,不会报No such file or directory,而是将命令后面的参数去掉执行。

4、if [ "${}1:0:1" = '-' ]; then

这是一个判断语句,在官方文档中已,上一行已经给出了注释:if command starts with an option, prepend mysqld;
这个判断语句是${1:0:1}意思是判断$1(调用该脚本的第一个参数),偏移量0(不偏移),取一个字符(取字符串的长度);
如果判断出来调用这个脚本后面所跟的参数第一个字符是“-”中横线的话,就认为后面的所有字符串都是mysqld的启动参数。
上面的这个操作类似于Python的字符串切片。

5、set -- mysqld "$@"

在上面判断完第一个参数是-开头之后,紧接着执行了set -- mysqld "$@"这个命令,使用了set --的用法。set --会将他后面所有以空格区分的字符串,按顺序分别存储在$1,$2,$3变量中,其中新的"$@"为set --后面的全部内容。
例如:bash docker-entrypoint.sh -f xxx.conf
在这种情况下,set -- mysqld "$@"中的"$@"的值为-f xxx.conf
当执行完set -- mysqld "$@"这条命令后:
$1=mysqld
$2=-f
$3=xxx.conf
$@=mysqld -f xxx.conf
可以看到, 当执行 docker-entrypoint.sh脚本的时候后面加了-x形式的参数之后, $@的值发生的改变, 在原有$@值的基础之上, 在前面又预添加了mysqld命令。

6、exec "$@"

几乎在每个docker-entrypoint.sh脚本的最后一行,执行的都是exec "$@"命令;
这个命令的意义在于你已经为你的镜像预想到了应该有的调用情况, 当实际使用镜像的人执行了你没有预料到的可执行命令时, 将会走到脚本的这最后一行, 去执行用户新的可执行命令。

7、情况判断

上面直接说了脚本的最后一行, 在之前的脚本中, 需要充分的去考虑你自己的脚本可能会被调用的情况. 还是拿 MySQL 官方的 dockerfile 来说, 他判断以下情况:
开头是 - , 认为是参数的情况
开头是 mysqld, 且用户 id 为0 (root 用户) 的情况
开头是 mysqld 的情况
判断完自己应用的所有调用形态之后, 最后应该加上exec "$@" 命令兜底

8、${mysql[@]}

Shell中的数组,直接执行${mysql[@]}会把这个数组当作可执行程序来执行。
mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )
echo ${mysql[1]}
-- output: mysql
echo ${mysql[2]}
--output: --protocol=socket
echo ${mysql[3]}
--output: -uroot
echo ${mysql[4]}
--output: -hlocalhost
echo ${mysql[@]}
--output: mysql --protocol=socket -uroot -hlocalhost --socket=

9、exec gosu mysql "$BASH_SOURCE" "$@"

这里的gosu命令, 是 Linux 中 sudo 命令的轻量级”替代品”;
gosu是一个golang语言开发的工具, 用来取代shell中的 sudo 命令。 su和sudo命令有一些缺陷, 主要是会引起不确定的TTY, 对信号量的转发也存在问题。如果仅仅为了使用特定的用户运行程序, 使用su或sudo显得太重了, 为此gosu应运而生。
gosu直接借用了libcontainer在容器中启动应用程序的原理, 使用/etc/passwd处理应用程序。gosu首先找出指定的用户或用户组, 然后切换到该用户或用户组。接下来, 使用exec启动应用程序。到此为止, gosu完成了它的工作, 不会参与到应用程序后面的声明周期中。使用这种方式避免了gosu处理TTY和转发信号量的问题, 把这两个工作直接交给了应用程序去完成。


举报

相关推荐

0 条评论