使用容器化数据库

使用本地容器化数据库提供了灵活性和易于设置的优势,让您可以紧密地模拟生产环境,而无需传统数据库安装的开销。Docker 简化了此过程,使您可以仅用几个命令即可在隔离的容器中部署、管理和扩展数据库。

在本指南中,您将学习如何

  • 运行本地容器化数据库
  • 访问容器化数据库的 shell
  • 从主机连接到容器化数据库
  • 从另一个容器连接到容器化数据库
  • 在卷中持久化数据库数据
  • 构建自定义数据库镜像
  • 使用 Docker Compose 运行数据库

本指南使用 MySQL 镜像作为示例,但这些概念可以应用于其他数据库镜像。

先决条件

要按照本指南进行操作,您必须安装 Docker。要安装 Docker,请参阅 获取 Docker

运行本地容器化数据库

大多数流行的数据库系统,包括 MySQL、PostgreSQL 和 MongoDB,在 Docker Hub 上都提供 Docker 官方镜像。这些镜像是一组经过精心挑选的镜像,遵循最佳实践,确保您可以访问最新的功能和安全更新。要开始使用,请访问 Docker Hub 并搜索您感兴趣的数据库。每个镜像的页面都提供了有关如何运行容器、自定义设置和根据您的需求配置数据库的详细说明。有关本指南中使用的 MySQL 镜像的更多信息,请参阅 Docker Hub MySQL 镜像 页面。

要运行数据库容器,您可以使用 Docker Desktop GUI 或 CLI。


要使用 CLI 运行容器,请在终端中运行以下命令

$ docker run --name my-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_DATABASE=mydb -d mysql:latest

在此命令中

  • --name my-mysql 为您的容器分配名称 my-mysql,以便于参考。
  • -e MYSQL_ROOT_PASSWORD=my-secret-pw 将 MySQL 的 root 密码设置为 my-secret-pw。将 my-secret-pw 替换为您选择的安全密码。
  • -e MYSQL_DATABASE=mydb 可选地创建一个名为 mydb 的数据库。您可以将 mydb 更改为您想要的数据库名称。
  • -d 以分离模式运行容器,这意味着它在后台运行。
  • mysql:latest 指定您要使用最新版本的 MySQL 镜像。

要验证您的容器是否正在运行,请在终端中运行 docker ps

要使用 GUI 运行容器

  1. 在 Docker Desktop 仪表板中,选择窗口顶部的全局搜索。

  2. 在搜索框中指定 mysql,如果尚未选择,请选择 Images 选项卡。

  3. 将鼠标悬停在 msyql 镜像上,然后选择 Run。“运行新容器”模型将出现。

  4. 展开 **可选设置**。

  5. 在可选设置中,指定以下内容

    • **容器名称**: my-mysql
    • 环境变量:
      • MYSQL_ROOT_PASSWORD:my-secret-pw
      • MYSQL_DATABASE:mydb
    The optional settings screen with the options specified.
  6. 选择 Run

  7. 在 Docker Desktop 仪表板中打开 **容器** 视图以验证您的容器是否正在运行。


访问容器化数据库的 shell

当您在 Docker 容器内运行数据库时,您可能需要访问其 shell 来管理数据库、执行命令或执行管理任务。Docker 提供了一种使用 docker exec 命令直接执行此操作的方法。此外,如果您更喜欢图形界面,可以使用 Docker Desktop 的 GUI。

如果您尚未运行数据库容器,请参阅 运行本地容器化数据库


要使用 CLI 访问 MySQL 容器的终端,您可以使用以下 docker exec 命令。

$ docker exec -it my-mysql bash

在此命令中

  • docker exec 告诉 Docker 您想要在一个正在运行的容器中执行一个命令。
  • -it 确保您访问的终端是交互式的,因此您可以将命令输入到其中。
  • my-mysql 是您的 MySQL 容器的名称。如果您在运行容器时将其命名为其他名称,请改用该名称。
  • bash 是您想要在容器内运行的命令。它打开一个 bash shell,让您可以与容器的文件系统和已安装的应用程序交互。

