【问题标题】:Fixing World-writable MySql error in Docker修复 Docker 中的 World-writable MySql 错误
【发布时间】:2016-08-28 07:54:55
【问题描述】:

我正在使用 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:[警告] 全局可写配置文件 '/etc/mysql/conf.d/my.cnf' 被忽略。

我使用 Windows 作为我的主机系统。问题是 Docker 挂载了具有完全权限的目录,并且无法更改。

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    我刚遇到这个问题,我的解决方法是在 Windows 中将 my.cnf 文件设置为只读。

    【讨论】:

    • 这应该是现在真正接受的答案。 1 个复选框,而不是构建新图像
    • 我只是对文件 my.cnf chmod 0444 my.cnf 授予较少的权限,它就起作用了。如果我授予所有权限 chmod 777 my.cnf 它不起作用。
    • 你先生是真正的 MVP。
    【解决方案2】:

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

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

    mysql -u root -p
    

    然后输入我的密码。

    当我输入SHOW VARIABLES; 时,我会看到来自my.cnf 的一些之前的设置(没有放置这个文件有不同的值),所以它按预期工作。

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

    【讨论】:

      【解决方案3】:

      这对我有用

            mysql:
              networks:
                - main
              image: library/mysql:5.7
              container_name: 'mysql'
              command: >
                bash -c "
                chmod 644 /etc/mysql/conf.d/*.cnf
                && /entrypoint.sh mysqld
                "
              ports:
                - "3308:3308"
              volumes:
                - ./my_local_dir/var/lib/mysql:/var/lib/mysql
                - ./my_local_dir/etc/mysql/conf.d/:/etc/mysql/conf.d/
              restart: always
              environment:
                MYSQL_ROOT_PASSWORD: 'root'
                MYSQL_DATABASE: 'some'
      
      

      【讨论】:

        【解决方案4】:

        对于那些只需要设置几个配置选项的人,我有一个替代答案

        在 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 图像制作新图像。

        command 在 docker compose 文件中所做的是覆盖图像中的默认 CMD 命令。 images 默认命令只是运行 mysqld(你可以在他们的 github 页面上查找),所以我也只是简单地运行它,但给它一些参数以传入。请参阅此文件的最后一行以查看 CMD 命令. (参考这个:https://github.com/docker-library/mysql/blob/master/5.5/Dockerfile

        使用这种方法,您甚至不需要担心 mysql 配置文件中的容量,这对我来说是一个大问题,因为在执行 docker-compose up 时它必须是 777 才能工作,但是然后将由于世界可写问题而继续失败。

        【讨论】:

          【解决方案5】:

          感谢@marcin-nabiałek 的启发,我无需编写自定义脚本来运行命令就可以使用此解决方案,因为我仍然遇到权限问题。脚本内容可以使用 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(注意卷的相对路径):

          (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\*
          

          这让我得到了我需要的一切,而且我的头上还剩下一些头发。让我知道这是否对其他人有帮助。

          【讨论】:

            【解决方案6】:

            现在您正在使用卷主机挂载,并且由于您的主机是 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 
            

            【讨论】:

            • 问题是我根本不想在容器之间共享这些卷。我只想将我的主机系统(Windows)中的容器 cnf 文件包含到 MySql 容器中。
            • 好的,我在答案中包含了另一个选项,即不在容器之间共享,但这不会从主机中提取。我看看能不能想点别的。
            • 感谢您的努力。看来我已经设法解决了这个问题(见我的回答)
            【解决方案7】:
            - /c/Users/marcin/dock-test/composers/l1.app/mysql/conf.d/:/etc/mysql/conf.d/:delegated
            

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-07-12
              • 2016-06-09
              • 2017-12-15
              • 1970-01-01
              • 2019-09-16
              • 2014-06-24
              • 2021-12-19
              相关资源
              最近更新 更多