Podman(或 docker)运行 MySQL 容器和共享数据目录

Podman(或 docker)运行 MySQL 容器和共享数据目录

我正在为我的开发环境运行 Ubuntu 20.04.5 LTS 虚拟机。过去,我运行过多个虚拟机来托管数据库、Web 服务器等,因为我的项目需要它们。简而言之,我是一个容器新手!

我正在尝试做的是创建一个运行 Podman 容器的 Ubuntu 虚拟机。

我当前的阻止程序是 MySQL 或任何其他 RDB。

如果我使用容器默认位置进行存储,每次启动容器时我都需要加载新的数据库转储,因为存储本质上是短暂的。这显然不是理想的。

我读过很多用例,它们指定创建一个附加或挂载的驱动器/目录来存储 MySQL 目录,这样容器每次重启后数据就不会消失。但我还没有找到如何正确设置它。

再次,我的目标是将 HOST 目录挂载为 MySQL 数据目录。

因此,首先,我创建了一个具有完全开放权限的共享数据位置:

echo "STATUS: Creating data directory for MySQL container"
sudo mkdir -p /opt/mysql/server/data
sudo chmod 777 /opt/mysql -R

然后我映射驱动器并指定数据目录:

echo "STATUS: Run container with mapped host drive"
podman run -d --replace --name=MySQL -h=mysql-pod -p=63306:3306 /
      -v="/opt/mysql/server:/var/lib/mysql" docker.io/mysql/mysql-server:8.0 /
      --basedir=/var/lib/mysql --datadir=/var/lib/mysql/data

执行此命令后,我得到以下日志条目:

podman:/vagrant/podman$ podman logs MySQL
[Entrypoint] MySQL Docker Image 8.0.30-1.2.9-server
2022-09-14T23:03:17.922048Z 0 [ERROR] [MY-010338] [Server] Can't find error-message file '/var/lib/mysql/share/mysql-8.0/errmsg.sys'. Check error-message file location and 'lc-messages-dir' configuration directive.
[Entrypoint] Initializing database
[Entrypoint] No password option specified for new database.
[Entrypoint]   A random onetime password will be generated.
mysqld: Can't create/write to file '/var/lib/mysql/data/is_writable' (OS errno 13 - Permission denied)
2022-09-14T23:03:17.954340Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
2022-09-14T23:03:17.954386Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.30) initializing of server in progress as process 12
2022-09-14T23:03:17.954403Z 0 [ERROR] [MY-010338] [Server] Can't find error-message file '/var/lib/mysql/share/mysql-8.0/errmsg.sys'. Check error-message file location and 'lc-messages-dir' configuration directive.
2022-09-14T23:03:17.954836Z 0 [ERROR] [MY-010460] [Server] --initialize specified but the data directory exists and is not writable. Aborting.
2022-09-14T23:03:17.954840Z 0 [ERROR] [MY-013236] [Server] The designated data directory /var/lib/mysql/data/ is unusable. You can remove all files that the server added to it.
2022-09-14T23:03:17.954859Z 0 [ERROR] [MY-010119] [Server] Aborting
2022-09-14T23:03:17.954918Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.30)  MySQL Community Server - GPL.

我尝试了多个权限集,在主机上创建一个 mysql 用户并赋予它目录所有权......以及其他一些事情,因为我找不到如何正确执行此操作的良好解释。

再说一次,我是一个容器新手,所以我很确定我遗漏了一些关于共享资源权限的东西,但我已经经历了一百次映射和权限迭代,并没有在网上找到任何可以使用非根 OCI (如 Podman)解决这个问题的东西。

也许答案是我必须为 Podman 强制使用 root 帐户,但我想在把笔记本电脑扔出窗外之前,我应该向社区发出呼吁。

在此先行致谢。

GC

温库尔蒙基

答案1

如果我使用容器默认位置进行存储,则每次启动容器时都需要加载新的数据库转储,因为存储本质上是短暂的。