执行此命令后,您将获得对 MySQL 容器内 bash shell 的访问权限,您可以从中直接管理 MySQL 服务器。您可以运行 exit 返回到您的终端。

  1. 打开 Docker Desktop 仪表板并选择 **容器** 视图。
  2. 在容器的 **操作** 列中,选择 **显示容器操作**,然后选择 **在终端中打开**。

在此终端中,您可以访问 MySQL 容器内的 shell,从中可以直接管理您的 MySQL 服务器。


访问容器终端后,您可以运行该容器中可用的任何工具。以下示例显示了在容器中使用 mysql 列出数据库。

# mysql -u root -p
Enter password: my-secret-pw

mysql> SHOW DATABASES;

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydb               |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

从主机连接到容器化数据库

从主机连接到容器化数据库涉及将容器内的端口映射到主机上的端口。此过程确保可以通过主机机的网络访问容器内的数据库。对于 MySQL,默认端口为 3306。通过公开此端口,您可以使用主机上的各种数据库管理工具或应用程序与您的 MySQL 数据库进行交互。

在开始之前,您必须删除之前为此指南运行的任何容器。要停止并删除容器,您可以:

  • 在终端中,运行 docker remove --force my-mysql 删除名为 my-mysql 的容器。
  • 或者,在 Docker Desktop 仪表板中,选择 **容器** 视图中容器旁边的 **删除** 图标。

接下来,您可以使用 Docker Desktop GUI 或 CLI 来运行带有端口映射的容器。


在终端中运行以下命令。

$ docker run -p 3307:3306 --name my-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_DATABASE=mydb -d mysql:latest

在此命令中,-p 3307:3306 将主机的 3307 端口映射到容器中的 3306 端口。

要验证端口是否已映射,请运行以下命令。

$ docker ps

您应该看到如下输出。

CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                               NAMES
6eb776cfd73c   mysql:latest   "docker-entrypoint.s…"   17 minutes ago   Up 17 minutes   33060/tcp, 0.0.0.0:3307->3306/tcp   my-mysql

要使用 GUI 运行容器

  1. 在 Docker Desktop 仪表板中,选择窗口顶部的全局搜索。

  2. 在搜索框中指定 mysql,如果尚未选择,请选择 Images 选项卡。

  3. 将鼠标悬停在 msyql 镜像上,然后选择 Run。“运行新容器”模型将出现。

  4. 展开 **可选设置**。

  5. 在可选设置中,指定以下内容

    • **容器名称**: my-mysql
    • **主机端口** 用于 **3306/tcp** 端口:3307
    • 环境变量:
      • MYSQL_ROOT_PASSWORD:my-secret-pw
      • MYSQL_DATABASE:mydb
    The optional settings screen with the options specified.
  6. 选择 Run

  7. 在 **容器** 视图中,验证端口是否已在 **端口(s)** 列下映射。您应该在 **my-mysql** 容器中看到 **3307:3306**。


此时,主机上运行的任何应用程序都可以通过 localhost:3307 访问容器中的 MySQL 服务。

从另一个容器连接到容器化数据库

从另一个容器连接到容器化数据库是在微服务架构和开发过程中常见的场景。Docker 的网络功能使得轻松建立此连接成为可能,而无需将数据库公开到主机网络。这是通过将数据库容器和需要访问它的容器都放置在同一个 Docker 网络上实现的。

在开始之前,您必须删除之前为此指南运行的任何容器。要停止并删除容器,您可以:

  • 在终端中,运行 docker remove --force my-mysql 删除名为 my-mysql 的容器。
  • 或者,在 Docker Desktop 仪表板中,选择 **容器** 视图中容器旁边的 **删除** 图标。

要创建网络并在其上运行容器

  1. 运行以下命令以创建一个名为 my-network 的 Docker 网络。

    $ docker network create my-network
    
  2. 运行您的数据库容器并使用 --network 选项指定网络。这将在 my-network 网络上运行容器。

    $ docker run --name my-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_DATABASE=mydb --network my-network -d mysql:latest
    
  3. 运行您的其他容器并使用 --network 选项指定网络。在此示例中,您将运行一个可以连接到数据库的 phpMyAdmin 容器。

    1. 运行一个 phpMyAdmin 容器。使用--network选项指定网络,使用-p选项允许您从主机访问容器,并使用-e选项指定此镜像所需的環境變量。

      $ docker run --name my-phpmyadmin -d --network my-network -p 8080:80 -e PMA_HOST=my-mysql phpmyadmin
      
  4. 验证容器之间可以通信。在本例中,您将访问 phpMyAdmin 并验证它是否连接到数据库。

    1. 打开http://localhost:8080来访问您的 phpMyAdmin 容器。
    2. 使用root作为用户名和my-secret-pw作为密码登录。您应该连接到 MySQL 服务器并看到您的数据库列表。

