修复Docker中的World-writable MySql错误

时间:2016-05-03 10:07:58

标签: mysql docker file-permissions docker-compose dockerfile

我正在使用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将不会使用MySql cnf文件:

  

mysqld:[警告]忽略全局可写配置文件'/etc/mysql/conf.d/my.cnf'。

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

问题 - 如何解决?正如你在我的Dockerfile中看到的那样,我尝试了一些解决方案,但它们都不适合我(但也许我做错了)。

目前我认为最合理的解决方案是将MySql conf文件不是直接安装到/etc/mysql/conf.d/而是安装到其他目​​录中,并在MySql启动之前将这些文件复制到/etc/mysql/conf.d/目录并将它们设置为777权限。我已经尝试过了,但在Dockerfile中,这些文件还没有出现,因此无法复制。

有没有简单的解决方案来解决它?或者也许某些MySql设置可以更改为不关心conf文件权限?

我也不能简单地在Dockerfile中使用COPY来复制Mysql配置文件(而不是使用卷),因为我希望多个站点使用这些图像,并且每个站点可能有不同的配置。

7 个答案:

答案 0 :(得分:5)

我刚遇到此问题,对我来说,解决方法是将my.cnf文件在Windows中设置为只读。

答案 1 :(得分:3)

使用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:
  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权限创建(在我的情况下保留默认值 - 不使用chmod是细)。

要验证是否已加载自定义mysql配置值,我运行:

mysql -u root -p

并输入我的密码。

当我输入SHOW VARIABLES;时,我会看到之前my.cnf的一些设置(不会将此文件设置为不同的值),因此它按预期工作。

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

答案 2 :(得分:1)

感谢@ marcin-nabiałek的灵感,我得到了这个解决方案,无需编写自定义脚本来运行命令,因为我仍然遇到了权限问题。脚本内容可以使用Dockerfile命令完成(参见下面的mariadb/Dockerfile内容)。

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

文件结构如下。 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(请注意卷的相对路径):

(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 a-w \etc\mysql\conf.d\*

这给了我所需要的一切&amp;我的头上还留着一些头发。如果这有助于其他任何人,请告诉我。

答案 3 :(得分:0)

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

由于您想要为配置使用卷的主要原因是您可以在容器之间共享,我建议使用数据卷容器。

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

您的其他容器将使用数据容器卷作为配置卷。

有关创建和使用数据容器的信息,请点击此处。

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

设置数据卷容器后,您将使用docker run上的--volumes-from标志链接到容器并附加卷。

您可以将此方法用于所有卷,或者只是少数,您喜欢什么。

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

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

答案 4 :(得分:0)

对于那些只需要设置少量配置选项的用户,我有一个替代答案

在docker compose文件中,您可以执行以下操作。

db:
  image: mysql
  command: >
            bash -c "mysqld --user=root --group_concat_max_len=1844674407370954752"
  environment:
     - MYSQL_ROOT_PASSWORD=pass
     - MYSQL_DATABASE=
     - MYSQL_USER=
     - MYSQL_PASSWORD=
  expose:
     - 3306

注意,我运行mysqld,然后设置选项--group_concat_max_len作为示例。如果您需要更多选项,只需在选项名称的“”内添加更多即可。这是一种优雅的解决方案,不需要从默认的mysql镜像中创建新镜像。

命令在docker组成文件中的作用是覆盖映像中默认的 CMD 命令。 images default命令仅运行mysqld(您可以在其github页面上查找它),因此我也只需运行它,但给它一些参数即可传入。请参阅此文件的最后一行以查看CMD命令。 。 (请参阅:https://github.com/docker-library/mysql/blob/master/5.5/Dockerfile

使用此方法,您甚至不需要担心在mysql配置文件中增加音量,这对我来说是个大问题,因为在进行docker-compose时必须为777才能工作,但是然后由于世界可写问题而失败。

答案 5 :(得分:0)

这对我有用

Exception

答案 6 :(得分:0)

- /c/Users/marcin/dock-test/composers/l1.app/mysql/conf.d/:/etc/mysql/conf.d/:delegated

使用委托将主机路径设置为只读模式。