docker-library / mysql

Docker Official Image packaging for MySQL Community Server
https://dev.mysql.com/
GNU General Public License v2.0
2.42k stars 2.18k forks source link

It is not possible to replace the "mysql" user with the "other" user for the mysqld process(There is a solution). #1064

Closed alexeyp0708 closed 2 weeks ago

alexeyp0708 commented 1 month ago

I encountered a problem where I need to change the user for mysqld as described here.

In the script "docker-entrypoint.sh" the user "mysql" is hardcoded. Before starting mysqld, the root user is changed to the user "mysql" through the "gosu" component ( docker-entrypoint.sh#L377 ) . All initialized directories and files have the owner "mysql" ( docker-entrypoint.sh#L210 ) . This behavior does not allow working with volumes and directories for which a different user ID is assigned.

To fix this, you need to dynamically assign a user to the mysqld process. I propose to make the following changes to "docker-entrypoint.sh" :

_get_option(){
    local reg_opt="$1"
    shift
    echo "$@" | grep -o -E "$reg_opt" | tail -n 1 | cut -d '=' -f 2 
}
mysql_get_user_option() {
    local reg_opt="\s--user=[a-zA-z0..9_\-]+"
    local proc_user="$(_get_option "$reg_opt" $@)"

    if [[ -z "$proc_user" ]]
    then
        local no_defaults="$(echo "$@"|grep -o -E "\s--no-defaults")"
        local defaults_file="$(echo "$@"|grep -o -P "\s--defaults-file\s*=\s*(?:[\S]+|\"[\s\S]+?\"|'[\s\S]+?')"|tail -n 1)"
        local defaults_extra_file="$(echo "$@"|grep -o -P "\s--defaults-extra-file\s*=\s*(?:[\S]+|\"[\s\S]+?\"|'[\s\S]+?')")"
        if [[ -z "$no_defaults" ]]
        then
            proc_user="$(_get_option "$reg_opt" $(mysqld $defaults_file $defaults_extra_file --print-defaults))"
        fi
    fi
    echo "$proc_user"
}
yosifkit commented 1 month ago

If the mounted directories (volumes) already have the correct owner/permissions for the user that you want to run mysql as, then just run the container with that user id (and group id) and it will just work. The image is designed to run in this way.

docker run --user 1000:1000 -e ... mysql:8.4

The chown and user swap are only done when running as root (and indeed can only be done as root). https://github.com/docker-library/mysql/blob/c857c9c091e6194c9fb9c91e83d343b186e103cd/8.4/docker-entrypoint.sh#L208-L210 https://github.com/docker-library/mysql/blob/c857c9c091e6194c9fb9c91e83d343b186e103cd/8.4/docker-entrypoint.sh#L375-L377

alexeyp0708 commented 1 month ago

@yosifkit volume is a universal storage to which several containers can connect, and therefore he should not depend on the settings of a specific container. Overriding the rights of a volume and its contents will disrupt the volume's interaction with other containers. If the volume and its contents are assigned to the same user and the containers communicate via the user ID(have access), the integrity of the interaction is maintained. If MYSQL supports the ability to interact with data through another user, then this possibility should be implemented in the Docker container. ~But you may not change anything and think that this is how it should be. At least my solution works for me.~

Example: An nginx container and a php container can be configured in a way where data in a volume can be jointly managed through the user www-data(id82). ~Mysql container requires a special case, since they decided to hardcode 'mysql' user into the entry points. This is at least unprofessional.~

alexeyp0708 commented 1 month ago

@yosifkit

docker run --user 1000:1000 -e ... mysql:8.4

I'm sorry. I didn’t immediately see the solution and didn’t understand that the mysql user is assigned only if the container is started as a root user.

tianon commented 1 month ago

https://hub.docker.com/_/mysql#:~:text=Running%20as%20an%20arbitrary%20user :innocent: