Fixing World-writable MySql error in Docker
Asked Answered
D

9

19

I'm using docker-compose, for db I have such container defined:

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/

My Dockerfile for this image is:

# 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

At the moment everything is commented except base MySql image.

The problem is, when I start my containers, my MySql cnf file won't be used by MySql because of this warning:

mysqld: [Warning] World-writable config file '/etc/mysql/conf.d/my.cnf' is ignored.

I'm using Windows as my host system. The problem is that Docker mounts diretory with full permissions and they couldn't be changed.

The question - how could it be solved? As you see in my Dockerfile I've tried a few solutions, but none of them works for me (but maybe I'm doing something wrong).

At the moment I think the most reasonable solution would be mounting MySql conf files not directly into /etc/mysql/conf.d/ but into some other directory and copy those files to /etc/mysql/conf.d/ directory before MySql starts and set them not 777 permissions. I've tried it, but in Dockerfile those files are not present yet so they cannot be copied.

Is there any easy solution to fix it? Or maybe some MySql settings could be changed to don't care about conf file permissions?

I also cannot simple use COPY inside Dockerfile to copy Mysql config files (instead of using volumes) because I want to use those images by multiple sites and each of them might have different configuration.

Delayedaction answered 3/5, 2016 at 10:7 Comment(0)
D
7

It seems solution for having files with not full permissions when using Windows host is sharing files with "intermediate directory" and then copy those files into desired directory in Docker container.

In above case (MySQL container) it could be done like this (you can use this method also in other cases)

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 (showed only db container)

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/