此时,在您的my-network容器网络上运行的任何应用程序都可以通过my-mysql:3306访问容器中的MySQL服务。

在卷中持久化数据库数据

将数据库数据持久化到 Docker 卷对于确保您的数据在容器重启和删除后仍然存在是必要的。Docker 卷允许您将数据库文件存储在容器的可写层之外,从而可以升级容器、切换基础并共享数据而不会丢失数据。以下是如何使用 Docker CLI 或 Docker Desktop GUI 将卷附加到您的数据库容器。

在开始之前,您必须删除之前为此指南运行的任何容器。要停止并删除容器,您可以:

  • 在终端中,运行 docker remove --force my-mysql 删除名为 my-mysql 的容器。
  • 或者,在 Docker Desktop 仪表板中,选择 **容器** 视图中容器旁边的 **删除** 图标。

接下来,您可以使用 Docker Desktop GUI 或 CLI 来运行带有卷的容器。


要运行附加了卷的数据库容器,请在您的docker run命令中包含-v选项,指定卷名称和数据库在容器内存储数据的路径。如果卷不存在,Docker 会自动创建它。

运行一个附加了卷的数据库容器,然后验证数据是否持久化。

  1. 运行容器并附加卷。

    $ docker run --name my-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_DATABASE=mydb -v my-db-volume:/var/lib/mysql -d mysql:latest
    

    此命令将名为my-db-volume的卷挂载到容器中的/var/lib/mysql目录。

  2. 在数据库中创建一些数据。使用docker exec命令在容器内运行mysql并创建一个表。

    $ docker exec my-mysql mysql -u root -pmy-secret-pw -e "CREATE TABLE IF NOT EXISTS mydb.mytable (column_name VARCHAR(255)); INSERT INTO mydb.mytable (column_name) VALUES ('value');"
    

    此命令使用容器中的mysql工具创建一个名为mytable的表,该表包含一个名为column_name的列,最后插入值为value

  3. 停止并删除容器。如果没有卷,删除容器时您创建的表将丢失。

    $ docker remove --force my-mysql
    
  4. 启动一个附加了卷的新容器。这次,您不需要指定任何环境变量,因为配置已保存在卷中。

    $ docker run --name my-mysql -v my-db-volume:/var/lib/mysql -d mysql:latest
    
  5. 验证您创建的表是否仍然存在。再次使用docker exec命令在容器内运行mysql

    $ docker exec my-mysql mysql -u root -pmy-secret-pw -e "SELECT * FROM mydb.mytable;"
    

    此命令使用容器中的mysql工具从mytable表中选择所有记录。

    您应该看到如下输出。

    column_name
    value
    

