从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等其他差异。

bannerAds