Plese notice that above we mount conf.d directory to /etc/mysql/conf.d/source directory and not to /etc/mysql/conf.d/ directory (so MySql won't load this file for now).

start.sh

#!/bin/sh

cp /etc/mysql/conf.d/source/* /etc/mysql/conf.d/

/entrypoint.sh mysqld

Above we copy now all files from conf.d/source directly into conf.d - those files are not shared with Windows host so they will be created with Linux permissions (in my case leaving defaults - without using chmod is fine).

To verify whether custom mysql configuration values are loaded now I run:

mysql -u root -p

and type my password.

When I type SHOW VARIABLES; I will see some settings from my.cnf that previously (without putting this file had different values), so it's working as expected.

Of course drawback of this solution is that those files won't be really shared so in case those files would be changed in Docker machine, they won't be updated in Windows host, but in above case when we want to use custom config files it doesn't make any difference and solve the issue.

Delayedaction answered 3/5, 2016 at 12:22 Comment(0)
F
45

I just encountered this issue and the fix for me is just to set my.cnf file to read-only in Windows.

Flambeau answered 15/8, 2018 at 7:36 Comment(5)
This should be the accepted answer really now. 1 checkbox instead of building a new imageKonya
I just give less permission to the file my.cnf chmod 0444 my.cnf and it worked. If I give all permissions chmod 777 my.cnf it doesn't work.Phuongphycology
YOU sir are the REAL MVP.Delusive
The issue is that there is no way to mark the file as read-only in git commit :(Sloven
Simple but effective!Calloway
D
7

It seems solution for having files with not full permissions when using Windows host is sharing files with "intermediate directory" and then copy those files into desired directory in Docker container.

In above case (MySQL container) it could be done like this (you can use this method also in other cases)

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 (showed only db container)

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/

Plese notice that above we mount conf.d directory to /etc/mysql/conf.d/source directory and not to /etc/mysql/conf.d/ directory (so MySql won't load this file for now).

start.sh

#!/bin/sh

cp /etc/mysql/conf.d/source/* /etc/mysql/conf.d/

/entrypoint.sh mysqld

Above we copy now all files from conf.d/source directly into conf.d - those files are not shared with Windows host so they will be created with Linux permissions (in my case leaving defaults - without using chmod is fine).

To verify whether custom mysql configuration values are loaded now I run:

mysql -u root -p

and type my password.

When I type SHOW VARIABLES; I will see some settings from my.cnf that previously (without putting this file had different values), so it's working as expected.

Of course drawback of this solution is that those files won't be really shared so in case those files would be changed in Docker machine, they won't be updated in Windows host, but in above case when we want to use custom config files it doesn't make any difference and solve the issue.

Delayedaction answered 3/5, 2016 at 12:22 Comment(0)
H
7

This works for me

      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'

Hoffert answered 16/10, 2020 at 11:47 Comment(0)
D
5

I have an alternative answer for those that just need to set a few configuration options.

In the docker compose file you can do something like this.

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

Notice I run mysqld and then set the options --group_concat_max_len as an example. If you need more options just add more -- within the "" with the name of the option. This is an elegant solution that does not require making a new image from the default mysql one.

What command does in a docker compose file is overwrites the default CMD command in the image. The images default command simply runs mysqld (you can look it up on their github page), so I simply just run it as well but give it some parameters to pass in. Refer to the very last line of this file to see the CMD command. (refer to this: https://github.com/docker-library/mysql/blob/master/5.5/Dockerfile)

Using this method you do not even need to worry about voluming in a mysql configuration file, which for me was a big issue since it had to be 777 to work when doing docker-compose up but would then proceed to fail due to the world writable problem.

Detestation answered 9/12, 2018 at 6:16 Comment(0)
F
3

Thanks to @marcin-nabiałek for the inspiration, I got this solution working without having to write a custom script to run commands as I was still ending up with permissions issues. The script contents could've been completed with the Dockerfile commands (see mariadb/Dockerfile contents below).

I run docker-compose -p my_project up --build -d in the project-root directory.

File structure is as follows. 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 (note the relative paths for the volumes):

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

This got me everything I needed & I still have some hair left on my head. Let me know if this helps anyone else.

Fighterbomber answered 22/8, 2016 at 21:33 Comment(2)
As the custom conf files are copied into the image, I don't think you need to mount the conf.d volume. At least I didn't need it. Didn't need the entrypoint: section either.Olmstead
@Olmstead the entrypoint was a script that setups the DB for me, inserts of default data, etc, think Laravel Factories. It might not be needed for others, but it was part of my project.Fighterbomber
L
1

The other answers didn't work for me because chown and chmod told me the folder's filesystem was read-only (i.e. using Nedudi's answer). So I had to delete the folder and recreate it:

FROM mariadb:10.8
RUN rm -rf /etc/mysql/conf.d
COPY --chown=mysql:mysql ./docker/misc/mariadb/mariadb.cnf /etc/mysql/mariadb.cnf
Litharge answered 18/8, 2022 at 10:49 Comment(0)
R
1

Alternatively, you can just mount the config file this way (note the :ro addition). Thanks to @Stefan for giving the idea. Worked for me in Windows 10 with WSL2

volumes:
  - ./db/my.cnf:/etc/my.cnf:ro
Robson answered 8/2, 2023 at 14:13 Comment(0)
M
0

Right now you are using volume host mounts, and because your host is Windows it is causing you problems with permissions.

Since the main reason why you want to use a volume for your configs is so that you can share between containers, I would recommend using a data volume container for this.

A data volume container will have the volumes you want to share, and they will be Linux mounts so the permissions issue should go away.

Your other containers would use the data containers volumes for the config volume.

Information on creating and using a data container can be found here.

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

Once you have your data volume container setup you would use the --volumes-from flag on docker run to link to the container and attach the volumes.

You can use this approach for all of your volumes or just a few, what ever you prefer.

Another option if you don't need to share your data between other containers is to just use regular volumes and not host mounted volumes. This would create a volume in Linux but isn't mounted to the Windows host. You would do that by just listing the volume with one directory name.

Volumes
 - /var/lib/mysql
 - /etc/mysql 
Margaritamargarite answered 3/5, 2016 at 11:18 Comment(3)
The problem is that I don't want to share those volumes between containers at all. I just want to include into container cnf files i have in my host system (Windows) into MySql container.Gentlefolk
Ok, I included another option in the answer for not sharing between containers, but that wouldn't pull from the host. I'll see if I can think of something else.Margaritamargarite
Thank you for your effort. It seems I've managed to solve this (see my answer)Gentlefolk
L
0
- /c/Users/marcin/dock-test/composers/l1.app/mysql/conf.d/:/etc/mysql/conf.d/:delegated

Use delegated to set the host path in read-only mode.

Lennie answered 17/12, 2020 at 3:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.