运行一个附加了卷的数据库容器,然后验证数据是否持久化。

  1. 运行一个附加了卷的容器。

    1. 在 Docker Desktop 仪表板中,选择窗口顶部的全局搜索。

    2. 在搜索框中指定mysql,如果尚未选择,请选择镜像选项卡。

    3. 将鼠标悬停在mysql镜像上,然后选择运行。将出现运行新容器模型。

    4. 展开 **可选设置**。

    5. 在可选设置中,指定以下内容

      • **容器名称**: my-mysql
      • 环境变量:
        • MYSQL_ROOT_PASSWORD:my-secret-pw
        • MYSQL_DATABASE:mydb
      • :
        • my-db-volume:/var/lib/mysql
      The optional settings screen with the options specified.

      这里,卷的名称是my-db-volume,它在容器中挂载到/var/lib/mysql

    6. 选择 Run

  2. 在数据库中创建一些数据。

    1. 容器视图中,在您的容器旁边选择显示容器操作图标,然后选择在终端中打开

    2. 在容器的终端中运行以下命令以添加表。

      # mysql -u root -pmy-secret-pw -e "CREATE TABLE IF NOT EXISTS mydb.mytable (column_name VARCHAR(255)); INSERT INTO mydb.mytable (column_name) VALUES ('value');"
      

      此命令使用容器中的mysql工具创建一个名为mytable的表,该表包含一个名为column_name的列,最后插入值为`value`。

  3. 容器视图中,选择您容器旁边的删除图标,然后选择永久删除。如果没有卷,删除容器时您创建的表将丢失。

  4. 运行一个附加了卷的容器。

    1. 在 Docker Desktop 仪表板中,选择窗口顶部的全局搜索。

    2. 在搜索框中指定mysql,如果尚未选择,请选择镜像选项卡。

    3. 将鼠标悬停在mysql镜像上,然后选择运行。将出现运行新容器模型。

    4. 展开 **可选设置**。

    5. 在可选设置中,指定以下内容

      • **容器名称**: my-mysql
      • 环境变量:
        • MYSQL_ROOT_PASSWORD:my-secret-pw
        • MYSQL_DATABASE:mydb
      • :
        • my-db-volume:/var/lib/mysql
      The optional settings screen with the options specified.
    6. 选择 Run

  5. 验证您创建的表是否仍然存在。

    1. 容器视图中,在您的容器旁边选择显示容器操作图标,然后选择在终端中打开

    2. 在容器的终端中运行以下命令以验证您创建的表是否仍然存在。

      # mysql -u root -pmy-secret-pw -e "SELECT * FROM mydb.mytable;"
      

      此命令使用容器中的mysql工具从mytable表中选择所有记录。

      您应该看到如下输出。

      column_name
      value
      

此时,任何挂载了my-db-volume的MySQL容器都能够访问和保存持久化数据。

构建自定义数据库镜像

自定义您的数据库镜像允许您在基本数据库服务器旁边包含其他配置、脚本或工具。这对于创建与您的特定开发或生产环境需求匹配的 Docker 镜像特别有用。以下示例概述了如何构建和运行包含表初始化脚本的自定义 MySQL 镜像。

在开始之前,您必须删除之前为此指南运行的任何容器。要停止并删除容器,您可以:

  • 在终端中,运行 docker remove --force my-mysql 删除名为 my-mysql 的容器。
  • 或者,在 Docker Desktop 仪表板中,选择 **容器** 视图中容器旁边的 **删除** 图标。

构建和运行您的自定义镜像

  1. 创建一个 Dockerfile。

    1. 在您的项目目录中创建一个名为Dockerfile的文件。在本例中,您可以在您选择的空目录中创建Dockerfile。此文件将定义如何构建您的自定义 MySQL 镜像。

    2. 将以下内容添加到Dockerfile

      # syntax=docker/dockerfile:1
      
      # Use the base image mysql:latest
      FROM mysql:latest
      
      # Set environment variables
      ENV MYSQL_DATABASE mydb
      
      # Copy custom scripts or configuration files from your host to the container
      COPY ./scripts/ /docker-entrypoint-initdb.d/

      在此 Dockerfile 中,您已设置 MySQL 数据库名称的环境变量。您还可以使用COPY指令将自定义配置文件或脚本添加到容器中。在本例中,来自主机./scripts/目录的文件被复制到容器的/docker-entrypoint-initdb.d/目录。在此目录中,.sh.sql.sql.gz脚本在容器首次启动时执行。有关 Dockerfile 的更多详细信息,请参见Dockerfile 参考

    3. 创建一个脚本文件以初始化数据库中的表。在您的Dockerfile所在的目录中,创建一个名为scripts的子目录,然后创建一个名为create_table.sql的文件,内容如下。

    CREATE TABLE IF NOT EXISTS mydb.myothertable (
      column_name VARCHAR(255)
    );
    
    INSERT INTO mydb.myothertable (column_name) VALUES ('other_value');

    您现在应该具有以下目录结构。

    ├── your-project-directory/
    │ ├── scripts/
    │ │ └── create_table.sql
    │ └── Dockerfile
  2. 构建您的镜像。

    1. 在终端中,将目录更改为您的Dockerfile所在的目录。

    2. 运行以下命令来构建镜像。

      $ docker build -t my-custom-mysql .
      

      在此命令中,-t my-custom-mysql将您的新镜像标记(命名)为my-custom-mysql。命令末尾的句点 (.) 指定当前目录作为构建的上下文,Docker 在此处查找 Dockerfile 和构建所需的任何其他文件。

  3. 像在运行本地容器化数据库中那样运行您的镜像。这次,指定您的镜像名称而不是mysql:latest。此外,您不再需要指定MYSQL_DATABASE环境变量,因为它现在由您的 Dockerfile 定义。

    $ docker run --name my-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d my-custom-mysql
    
  4. 使用以下命令验证您的容器是否正在运行。

    $ docker ps
    

    您应该看到如下输出。

    CONTAINER ID   IMAGE              COMMAND                  CREATED        STATUS          PORTS                 NAMES
    f74dcfdb0e59   my-custom-mysql   "docker-entrypoint.s…"    2 hours ago    Up 51 minutes   3306/tcp, 33060/tcp   my-mysql
    
  5. 验证您的初始化脚本是否已运行。在终端中运行以下命令以显示myothertable表的内容。

    $ docker exec my-mysql mysql -u root -pmy-secret-pw -e "SELECT * FROM mydb.myothertable;"
    

    您应该看到如下输出。

    column_name
    other_value
    

