How do I set the perms of a my.cnf file to be readonly from within Docker (not at the client's OS level)?

4.1k views Asked by At

I'm using docker-compose v 1.27 and Docker v 19.03. I have this in my docker-compose.yml file ...

version: '3'
  

services:
  mysql:
    restart: always
    image: mysql:8.0
    cap_add:
      - SYS_NICE  # CAP_SYS_NICE
    environment:
      MYSQL_DATABASE: 'directory_data'
      # So you don't have to use root, but you can if you like
      MYSQL_USER: 'root'
      # You can use whatever password you like
      MYSQL_PASSWORD: 'password'
      # Password for root access
      MYSQL_ROOT_PASSWORD: 'password'
      MYSQL_ROOT_HOST: '%'
    ports:
      - "3406:3306"
    volumes:
      - my-db:/var/lib/mysql
      - ./mysql/mysqlconf:/etc/mysql/conf.d
    command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci']

Note that I have no Dockerfile (didn't think I needed it). My "my.cnf" file, is below

davea$ cat mysql/mysqlconf/my.cnf 
bind-address = 0.0.0.0

From Docker, how do I set the permissions of the my.cnf file to be read-only? This comes into play on Windows 10 in which running "docker-compose up" results in this warning

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

Note, this answer -- https://stackoverflow.com/questions/64327260/in-docker-compose-how-do-i-set-perms-on-a-my-cnf-file-if-i-dont-have-a-dockerf, doesn't cut it, because it relies on setting th

3

There are 3 answers

1
concision On

I think the underlying problem here is that you are mounting a NTFS directory volume inside of an ext filesystem. Below are some possible solutions that may be helpful.


Docker-level: Use Read-only Volume Mounts

You can use a read-only volume mount instead of the default read-write setting.

For example, add :ro (read-only) to the end of the volume specification:

    volumes:
      - ...
      - ./mysql/mysqlconf:/etc/mysql/conf.d:ro

Container-level: chmod the configuration file

If you want to suppress the warning, you can try setting the permissions of the files at run-time to read-only by expanding the command configuration to several commands. I think this is what you are referring to as the client's OS level, though. The mount would not be read-only.

For example:

    command: bash -c "
        chmod -R 0444 /etc/mysql/conf.d/ &&
        mysqld --user=root --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
        "

Note that this is incompatible with read-only mounts, as you cannot adjust the permissions since it is a read-only filesystem.

0
wedi On

I suggest you set the permissions in a custom entrypoint script. This ensures they are adjusted on every container start, plays nicely with the "official" mysql image (it has custom entry point script support baked in) and does not collide with docker best practices (keeps mysqld running as pid 1).

It's three steps.

  1. Create a script that makes all necessary adjustments and make it executable:

    cat <<EOF > ./adjust-permissions.sh
    #!/bin/sh
    set -ex
    chown -R root:root /etc/mysql/conf.d/
    chmod -R 0644 /etc/mysql/conf.d/
    EOF
    chmod +x ./adjust-permissions.sh
    

    You might want to leave out chown, personally, I like to ensure there are no surprises with mounted files.

  2. Mount it into /docker-entrypoint-initdb.d/ inside the container (see docker-entrypoint.sh):

     volumes:
       [...]
       - ./adjust-permissions.sh:/docker-entrypoint-initdb.d/adjust-permissions.sh
    
  3. Enjoy.

1
François B. On

In your docker-compose yaml file, you can define the read-only access to the mounted volume
by adding :ro at the end of the volume definition.

version: '3'
  

services:
  mysql:
    restart: always
    image: mysql:8.0
    cap_add:
      - SYS_NICE  # CAP_SYS_NICE
    environment:
      MYSQL_DATABASE: 'directory_data'
      # So you don't have to use root, but you can if you like
      MYSQL_USER: 'root'
      # You can use whatever password you like
      MYSQL_PASSWORD: 'password'
      # Password for root access
      MYSQL_ROOT_PASSWORD: 'password'
      MYSQL_ROOT_HOST: '%'
    ports:
      - "3406:3306"
    volumes:
      - my-db:/var/lib/mysql
      - ./mysql/mysqlconf:/etc/mysql/conf.d:ro
    command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci']