docker容器中的mysql不能在os x上运行挂载的卷

时间:2021-07-22 20:54:38

On OS X.

在OS X。

I am trying to run mysql in a docker container through boot2docker, by mounting the volume /var/lib/mysql on the host, so that I can have persistant mysql data. I plan to use a data only container in future, but right now I was trying to do this using this option.

我正在尝试通过boot2docker在docker容器中运行mysql,方法是在主机上安装卷/var/lib/mysql,这样我就可以拥有持久的mysql数据。我计划将来使用一个只包含数据的容器,但是现在我尝试使用这个选项。

I use the following command to run the container :

我使用以下命令来运行容器:

docker run -v /Users/yash/summers/db:/var/lib/mysql -i -t 'image name'

docker运行-v /Users/yash/summers/db:/var/lib/mysql -i -t 'image name'

The /Users/yash/summers/db folder is already there.

/Users/yash/summers/db文件夹已经存在。

I am facing persmission issues in this. Using commandline, I am able to access the directory, create/remove new files, but when I am running service mysql start, I get the following error:

我在这件事上遇到了个人问题。使用命令行,我可以访问目录,创建/删除新文件,但是当我运行服务mysql start时,我得到以下错误:

150528 15:43:43 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
150528 15:43:43 [Warning] Using unique option prefix key_buffer instead of key_buffer_size is deprecated and will be removed in a future release. Please use the full name instead.
150528 15:43:43 [Note] /usr/sbin/mysqld (mysqld 5.5.43-0ubuntu0.14.04.1) starting as process 909 ... 
150528 15:43:43 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
150528 15:43:43 [Warning] Using unique option prefix myisam-recover instead of myisam-recover-options is deprecated and will be removed in a future release. Please use the full name instead.150528 15:43:43 [Note] Plugin 'FEDERATED' is disabled.
/usr/sbin/mysqld: Table 'mysql.plugin' doesn't exist
150528 15:43:43 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
150528 15:43:43 InnoDB: The InnoDB memory heap is disabled
150528 15:43:43 InnoDB: Mutexes and rw_locks use GCC atomic builtins
150528 15:43:43 InnoDB: Compressed tables use zlib 1.2.8 
150528 15:43:43 InnoDB: Using Linux native AIO
150528 15:43:43 InnoDB: Initializing buffer pool, size = 128.0M
150528 15:43:43 InnoDB: Completed initialization of buffer pool
150528 15:43:43  InnoDB: Operating system error number 13 in a file operation.
InnoDB: The error means mysqld does not have the access rights to
InnoDB: the directory.
InnoDB: File name ./ibdata1
InnoDB: File operation call: 'create'.
InnoDB: Cannot continue operation.
150528 15:43:44 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended 

I have trying to solve this for the past 2 days, going through so many pages like this, this, and this.

在过去的两天里,我一直在试图解决这个问题,读了这么多页,像这样,这样,这样,这样。

I can't solve my problem. I think I am not able to perfectly do what the solutions are suggesting.

我不能解决我的问题。我认为我不能很好地完成解所建议的。

From my understanding, there are some workarounds listed on those pages which include changing the uids and guids, but I think they are not well explained.

根据我的理解,这些页面上列出了一些解决方案,包括修改uid和guids,但是我认为它们没有得到很好的解释。

Can anybody please explain to me a detailed workaround for this.

谁能给我解释一下详细的解决办法吗?

Update 1 : I tried the it with using a data only container also, and still facing the same issue.

更新1:我也尝试了只使用数据容器的it,但仍然面临同样的问题。

I am able to run everything fine if I don't use any -v or --volumes-from option, so I think there is no prob in mysql server.

如果不使用-v或-volumes-from选项,我可以运行一切正常,所以我认为mysql服务器没有问题。

Update 2 : Dockerfile used for creating the data-only container:

更新2:用于创建只包含数据的容器的Dockerfile:

FROM ubuntu

RUN mkdir /var/lib/mysql

VOLUME /var/lib/mysql

3 个解决方案

#1


3  

There are two different solutions.

