在Docker中修复世界可写的MySql错误

我使用的是docker-compose,对于db我定义了这样的容器:

db: build: ../builds/mysql-5.7 environment: - MYSQL_ROOT_PASSWORD=pass - MYSQL_DATABASE= - MYSQL_USER= - MYSQL_PASSWORD= expose: - 3306 volumes: - /c/Users/marcin/dock-test/composers/l1.app/mysql/data/:/var/lib/mysql/ - /c/Users/marcin/dock-test/composers/l1.app/mysql/conf.d/:/etc/mysql/conf.d/ - /c/Users/marcin/dock-test/composers/l1.app/mysql/log/:/var/log/mysql/ 

我的这个图像的Dockerfile是:

 # Base image FROM mysql:5.7 # Set valid file permissions - otherwise MySql won't read those files #COPY mysql-perm-fix.sh /etc/init.d/mysql-perm-fix.sh #RUN chmod +x /etc/init.d/mysql-perm-fix.sh #RUN update-rc.d mysql-perm-fix.sh defaults 100 #RUN mkdir /etc/mysql/conf.d/source #RUN cp /etc/mysql/conf.d/source/my.cnf /etc/mysql/conf.d/my.cnf #RUN chmod -R 644 /etc/mysql/conf.d 

目前,除了基本的MySql映像之外,所有的东西都被注释掉了。

问题是,当我启动我的容器时,我的MySql cnf文件将不会被MySql使用,因为这个警告:

mysqld:[Warning]全局可写configuration文件'/etc/mysql/conf.d/my.cnf'被忽略。

我使用Windows作为我的主机系统。 问题在于Docker以完全权限挂载diretory,并且无法更改。

这个问题 – 如何解决? 正如你在我的Dockerfile中看到的,我尝试了一些解决scheme,但是它们都不适合我(但也许我做错了什么)。

目前我认为最合理的解决scheme是将MySqlconfiguration文件不直接挂载到/etc/mysql/conf.d/而是挂载到其他目录中,并在MySql启动之前将这些文件复制到/etc/mysql/conf.d/目录并设置它们不是777权限。 我已经尝试过了,但是在Dockerfile中这些文件还没有出现,所以它们不能被复制。

有没有简单的解决scheme来解决它? 或者,也许一些MySql设置可以改变,不关心conf文件的权限?

我也不能简单的在Dockerfile里面使用COPY来复制Mysql的configuration文件(而不是使用卷),因为我想要在多个站点上使用这些镜像,而且每个镜像都可能有不同的configuration。

这似乎是解决scheme,使用Windows主机共享文件与“中间目录”,然后将这些文件复制到Docker容器中所需的目录时,具有不完全权限的文件。

在上面的情况下(MySQL容器)它可以这样做(您也可以在其他情况下使用此方法)

Dockerfile

 # Base image FROM mysql:5.7 # Copy starting scripts file COPY start.sh /root/start.sh # Run necessary services CMD ["/bin/bash", "/root/start.sh"] 

docker-compose.yml (只显示db容器)

 db: build: ../builds/mysql-5.7 environment: - MYSQL_ROOT_PASSWORD=pass - MYSQL_DATABASE= - MYSQL_USER= - MYSQL_PASSWORD= expose: - 3306 volumes: - /c/Users/marcin/dock-test/composers/l1.app/mysql/data/:/var/lib/mysql/ - /c/Users/marcin/dock-test/composers/l1.app/mysql/conf.d/:/etc/mysql/conf.d/source - /c/Users/marcin/dock-test/composers/l1.app/mysql/log/:/var/log/mysql/ 

请注意,上面我们将conf.d目录挂载到/etc/mysql/conf.d/source目录,而不是挂载到/etc/mysql/conf.d/目录(所以MySql现在不会加载这个文件)。

start.sh

 #!/bin/sh cp /etc/mysql/conf.d/source/* /etc/mysql/conf.d/ /entrypoint.sh mysqld 

上面我们将conf.d/source所有文件直接复制到conf.d – 这些文件不与Windows主机共享,因此将使用Linux权限创build它们(在我的情况下保留默认设置 – 不使用chmod就可以)。

要validation自定义mysqlconfiguration值是否现在加载我运行:

 mysql -u root -p 

并input我的密码。

当我inputSHOW VARIABLES; 我以前会看到my.cnf中的一些设置(没有把这个文件设置为不同的值),所以它按照预期工作。

当然,这个解决scheme的缺点是这些文件不会真正共享,所以如果这些文件在Docker机器中被更改,它们将不会在Windows主机中更新,但是在上述情况下,当我们要使用自定义configuration文件它没有任何区别和解决问题。

现在,您正在使用卷主机装载,并且因为您的主机是Windows,它会导致您的权限问题。

由于你想为你的configuration使用卷的主要原因是你可以在容器之间共享,所以我build议使用一个数据卷容器。

数据卷容器将具有要共享的卷,并且它们将是Linux挂载,因此权限问题应该消失。

您的其他容器将使用configuration卷的数据容器卷。

有关创build和使用数据容器的信息可以在这里find。

https://docs.docker.com/engine/userguide/containers/dockervolumes/#creating-and-mounting-a-data-volume-container

一旦你有了你的数据卷容器的设置,你可以使用docker run上的–volumes-from标志来链接到容器并连接这些卷。

你可以使用这种方法来处理所有的卷或者只是几个,你喜欢什么。

如果您不需要在其他容器之间共享数据,另一个select是使用常规卷而不是主机装入卷。 这将在Linux中创build一个卷,但不会挂载到Windows主机上。 你只需要用一个目录名列出卷即可。

 Volumes - /var/lib/mysql - /etc/mysql 

感谢@ marcin-nabiałek的灵感,我得到了这个解决scheme,而不必编写自定义脚本来运行命令,因为我仍然遇到了权限问题。 脚本内容可以通过Dockerfile命令完成(请参阅下面的mariadb/Dockerfile内容)。

我在project-root目录下运行docker-compose -p my_project up --build -d

文件结构如下。 project-root

 drwxr-xr-x 1 cmeza 197121 0 Aug 22 16:19 .git/ -rw-r--r-- 1 cmeza 197121 40 Aug 22 15:41 .gitignore -rw-r--r-- 1 cmeza 197121 1056 Aug 22 13:24 Dockerfile -rw-r--r-- 1 cmeza 197121 291 Aug 22 13:24 PROJECT.md -rw-r--r-- 1 cmeza 197121 3642 Aug 22 13:24 README.md drwxr-xr-x 1 cmeza 197121 0 Aug 22 13:24 bin/ -rw-r--r-- 1 cmeza 197121 944 Aug 22 15:42 docker-compose.yml drwxr-xr-x 1 cmeza 197121 0 Aug 22 15:41 mariadb/ 

project-root/mariadb

 -rw-r--r-- 1 cmeza 197121 193 Aug 22 15:46 Dockerfile drwxrwxrwx 1 cmeza 197121 0 Aug 22 13:57 conf/ -rwxrwxrwx 1 cmeza 197121 5013 Aug 22 13:57 conf/my_custom.cnf drwxrwxrwx 1 cmeza 197121 0 Aug 22 16:07 data/ -rwxrwxrwx 1 cmeza 197121 0 Aug 22 16:07 data/.gitignore drwxrwxrwx 1 cmeza 197121 0 Aug 22 16:06 entrypoint/ -rwxrwxrwx 1 cmeza 197121 1163 Aug 22 16:06 entrypoint/default.sql drwxrwxrwx 1 cmeza 197121 0 Aug 22 15:52 log/ -rwxrwxrwx 1 cmeza 197121 0 Aug 22 15:52 log/.gitignore 

docker-compose.yml (注意卷的相对path):

 (other services here) db: environment: - MYSQL_ROOT_PASSWORD=my_super_secret_password - MYSQL_DATABASE=my_db ports: - "3306:3306" volumes: - ./mariadb/entrypoint:/docker-entrypoint-initdb.d - ./mariadb/conf:/etc/mysql/conf.d/my_conf_files - ./mariadb/data:/var/lib/mysql - ./mariadb/log:/var/log/mysql build: ./mariadb entrypoint: - docker-entrypoint.sh - mysqld (some other services here) 

mariadb/Dockerfile

 # Base image FROM mariadb:5.5 # Copy custom conf file(s) # .\conf being your relative host path from this Dockerfile # \etc\mysql\conf.d\ being the VM path COPY .\conf\* \etc\mysql\conf.d\ # Make the conf files not writeable so mysql will read them RUN chmod aw \etc\mysql\conf.d\* 

这让我得到了我所需要的一切,头上还留着一些头发。 让我知道这是否有助于其他人。