确实,容器的主文件系统是临时的,您不应该将数据存储在那里。但是,这不是您唯一的存储选择。

Docker 和 Podman 等容器运行时支持“卷”的概念 - 由容器运行时管理的命名(或匿名)存储,运行时安装在容器中,与容器文件系统分开。卷的生命周期与相关容器无关。

所有主要数据库映像都已配置为将数据库数据存储在卷上。例如,如果您podman volume ls在运行postgres映像之前运行:

$ podman volume ls
<no output here>

然后启动(和停止)一个postgres容器:

$ podman run --rm -e POSTGRES_PASSWORD=secret docker.io/postgres:14

然后再次检查卷列表:

$ podman volume ls
DRIVER      VOLUME NAME
local       7b33982f61ec36601371803f9f4dcca66dc0a326cad1b2260ab30136b7ef6b40

您将看到已创建卷,并且即使容器已被删除,它仍会保留。这是一个“匿名”卷:它尚未被分配明确的名称,这意味着它不是特别有用(您可以使用长卷 ID 来引用它,但这并不是您与卷交互的真正方式)。为了使某些东西更易于管理,您可以创建命名卷并使用它们。例如:

$ podman run --rm -v postgres_data:/var/lib/postgres -e POSTGRES_PASSWORD=secret postgres:14

这将创建一个名为的卷postgres_data,并将其挂载到容器中的适当位置。如果您停止容器,则可以创建一个具有相同卷参数的新容器,它将可以访问相同的数据:尽管运行的是新容器,但数据库仍将继续提供相同的数据。


还可以创建“绑定挂载”——即将特定主机目录挂载到容器中。当您将文件系统路径作为 的第一个参数提供时-v,您就会这样做,如下所示:

podman run -v "/opt/postgres/server:/var/lib/postgres" docker.io/postgres:14

如果您需要在主机和容器之间共享数据,这可能很有用,但对于数据库之类的东西,底层存储实际上是一个“黑匣子”(访问它的唯一方式是通过数据库服务器),卷通常更容易管理。

如果您想使用绑定挂载进行存储来通过 podman 启动 MySQL 容器,则需要确保该目录可由容器中的 mysql 用户写入。

您创建了一个如下目录:

sudo mkdir -p /opt/mysql/server/data
sudo chmod 777 /opt/mysql -R

这看起来应该可以工作,因为数据目录是全世界可写的,但是存在两个问题:

  • MySQL 容器中的启动脚本将尝试更改数据目录的所有者。由于我们没有权限执行此操作,因此我们的容器也没有该权限。

  • 即使这不是问题,强制访问控制系统linux系统仍可能造成阻碍。

如果我们拥有数据目录,事情就会变得更好:

sudo mkdir /opt/mysql
sudo chown $UID:$UID /opt/mysql
mkdir -p /opt/mysql/server/data
podman run -d --replace --name=MySQL -p 63306:3306 \
      -v "/opt/mysql/server/data:/var/lib/mysql" \
      docker.io/mysql/mysql-server:8.0

如果我们正在运行 selinux,我们需要修改-v选项以包含:z限定符,如下所示:

      -v "/opt/mysql/server/data:/var/lib/mysql:z" \

我们可以通过仅使用主目录的子目录而不是在以下位置创建目录来简化一些事情/opt

mkdir -p $HOME/data/mysql
podman run -d --replace --name=MySQL -p 63306:3306 \
      -v "$HOME/data/mysql:/var/lib/mysql:z" \
      docker.io/mysql/mysql-server:8.0

但是,正如我之前指出的那样,使用卷可以消除大部分混乱,因为容器运行时负责分配和管理存储:

podman run -d --replace --name=MySQL -p 63306:3306 \
      -v mysql_data:/var/lib/mysql \
      docker.io/mysql/mysql-server:8.0

您可以在 Docker 的“在 Docker 中管理数据“文档,以及相关的“使用卷“ 和 ”使用绑定挂载“文档。这里的材料同样适用于 Podman。

相关内容