使用您的my-custom-mysql镜像运行的任何容器都将在首次启动时初始化表。

使用 Docker Compose 运行数据库

Docker Compose 是一种用于定义和运行多容器 Docker 应用程序的工具。使用单个命令,您可以配置所有应用程序的服务(如数据库、Web 应用程序等)并进行管理。在本例中,您将创建一个 Compose 文件并使用它来运行 MySQL 数据库容器和 phpMyAdmin 容器。

使用 Docker Compose 运行您的容器

  1. 创建一个 Docker Compose 文件。

    1. 在您的项目目录中创建一个名为compose.yaml的文件。此文件将定义服务、网络和卷。

    2. 将以下内容添加到compose.yaml文件。

      services:
        db:
          image: mysql:latest
          environment:
            MYSQL_ROOT_PASSWORD: my-secret-pw
            MYSQL_DATABASE: mydb
          ports:
            - 3307:3306
          volumes:
            - my-db-volume:/var/lib/mysql
      
        phpmyadmin:
          image: phpmyadmin/phpmyadmin:latest
          environment:
            PMA_HOST: db
            PMA_PORT: 3306
            MYSQL_ROOT_PASSWORD: my-secret-pw
          ports:
            - 8080:80
          depends_on:
            - db
      
      volumes:
        my-db-volume:

      对于数据库服务

      • db是服务的名称。
      • image: mysql:latest指定该服务使用来自 Docker Hub 的最新 MySQL 镜像。
      • environment列出了 MySQL 用于初始化数据库的环境变量,例如 root 密码和数据库名称。
      • ports将主机的 3307 端口映射到容器中的 3306 端口,允许您从主机连接到数据库。
      • volumesmy-db-volume挂载到容器内的/var/lib/mysql以持久化数据库数据。

      除了数据库服务之外,还有一个 phpMyAdmin 服务。默认情况下,Compose 为您的应用程序设置单个网络。每个服务的容器都加入默认网络,并且可以通过该网络上的其他容器访问,并且可以通过服务的名称发现。因此,在PMA_HOST环境变量中,您可以指定服务名称db以连接到数据库服务。有关 Compose 的更多详细信息,请参见Compose 文件参考

  2. 运行 Docker Compose。

    1. 打开终端并将目录更改为您的compose.yaml文件所在的目录。

    2. 使用以下命令运行 Docker Compose。

      $ docker compose up
      

      您现在可以访问http://localhost:8080并使用root作为用户名和my-secret-pw作为密码连接到您的数据库。

    3. 要停止容器,请在终端中按ctrl+c

现在,使用 Docker Compose,您可以启动数据库和应用程序、挂载卷、配置网络等等,所有这些都只需一个命令即可完成。

总结

本指南介绍了使用容器化数据库(特别是 MySQL)的基础知识,重点介绍了如何增强开发环境的灵活性和易用性,并保持一致性。本指南中介绍的用例不仅简化了您的开发工作流程,还为您准备了更高级的数据库管理和部署场景,确保您的数据驱动应用程序保持健壮和可扩展。

相关信息