有两种不同的解决方案。

  1. Solution #1. With Dockerfile

    # 1的解决方案。与Dockerfile

    (I don't like it because I prefer official image from Docker Hub without any changes)

    (我不喜欢它,因为我喜欢Docker Hub的官方形象,没有任何改变)

    Add RUN usermod -u 1000 mysql to your Docker file to set ID 1000 for user "mysql" ( the same ID like inside docker-machine).

    在Docker文件中添加RUN usermod -u 1000 mysql,以便为用户“mysql”设置ID 1000(与Docker -machine内部相同的ID)。

  2. Solution #2. With my.cnf.

    # 2的解决方案。。在my . cnf中所做

    Still I am using my own config I prefer this solution. We alredy have root user with ID 1000, because of that we can run MySQL with this user:

    我仍然使用我自己的配置,我喜欢这个解决方案。我们也有ID为1000的root用户,因此我们可以使用这个用户运行MySQL:

    • my.cnf

      my.cnf

      Main row is user = root (you can use sed to change only this row in file. I prefer mount all file)

      Main row是user = root(您可以使用sed来更改文件中的这一行。我喜欢挂载所有文件)

      [client]
      port        = 3306
      socket      = /var/run/mysqld/mysqld.sock
      default-character-set = utf8
      
      [mysqld_safe]
      pid-file    = /var/run/mysqld/mysqld.pid
      socket      = /var/run/mysqld/mysqld.sock
      nice        = 0
      
      [mysqld]
      user        = root
      pid-file    = /var/run/mysqld/mysqld.pid
      socket      = /var/run/mysqld/mysqld.sock
      port        = 3306
      basedir     = /usr
      datadir     = /var/lib/mysql
      tmpdir      = /tmp
      lc-messages-dir = /usr/share/mysql
      explicit_defaults_for_timestamp
      init_connect='SET collation_connection = utf8_unicode_ci'
      init_connect='SET NAMES utf8'
      character-set-server=utf8
      collation-server=utf8_unicode_ci
      skip-character-set-client-handshake
      
      # Instead of skip-networking the default is now to listen only on
      # localhost which is more compatible and is not less secure.
      #bind-address   = 127.0.0.1
      
      #log-error  = /var/log/mysql/error.log
      
      # Recommended in standard MySQL setup
      sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
      
      # Disabling symbolic-links is recommended to prevent assorted security risks
      symbolic-links=0
      
      # * IMPORTANT: Additional settings that can override those from this file!
      #   The files must end with '.cnf', otherwise they'll be ignored.
      #
      !includedir /etc/mysql/conf.d/
      
    • Change default my.cnf with this file:

      使用此文件更改默认的my.cnf:

      docker run -it -v ./mysql/var/lib/mysql:/var/lib/mysql -v ./my.cnf::/etc/mysql/my.cnf mariadb:10.0.22

      docker运行-v ./mysql/var/lib/mysql:/var/lib/mysql -v ./my.cnf::/etc/mysql/my.cnf mariadb:10.0.22

#2


0  

When you are using docker run -v option then docker don't manipulate with files ownership. So owner of the mounted folder inside container will have the same UID as in the host system (username can be different). You can change ownership of the file or directory inside container by chmod command but it change ownership in host sytem too. So you can prepare correct ownership on your host system before you run docker container. This example demonstrates how it works (try it on your system):

当您使用docker run -v选项时,docker不会对文件所有权进行操作。因此,容器内已挂载文件夹的所有者将拥有与主机系统中相同的UID(用户名可能不同)。您可以通过chmod命令更改容器内文件或目录的所有权,但它也会更改主机sytem中的所有权。因此,在运行docker容器之前,可以在主机系统上准备正确的所有权。这个例子演示了它是如何工作的(在你的系统上试试):

I have ~/foo directory which is owned by me - my UID is 1000

我有~/foo目录,属于我-我的UID是1000

~ $ ls -lnd foo
drwxr-xr-x 2 1001 1000 4096 Nov 24 22:47 foo

Run docker container, mount ~/foo directory to them and display ownership inside container

运行docker容器、mount ~/foo目录,并显示容器内的所有权。

~ $ docker run -it --rm -v ~/foo:/tmp/foo busybox ls -ln /tmp
total 4
drwxr-xr-x    2 1000     1000          4096 Nov 24 21:47 foo

Owner UID inside container is the same. Now I change directory ownership on my computer.

容器内的所有者UID是相同的。现在我改变了我电脑上的目录所有权。

~ $ sudo chown 1001 foo

Start container again, mount the foo directory and display ownership

再次启动容器,挂载foo目录并显示所有权

~ $ docker run -it --rm -v ~/foo:/tmp/foo busybox ls -ln /tmp
total 4
drwxr-xr-x    2 1001     1000          4096 Nov 24 21:47 foo

Owner UID was changed as well

所有者UID也被更改

But there is one exception. If you try to mount volume to nonexistent directory then docker will create this missing directory automatically (but this is deprecated feature, so don't do this) and this directory will by created with UID 0. Try it:

但有一个例外。如果您试图将卷挂载到不存在的目录,那么docker将自动创建这个丢失的目录(但这是不赞成的特性,所以不要这样做),这个目录将使用UID 0创建。试一试:

~ $ docker run -it --rm -v ~/foo:/tmp/bar/foo busybox ls -ln /tmp
total 4
drwxr-xr-x    3 0        0             4096 Nov 24 22:10 bar

#3


-1  

I similarly ran into this issue; I solved it by chmod/chown'ing inside my data container, e.g.:

我同样遇到了这个问题;我用chmod/chown'ing形式在我的数据容器中解决了这个问题,例如:

FROM ubuntu

# Create data directory
RUN mkdir -p /data /var/lib/mysql
RUN chmod -R 777 /data /var/lib/mysql
RUN chown -R root:root /data /var/lib/mysql

# Create /data volume
VOLUME /data
VOLUME /var/lib/mysql

I believe this works because UFS now properly records permissions rather than relying on a direct from host mount to do so, which as you've discovered, does not work on OS X

我相信这是可行的,因为UFS现在正确地记录权限,而不是依赖于来自主机挂载的直接记录权限,正如您所发现的,这在OS X上是行不通的

#1


3  

There are two different solutions.

有两种不同的解决方案。

  1. Solution #1. With Dockerfile

    # 1的解决方案。与Dockerfile

    (I don't like it because I prefer official image from Docker Hub without any changes)

    (我不喜欢它,因为我喜欢Docker Hub的官方形象,没有任何改变)

    Add RUN usermod -u 1000 mysql to your Docker file to set ID 1000 for user "mysql" ( the same ID like inside docker-machine).

    在Docker文件中添加RUN usermod -u 1000 mysql,以便为用户“mysql”设置ID 1000(与Docker -machine内部相同的ID)。

  2. Solution #2. With my.cnf.

    # 2的解决方案。。在my . cnf中所做

    Still I am using my own config I prefer this solution. We alredy have root user with ID 1000, because of that we can run MySQL with this user:

    我仍然使用我自己的配置,我喜欢这个解决方案。我们也有ID为1000的root用户,因此我们可以使用这个用户运行MySQL:

    • my.cnf

      my.cnf

      Main row is user = root (you can use sed to change only this row in file. I prefer mount all file)

      Main row是user = root(您可以使用sed来更改文件中的这一行。我喜欢挂载所有文件)

      [client]
      port        = 3306
      socket      = /var/run/mysqld/mysqld.sock
      default-character-set = utf8
      
      [mysqld_safe]
      pid-file    = /var/run/mysqld/mysqld.pid
      socket      = /var/run/mysqld/mysqld.sock
      nice        = 0
      
      [mysqld]
      user        = root
      pid-file    = /var/run/mysqld/mysqld.pid
      socket      = /var/run/mysqld/mysqld.sock
      port        = 3306
      basedir     = /usr
      datadir     = /var/lib/mysql
      tmpdir      = /tmp
      lc-messages-dir = /usr/share/mysql
      explicit_defaults_for_timestamp
      init_connect='SET collation_connection = utf8_unicode_ci'
      init_connect='SET NAMES utf8'
      character-set-server=utf8
      collation-server=utf8_unicode_ci
      skip-character-set-client-handshake
      
      # Instead of skip-networking the default is now to listen only on
      # localhost which is more compatible and is not less secure.
      #bind-address   = 127.0.0.1
      
      #log-error  = /var/log/mysql/error.log
      
      # Recommended in standard MySQL setup
      sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
      
      # Disabling symbolic-links is recommended to prevent assorted security risks
      symbolic-links=0
      
      # * IMPORTANT: Additional settings that can override those from this file!
      #   The files must end with '.cnf', otherwise they'll be ignored.
      #
      !includedir /etc/mysql/conf.d/
      
    • Change default my.cnf with this file:

      使用此文件更改默认的my.cnf:

      docker run -it -v ./mysql/var/lib/mysql:/var/lib/mysql -v ./my.cnf::/etc/mysql/my.cnf mariadb:10.0.22

      docker运行-v ./mysql/var/lib/mysql:/var/lib/mysql -v ./my.cnf::/etc/mysql/my.cnf mariadb:10.0.22

#2


0  

When you are using docker run -v option then docker don't manipulate with files ownership. So owner of the mounted folder inside container will have the same UID as in the host system (username can be different). You can change ownership of the file or directory inside container by chmod command but it change ownership in host sytem too. So you can prepare correct ownership on your host system before you run docker container. This example demonstrates how it works (try it on your system):

当您使用docker run -v选项时,docker不会对文件所有权进行操作。因此,容器内已挂载文件夹的所有者将拥有与主机系统中相同的UID(用户名可能不同)。您可以通过chmod命令更改容器内文件或目录的所有权,但它也会更改主机sytem中的所有权。因此,在运行docker容器之前,可以在主机系统上准备正确的所有权。这个例子演示了它是如何工作的(在你的系统上试试):

I have ~/foo directory which is owned by me - my UID is 1000

我有~/foo目录,属于我-我的UID是1000

~ $ ls -lnd foo
drwxr-xr-x 2 1001 1000 4096 Nov 24 22:47 foo

Run docker container, mount ~/foo directory to them and display ownership inside container

运行docker容器、mount ~/foo目录,并显示容器内的所有权。

~ $ docker run -it --rm -v ~/foo:/tmp/foo busybox ls -ln /tmp
total 4
drwxr-xr-x    2 1000     1000          4096 Nov 24 21:47 foo

Owner UID inside container is the same. Now I change directory ownership on my computer.

容器内的所有者UID是相同的。现在我改变了我电脑上的目录所有权。

~ $ sudo chown 1001 foo

Start container again, mount the foo directory and display ownership

再次启动容器,挂载foo目录并显示所有权

~ $ docker run -it --rm -v ~/foo:/tmp/foo busybox ls -ln /tmp
total 4
drwxr-xr-x    2 1001     1000          4096 Nov 24 21:47 foo

Owner UID was changed as well

所有者UID也被更改

But there is one exception. If you try to mount volume to nonexistent directory then docker will create this missing directory automatically (but this is deprecated feature, so don't do this) and this directory will by created with UID 0. Try it:

但有一个例外。如果您试图将卷挂载到不存在的目录,那么docker将自动创建这个丢失的目录(但这是不赞成的特性,所以不要这样做),这个目录将使用UID 0创建。试一试:

~ $ docker run -it --rm -v ~/foo:/tmp/bar/foo busybox ls -ln /tmp
total 4
drwxr-xr-x    3 0        0             4096 Nov 24 22:10 bar

#3


-1  

I similarly ran into this issue; I solved it by chmod/chown'ing inside my data container, e.g.:

我同样遇到了这个问题;我用chmod/chown'ing形式在我的数据容器中解决了这个问题,例如:

FROM ubuntu

# Create data directory
RUN mkdir -p /data /var/lib/mysql
RUN chmod -R 777 /data /var/lib/mysql
RUN chown -R root:root /data /var/lib/mysql

# Create /data volume
VOLUME /data
VOLUME /var/lib/mysql

I believe this works because UFS now properly records permissions rather than relying on a direct from host mount to do so, which as you've discovered, does not work on OS X

我相信这是可行的,因为UFS现在正确地记录权限,而不是依赖于来自主机挂载的直接记录权限,正如您所发现的,这在OS X上是行不通的