容器化的部署已经是现在企业的家常便饭,Mysql image
的使用也是司空见惯,为了更高效的部署有必要了解一下关于 mysql
镜像的 docker-entrypoint
的那些事儿。mysql
原始的 Dockerfile
中 ENTRYPOINT
对应的 docker-entrypoint.sh
涉及了 Mysql
如何初始化,如何设置密码,如何启动服务等关键问题。
Dockerfile
...
RUN mkdir /docker-entrypoint-initdb.d
...
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306 33060
CMD ["mysqld"]
Dockerfile
的ENTRYPOINT
是docker-entrypoint.sh
, 对于CMD
指令用户可以指定参数,最后附加到ENTRYPOINT
的后面
一个docker-compose.yml
的例子
version: "2"
services:
mysqlfortest:
image: "mysql:latest"
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: azkaban
MYSQL_USER: azkaban
MYSQL_PASSWORD: azkaban
docker-entrypoint.sh
该脚本通过对环境变量、运行参数的判断来初始化mysql以及数据库、用户,还有对一些特殊情况的判断
环境变量
MYSQL_ROOT_PASSWORD
root 用户的密码
MYSQL_ALLOW_EMPTY_PASSWORD
允许root不使用密码
MYSQL_RANDOM_ROOT_PASSWORD
允许root使用随机密码
以上的三个环境变量必须指定其中一个
MYSQL_ONETIME_PASSWORD
当变量为true(这是默认状态,除非设置了
MYSQL_ROOT_PASSWORD
或MYSQL_ALLOW_EMPTY_PASSWORD
设置为 true)时,root用户的密码设置为expired,必须先更改才能正常使用MySQL。
MYSQL_INITDB_SKIP_TZINFO
不导入时区信息到MYSQL中,默认不使用该参数进行导入时区
MYSQL_DATABASE
默认创建一个数据库
MYSQL_USER
新建一个用户
MYSQL_PASSWORD
新建用户的密码
关于 /docker-entrypoint-initdb.d
目录
在 docker-entrypoint.sh
中有一段
process_init_file() {
local f="$1"; shift
local mysql=( "$@" )
case "$f" in
*.sh) echo "$0: running $f"; . "$f" ;;
*.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
*.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
*) echo "$0: ignoring $f" ;;
esac
echo
}
该目录下的文件会被执行,如果你有一些DDL或脚本需要执行,复制到此目录下即可,但是多个文件不保证执行顺序,需要自行控制。
一些语法解析
set -e 或 set -o errexit
任何语句的执行结果不是true则应该退出
set -o pipefail
执行错误之后立即退出, -o pipefail 的作用域是管道, 也就是说在 Linux 脚本中的管道
shopt -s nullglob
使用 Linux 中的通配符时 * ?等 如果没有匹配到任何文件, 不会报 No such file or directory 而是将命令后面的参数去掉执行
if [ "${1:0:1}" = '-' ]; then...
${1:0:1} 是判断 $1(调用该脚本的第一个参数), 偏移量0(不偏移), 取一个字符(取字符串的长度),如果判断出来调用这个脚本后面所跟的参数第一个字符是-中横线的话, 就认为后面的所有字符串都是 mysqld 的启动参数
set -- mysqld "$@"
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
exec "$@"
这个命令的意义在于你已经为你的镜像预想到了应该有的调用情况, 当实际使用镜像的人执行了你没有预料到的可执行命令时, 将会走到脚本的这最后一行, 去执行用户新的可执行命令
exec gosu mysql "$BASH_SOURCE" "$@"
这里的 gosu 命令, 是 Linux 中 sudo 命令的轻量级”替代品”,用来取代 shell 中的 sudo 命令. su 和 sudo 命令有一些缺陷, 主要是会引起不确定的 TTY, 对信号量的转发也存在问题。