如何重新创建使用卷的 docker mysql 映像?

时间:2021-07-28 05:42:44

标签: docker docker-compose

我正在使用 docker-compose 创建一个 mysql 容器,并在其中创建一个数据库。如果我手动删除数据库,无论我做什么,都无法重新创建容器并强制它也重新创建数据库。

这是我的 docker-compose.yml:

version: '3'
services:
  mysql:
    container_name: mysqltest-db
    image: mysql:5.6.51
    volumes:
      - ./my_volume:/var/lib/mysql
      - ./data/init.sql:/docker-entrypoint-initdb.d/1.init.sql
    command: --default-authentication-plugin=mysql_native_password
    ports:
      - 3306:3306
    environment:
       MYSQL_ROOT_PASSWORD: root
       MYSQL_DATABASE: my_database
       MYSQL_USER: my_user
       MYSQL_PASSWORD: mypass

volumes:
  my_volume: {}

init.sql 脚本只是创建一个数据库:

CREATE DATABASE IF NOT EXISTS my_database;
GRANT ALL PRIVILEGES ON my_database.* TO my_user@'%' IDENTIFIED BY 'mypass';
FLUSH PRIVILEGES;

第一次我运行 docker-compose up,一切正常。我可以用docker container exec -it mysqltest-db bash登录mysql,然后用mysql -u root -proot登录mysql,然后运行show databases。果然,有my_database

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| my_database        |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.01 sec)

接下来我通过运行 drop database my_database手动删除数据库。

然后我 ctrl+c 杀死容器,然后运行 ​​docker-compose down -v。据我了解,-v 应该销毁包含 mysql 数据的卷。我通过运行 docker volume ls 检查它是否真的消失了,并确认 dockertest_my_volume 卷不再存在。

然后我运行 docker-compose pull && docker-compose up -V --force-recreate 来重新创建容器。这就是我被困的地方。当我登录容器,然后登录 mysql,再次运行 show databases 时,my_database 仍然不见了:

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.01 sec)

强制 Docker 从头开始​​完全重建,以便第二次创建 mysql 数据库,我缺少什么?

第一次和第二次运行之间的日志输出量显然存在很大差异。但是在这两种情况下,似乎都在创建一个卷:

$-> docker-compose up -V --force-recreate
Docker Compose is now in the Docker CLI, try `docker compose up`

Creating network "dockertest_default" with the default driver
Creating volume "dockertest_my_volume" with default driver
Creating mysqltest-db ... done
Attaching to mysqltest-db

2 个答案:

答案 0 :(得分:1)

哇,终于轻松了。 Docker 卷是名称,而不是路径。你有:

volumes:
      - ./my_volume:/var/lib/mysql

将本地文件系统上相对于上下文(您启动容器的文件夹)的路径 ./my_volume 装入路径 /var/lib/mysql 处的容器中。你真正想要的是:

volumes:
      - my_volume:/var/lib/mysql

其中包含卷引用(命名卷)。这会在容器内创建/安装卷 my_volume/var/lib/mysql

您可以诊断问题,因为您将在 my_volume 文件旁边有一个名为 docker-compose.yaml 的目录。检查这一点的另一种方法是在容器运行时执行 docker volume ls,您会注意到没有 my_volume 卷(运行您的代码时,不是我的 - 当您运行我的代码时,它会工作;).

虽然很容易修复:)

答案 1 :(得分:1)

Docker 有两种内置存储,named volumesbind mounts。它们的语法非常相似,但命名卷将 Docker 管理的存储附加到容器,而绑定挂载则直接附加一些主机目录。

您的 docker-compose.yml 文件说:

volumes:
  - ./my_volume:/var/lib/mysql

这是绑定挂载语法;它直接在您的主机系统上命名路径。 (如果您仔细观察,您可以看到 my_volume 目录和其中的 MySQL 数据文件。)

MySQL 映像启动序列知道在 /var/lib/mysql 目录中查找,并且如果该目录为空,它将执行首次初始化序列。如果那里有 MySQL 安装,它不会重新运行初始化脚本,即使您删除了那里的内容。如果它是命名卷或绑定安装,则这是相同的行为。

就您而言,即使您删除了数据库,MySQL 系统文件仍然存在。您可以强制它从头开始:

docker-compose rm --stop mysql
rm -rf my_volume
docker-compose up -d
相关问题