代码路径:
https://github.com/docker-library/mysql/tree/master/5.6
commit id:
883703dfb30d9c197e0059a669c4bb64d55f6e0d
Dockerfile分析
4 RUN groupadd -r mysql && useradd -r -g mysql mysql
增加用户组mysql,并且增加一个用户mysql到mysql用户组
查看所有用户:cat /etc/passwd
查看所有用户组:cat /etc/group
查看用户属于哪一个组:groups mysql
10 && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)" \
获取平台的类型,如i386等
11 && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc" \
.asc是用来校验文件没被更改过
12 && export GNUPGHOME="$(mktemp -d)" \
生成临时路径,仅仅是一个名字,没有实际去创建这个路径
13 && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
接收公钥
14 && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
--batch:静默模式,不请求用户输入,用公钥gousu.asc校验gosu
17 && gosu nobody true \
切换到nobody用户
45 RUN { \
46 echo mysql-community-server mysql-community-server/data-dir select ''; \
47 echo mysql-community-server mysql-community-server/root-pass password ''; \
48 echo mysql-community-server mysql-community-server/re-root-pass password ''; \
49 echo mysql-community-server mysql-community-server/remove-test-db select false; \
50 } | debconf-set-selections \
51 && apt-get update && apt-get install -y mysql-server="${MYSQL_VERSION}" && rm -rf /var/lib/apt/lists/* \
无人值守安装时,预置所有待输入的参数,可以先找出安装过程中需要用户输入的信息
root@ubuntu:~# debconf-show mysql-server-5.7
* mysql-server/root_password_again: (password omitted)
* mysql-server/root_password: (password omitted)
* mysql-server/password_mismatch:
mysql-server-5.7/really_downgrade: false
mysql-server-5.7/nis_warning:
mysql-server-5.7/postrm_remove_databases: false
mysql-server/no_upgrade_when_using_ndb:
mysql-server-5.7/start_on_boot: true
57 && find /etc/mysql/ -name '*.cnf' -print0 \
58 | xargs -0 grep -lZE '^(bind-address|log)' \
59 | xargs -rt -0 sed -Ei 's/^(bind-address|log)/#&/' \
找到所有.cnf,然后显示在同一行
xargs 默认是以空白字符 (空格, TAB, 换行符) 来分割记录的, 因此文件名 ./file 1.log 被解释成了两个记录 ./file 和 1.log,为了解决此类问题,让 find 在打印出一个文件名之后接着输出一个 NULL 字符 ('\0') 而不是换行符, 然后再告诉 xargs 也用 NULL 字符来作为记录的分隔符(它等价于xargs -d"\0"),这就是 find 的 -print0 和 xargs 的 -0 的来历
-r:如果传给xargs的参数是空的,则不执行后面的命令
-t:执行命令前,先打印命令
sed -i 's/^http/#&/' baobao.txt:把以http开头的行注释掉
docker-entrypoint.sh分析
2 set -eo pipefail
-e:有错误立刻退出
-o pipefail:表示在管道连接的命令序列中,只要有任何一个命令返回非0值,则整个管道返回非0值,即使最后一个命令返回0
3 shopt -s nullglob
关闭通配符,路径传递时,通配符路径直接失效
5 # if command starts with an option, prepend mysqld
6 if [ "${1:0:1}" = '-' ]; then
7 set -- mysqld "$@"
8 fi
$@:代表所有的参数列表
$1:第一个参数,$2第二个参数,以此类推
它的效果是:如果参数中含有-选项,则将选项和mysqld拼接起来(mysqld -x abc -y efg)
举个例子:
# [root@CentOS tmp]# cat test.sh
# #!/bin/bash
# set -e
# if [ "${1:0:1}" = '-' ]; then
# set -- mysqld "$@"
# fi
# echo '$@='$@
# echo '$1='$1
# echo '$2='$2
# echo '$3='$3
# [root@CentOS tmp]# sh test.sh -p 22 -h 192.168.31.20
# $@=mysqld -p 22 -h 192.168.31.20
# $1=mysqld
# $2=-p
# $3=22
11 wantHelp=
12 for arg; do
13 case "$arg" in
14 -'?'|--help|--print-defaults|-V|--version)
15 wantHelp=1
16 break
17 ;;
18 esac
19 done
如果执行脚本跟了参数(这些参数 -'?'|--help|--print-defaults|-V|--version),将将wantHelp=1
28 local def="${2:-}"
如果没有有第2个参数,def就是空值,有第2个参数,则def=$2
37 val="$(< "${!fileVar}")"
将文件的内容读出来,放到变量val中
44 toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" )
$@:所有参数,还没研究透
45 if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
46 cat >&2 <<-EOM
47
48 ERROR: mysqld failed while attempting to check config
49 command was: "${toRun[*]}"
50
51 $errors
52 EOM
53 exit 1
54 fi
2>&1 > /dev/null:错误输出重定向到标准输出,然后一起全部重定向到/dev/null
cat > &2 << -EOM
xxx
EOM
把xxx显示在标准错误输出流,也就是屏幕上
${toRun[@]}:表示所有参数,举个例子
root@ubuntu:~# toRun=("ls -lh" /tmp)
root@ubuntu:~# ${toRun[0]}
total 24K
drwxr-xr-x 2 root root 4.0K Nov 21 19:28 5.6
-rw-r--r-- 1 root root 10 Oct 29 01:44 baidu_verify_ZbHchxuu6r.html
-rw-r--r-- 1 root root 6 Nov 20 22:06 baobao.txt
-rw-r--r-- 1 root root 144 Nov 3 23:42 push_2_baidu.sh
-rw-r--r-- 1 root root 114 Nov 3 23:45 push_2_baidu.txt
drwxr-xr-x 5 root root 4.0K Nov 19 15:24 WorkSpace
root@ubuntu:~# ${toRun[@]}
total 36K
srwxr-xr-x 1 root root 0 Nov 18 15:22 Aegis-
drwxr-xr-x 2 root root 4.0K Nov 18 15:22 hsperfdata_root
drwx------ 2 root root 4.0K Nov 20 21:14 tmp.hlu8E2o9Jv
drwx------ 2 root root 4.0K Nov 20 21:14 tmp.IruuIKsj05
drwx------ 2 root root 4.0K Nov 20 21:14 tmp.IXSSh14ros
drwx------ 2 root root 4.0K Nov 20 21:14 tmp.JG1ztjKAXQ
drwx------ 2 root root 4.0K Nov 20 21:14 tmp.KEdUeRMF96
drwx------ 2 root root 4.0K Nov 20 21:14 tmp.qjR9ulWt4b
drwx------ 2 root root 4.0K Nov 20 21:14 tmp.Qr9gCqSKGC
drwx------ 2 root root 4.0K Nov 20 21:14 tmp.V7kDngPX97
${toRun[0]} <---> ls -lh
${toRun[@]} <---> ls -lh /tmp
60 _get_config() {
61 local conf="$1"; shift
62 "$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null | awk '$1 == "'"$conf"'" { print $2; exit }'
63 }
shift:依次向左移位
awk '$1 == "'"$conf"'" { print $2; exit }':以空格作为分隔符,如果模式空间的第1列等于conf,则打印第2列的内容
65 # allow the container to be started with `--user`
66 if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then
67 _check_config "$@"
68 DATADIR="$(_get_config 'datadir' "$@")"
69 mkdir -p "$DATADIR"
70 chown -R mysql:mysql "$DATADIR"
71 exec gosu mysql "$BASH_SOURCE" "$@"
72 fi
-a:与或非得与逻辑,表示同时满足条件
-z:非空
$(id -u):当前用户的id
exec gosu mysql "$BASH_SOURCE" "$@":用mysql用户去执行(不另外开辟线程)
91 mysql_install_db --datadir="$DATADIR" --rpm --keep-my-cnf
--rpm --keep-my-cnf:保留用户my.cnf文件(启动时会用到,没有的话读取默认配置)
100 for i in {30..0}; do
101 if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then
102 break
103 fi
104 echo 'MySQL init process in progress...'
105 sleep 1
106 done
for i in {30..0}:倒计时30秒,30 29 28 。。。
if echo 'SELECT 1':如果屏幕打印1,也就是当倒计时到1的时候
128 read -r -d '' rootCreate <<-EOSQL || true
-r:
-d:
|| true: