分析MySQL 5.6的Dockerfile(2)

if ! kill -s TERM "$pid" || ! wait "$pid"; then
            echo >&2 'MySQL init process failed.'
            exit 1
        fi

echo
        echo 'MySQL init process done. Ready for start up.'
        echo
    fi

chown -R mysql:mysql "$DATADIR"
fi

exec "$@"

说明如下:

1> set -e, Manual文档的说明如下:

Exit immediately if a pipeline (which may consist of a single simple command), a subshell com‐
mand enclosed in parentheses, or one of the commands executed as part of a command list
 enclosed by braces (see SHELL GRAMMAR above) exits with a non-zero status.

这句语句告诉bash如果任何语句的执行结果不是true则应该退出。这样的好处是防止错误像滚雪球般变大导致一个致命的错误,而这些错误本应该在之前就被处理掉。

关于set -e的利弊,可参考一下两篇博客

(1)Unix/Linux 脚本中 “set -e” 的作用

(2)linux中的set命令: "set -e" 与 "set -o pipefail"

2>

if [ "${1:0:1}" = '-' ]; then
    set -- mysqld "$@"
fi

用于判断该脚本后面的参数是否以“-”开始,它考虑的是启动mysqld是带参数的情况,如果有的话,就将mysqld和参数作为变量存到$@中。

关于set --,Manual文档的说明如下:

If no arguments follow this option, then the positional parameters are unset. Otherwise, the
 positional parameters are set to the args, even if some of them begin with a -.

验证如下:

首先构造脚本

[root@localhost ~]# cat 4.sh
#!/bin/bash
if [ "${1:0:1}" = '-' ]; then
        set -- mysqld "$@"
fi
echo '$@: '"$@"
echo '$1: '"$1"

加入参数进行验证

[root@localhost ~]# sh 4.sh 123
$@: 123
$1: 123
[root@localhost ~]# sh 4.sh -123
$@: mysqld -123
$1: mysqld
[root@localhost ~]# sh 4.sh -123 456
$@: mysqld -123 456
$1: mysqld

补充一点:关于$@与$*的区别,$@指每个位置参数参数都是一个独立的""引用字串,这就意味着参数被完整地传递,而$*则指所有位置参数只被一个""引用,相当于一个参数。

3>

if [ "$1" = 'mysqld' ]; then

如果$1为mysqld,则执行下面的代码,如果不是,则执行该脚本最后一行的exec "$@"。

注意:Dockerfile中的CMD命令为 ["mysqld"],CMD命令其实就是ENTRYPOINT的参数,譬如如果ENTRYPOINT命令为ls,则CMD命令为-l,则实现的效果就是ls -l,

在启动容器时,自己输入的命令其实是覆盖CMD参数的,具体在本例中,就意味着在启动容器时,自已输入的命令只有在三种情况下才会启动mysqld服务:一、mysqld(相当于CMD参数)。二、以“-”开始的参数列表,这样上述2中的脚本才会判断为真。三、mysqld + 以“-”开始的参数列表。除此之外,其它所有的命令都不会启动mysql server服务,而是直接执行自己输入的命令。

4>

DATADIR="$("$@" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')"

获取mysql server的数据目录,倘若我们没有输入任何以“-”开始的参数列表,则$@为mysqld,上述命令执行的结果如下:

[root@localhost ~]# mysqld --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }'
/var/lib/mysql/

5>

if [ ! -d "$DATADIR/mysql" ]; then

如果存在/var/lib/mysql/mysql目录存在文件,则跳过中间的步骤,直接执行chown -R mysql:mysql "$DATADIR",它这里判断的一个依据是,如果/var/lib/mysql/mysql存在文件,则代表mysql server已经安装,这时就无需安装(当然,如果强行安装的 话,可能会覆盖),直接将其属主修改为mysql用户。很多童鞋可能好奇,不是新建的镜像么?这个目录怎么可能存在呢?我当初也存在这样的疑惑,后来验证了一番,发现如果将宿主机的目录直接挂载到镜像的/var/lib/mysql下,则启动mysql镜像时,没有进行mysql的初始化,设置root密码等,直接启动mysql服务,具体如下:

[root@localhost ~]# docker run -v /var/lib/mysql:/var/lib/mysql mysql
2015-09-24 02:08:05 0 [Note] mysqld (mysqld 5.6.26) starting as process 1 ...
2015-09-24 02:08:05 1 [Note] Plugin 'FEDERATED' is disabled.
2015-09-24 02:08:05 1 [Note] InnoDB: Using atomics to ref count buffer pool pages
2015-09-24 02:08:05 1 [Note] InnoDB: The InnoDB memory heap is disabled
2015-09-24 02:08:05 1 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2015-09-24 02:08:05 1 [Note] InnoDB: Memory barrier is not used
2015-09-24 02:08:05 1 [Note] InnoDB: Compressed tables use zlib 1.2.7
2015-09-24 02:08:05 1 [Note] InnoDB: Using Linux native AIO
2015-09-24 02:08:05 1 [Note] InnoDB: Using CPU crc32 instructions
2015-09-24 02:08:05 1 [Note] InnoDB: Initializing buffer pool, size = 128.0M
2015-09-24 02:08:05 1 [Note] InnoDB: Completed initialization of buffer pool
2015-09-24 02:08:05 1 [Note] InnoDB: Highest supported file format is Barracuda.
2015-09-24 02:08:06 1 [Note] InnoDB: 128 rollback segment(s) are active.
2015-09-24 02:08:06 1 [Note] InnoDB: Waiting for purge to start
2015-09-24 02:08:06 1 [Note] InnoDB: 5.6.26 started; log sequence number 1697388
2015-09-24 02:08:06 1 [Note] Server hostname (bind-address): '*'; port: 3306
2015-09-24 02:08:06 1 [Note] IPv6 is available.
2015-09-24 02:08:06 1 [Note]  - '::' resolves to '::';
2015-09-24 02:08:06 1 [Note] Server socket created on IP: '::'.
2015-09-24 02:08:06 1 [Warning] 'user' entry 'root@localhost.localdomain' ignored in --skip-name-resolve mode.
2015-09-24 02:08:06 1 [Warning] 'user' entry '@localhost.localdomain' ignored in --skip-name-resolve mode.
2015-09-24 02:08:06 1 [Warning] 'proxies_priv' entry '@ root@localhost.localdomain' ignored in --skip-name-resolve mode.
2015-09-24 02:08:06 1 [Note] Event Scheduler: Loaded 0 events
2015-09-24 02:08:06 1 [Note] mysqld: ready for connections.
Version: '5.6.26'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)

而先前的启动过程则涉及到初始化,启动,显性设置root密码等。

将宿主机的var/lib/mysql/挂载给容器后,我们再来看看宿主机上该目录的权限。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/99928b6f9d32253dda82708cc891ef35.html