从Dockerfile周围读取Docker官方MySQL(MariaDB)容器的行为
我在2018年3月12日更新了有关环境变量MYSQL_ROOT_HOST的说明。
動機 –
Explanation:
This is the Chinese translation for “motivation” or “motive.”
在Docker官方的MySQL(MariaDB)容器中,可以通过环境变量和初始化脚本来注入功能。
尽管非常方便,但常常容易忽略一个限制条件:“仅适用于首次启动”。
判断是否是第一次启动是通过检查容器内的mysql目录是否存在来决定的(详见后文)。
在MySQL(MariaDB)容器中,由于数据库的特性,通常会与Docker的卷功能结合使用。因此,即使在docker-compose.yml中更改了环境变量或稍作修改并重新运行初始化脚本,也会被判断为非首次启动,从而导致数据库完全没有反映。
由于不知道的话会陷入无可奈何的境地,所以在这里整理了Docker官方MySQL(MariaDB)的行为。所有信息截至2018年2月14日。
MySQL的官方存储库位于https://hub.docker.com/_/mysql/。
MariaDB官方仓库链接为https://hub.docker.com/r/mariadb/。
我們會盡快安排。 huì .)
(Note: This translation assumes that “となります” is in the context of making arrangements or taking action promptly.)
建议您阅读每个官方存储库中详细介绍的启动选项等使用方法。
还介绍了在docker run中玩耍的方法,建议一读。
本次分析的对象是官方仓库中的Dockerfile以及从中调用的docker-entrypoint.sh。
识别是否是第一次启动
会读Shell脚本的人很少,所以最简单和可靠的方法是阅读docker-entrypoint.sh。
...
if [ ! -d "$DATADIR/mysql" ]; then
...
通过判断数据容量中是否存在名为mysql的目录来决定是初次启动还是其他情况。
在启动Docker容器之前,如果在卷上创建了类似于/var/lib/mysql/mysql的目录,可能会导致意想不到的行为。
使用自定义设置文件
指定された設定ファイルを使ってMySQL(MariaDB)サーバーを起動できます。
...
services:
db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: my-secret-pw
volumes:
- /my/custom:/etc/mysql/conf.d
...
当你设置了音量,它将在启动时读取该配置文件。但是,如果你仔细阅读Dockerfile文件,你会发现
sed -ri 's/^user\s/#&/' /etc/mysql/my.cnf /etc/mysql/conf.d/*
因为有一行“user选项失效”所以需要注意。
这个功能不仅在第一次启动时有效,而且在第二次及以后的启动中也有效。
环境变量的一些设置
Docker官方的MySQL(MariaDB)容器可以通过环境变量进行一些额外配置设置。
但请注意,这些设置只有在初次启动容器时才会生效。
MYSQL_ROOT_PASSWORD的中文释义是”MYSQL的根密码”。
在MySQL(MariaDB)中设置root用户的密码。
首次启动时,
-
- MYSQL_ROOT_PASSWORD
-
- MYSQL_ALLOW_EMPTY_PASSWORD
- MYSQL_RANDOM_ROOT_PASSWORD
若没有进行任何设置,容器将无法启动。
而且,该环境变量只在初次启动时有效,不能用于更改已启动容器的根密码。
一旦启动后,您需要通过MySQL(MariaDB)客户端连接到服务器并更改密码。
MYSQL_INITDB_SKIP_TZINFO 可以跳过时区信息的设置。
在官方存储库的说明文中没有提到,但是如果为其设置适当的字符,将跳过首次启动时执行的时区表加载。
然而,这有点复杂。
environment:
MYSQL_INITDB_SKIP_TZINFO: yes
尽管如此译法仅为一种:
无论如何努力也好。
environment:
MYSQL_INITDB_SKIP_TZINFO: no
由于无论选择哪个,都会被跳过,请注意不要触碰。看起来最好不要碰。
MYSQL_RANDOM_ROOT_PASSWORD
MYSQL随机根密码
如果在这个环境变量中设置了适当的字符串,那么在初次启动时会生成并设置一个32个字符长的随机root密码,并将设置的密码输出到stdout。如果在无法获取docker-compose的输出的环境中,最好不要使用这个方法。
例如,若以Debian/GNU Linux jessie为例,
$ pwgen -1 32
也许考虑将生成的密码值设置为MYSQL_ROOT_PASSWORD,因为可以通过相同的逻辑获得相同的密码。
MYSQL_ROOT_HOST
MYSQL_ROOT_HOST 的汉语翻译为:MySQL根主机
這個環境變數是可選的。如果設定了它,則可以從該主機以root用戶身份訪問MySQL服務器。
在內部實現上,
CREATE USER 'root'@'a_host' IDENTIFIED BY 'a_root_password' ;
GRANT ALL ON *.* TO 'root'@'a_host' WITH GRANT OPTION ;
即便设置了这个值,也可以使用 localhost 作为 root 用户登录到 MySQL 服务器,并执行所述的 SQL 语句。
(2018年3月12日 补充)
如果没有设置此环境变量,则在内部会有一些问题。
CREATE USER 'root'@'%' IDENTIFIED BY 'a_root_password' ;
GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ;
通过执行此SQL语句,在网络中的任何位置都可以作为root用户登录到mysql服务器。
如果想要避免这个问题,你需要在MYSQL_ROOT_HOST中指定localhost。
MYSQL允许空密码。
是可选的。如果设置了此值,则将其设置为无根密码。
文件中写着要将其设置为yes,但启动脚本中没有这样的检查项。只要有任何值被设置,就会取消root密码。
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: no
只要沒有root密碼,這就是一個不應該設置的環境變數,因為在許多方面,只有真正明白自己在做什麼的人才能設置。
MySQL数据库
这个环境变量是可选的。
在初次启动时,会创建与该环境变量设置的名称相同的数据库。
在内部
CREATE DATABASE IF NOT EXISTS `a_database` ;
会发出类似的 SQL 查询语句。
如果 MYSQL_USER 和 MYSQL_PASSWORD 被设置了,在这个用户上将被授予对该数据库的 GRANT ALL,并且将被授予有关数据库操作的全部权限。
如果在应用程序中已经安排好了创建数据库的步骤,并且在启动时不希望创建额外的数据库,那么就不应该设置这个值。
MYSQL_USER,MYSQL_PASSWORD
MySQL用户,MySQL密码
这些值是可选的。如果没有同时设置它们,就没有效果。只指定其中一个值将被简单地忽略,不会显示任何错误。在内部上。
CREATE USER 'a_user`@'%' IDENTIFIED BY 'a_password' ;
会发出类似的SQL查询。
如果设置了MYSQL_DATABASE,那么对于此用户,将授权其进行该数据库的GRANT ALL操作。
GRANT ALL ON `a_database`.* TO 'a_user'@'%' ;
将会执行类似的SQL语句。
MYSQL一次性密码
截止到2018年2月14日,此环境变量仅在MySQL 5.6及以上版本中有效(MariaDB版本不可用)。
根用户的密码将被设置为过期状态,并在首次登录时强制要求更改密码。
执行初始化脚本
MySQL和MariaDB是通用的。
在容器内的/docker-entrypoint-initdb.d/目录中,如果有扩展名为.sh、.sql、.sql.gz的文件,这些文件在首次启动时将被处理。
仅在首次启动时处理,所以即使容器中保留了文件,也不会在第二次及以后的启动中被执行。
逆而言之,如果在初始化脚本中存在写错等错误时,即使重新启动容器,也不会应用更改(当然前提是使用了卷)。请注意。
看一下在容器启动时执行的 docker-entrypoint.sh。
...
for f in /docker-entrypoint-initdb.d/*; do
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
done
...
在中国大陆州具处理如下。会按字母顺序读取 /docker-entrypoint-initdb.d/ 目录中的文件,如果文件扩展名是 .sh,就直接执行;如果是 .sql,则将其导入到 MySQL 中;如果是 .sql.gz,则先解压缩再导入 MySQL。
MySQL和MariaDB的兼容性
MariaDB的容器基本上可以直接替换使用MySQL的容器。
因此,即使是MariaDB容器,例如环境变量的名称也应以MYSQL_开头。
将其更改为MARIADB_等是无法运行的。
然而,如果我们细致地观察,就会发现MariaDB缺少类似于MYSQL_ONETIME_PASSWORD的功能,并且默认安装了Percona XtraBackup等其他差异。