环境:Linux version 5.15.0-92-generic,Docker version 26.1.3,mariadb from 11.3.2-MariaDB

  1. 首先是 MariaDB 在 Docker 官网 给出的,运行一个 MariaDB 的最简化配置方案。

    docker run --detach --name some-mariadb --env MARIADB_ROOT_PASSWORD=my-secret-pw mariadb:latest
    

    --detach 也就是 -d 后台运行,--name 顾名思义是容器的名字,--env 同理是环境配置,MARIADB_ROOT_PASSWORD 这里初始化了 root 用户的密码为 my-secret-pw ,最后 mariadb:latest 使用 MariaDB 的最新版本。

    我们在服务器上执行如下命令,尝试本地连接上 Docker 中的数据库,

    mariadb -uroot -pmy-secret-pw
    

    -u 指定用户名,-p 指定用户的密码,-P 指定端口号。

    ```bash
    \# mariadb -uroot -pmy-secret-pw
    

    如果你本地没有下载过数据库核心的话,可能会提示你去下载 **-core,按照提示下载即可。然后就可以成功收获一条 ERROR (恭喜),

    ERROR 2002 (HY000): Can't connect to local server through socket '/run/mysqld/mysqld.sock' (2) ,这种方式就是通过 本地 sock 连接,我们本地根本就没安装 MariaDB,自然也就无法通过 sock 进行连接。

    再尝试指定端口进行连接,

    mariadb -uroot -pmy-secret-pw -P3306
    

    ERROR 2002 (HY000): Can't connect to server on 'localhost' (115)

    这是因为我们在创建容器的时候并没有进行端口映射 -p [本机端口]:[容器端口(数据库的话也就是3306)] ,连接数据库也就无从谈起了。

  2. 于是我们删除之前的容器,加上端口重新创建容器,

    docker stop some-mariadb && docker rm some-mariadb
    
    docker run --detach --name some-mariadb --env MARIADB_ROOT_PASSWORD=my-secret-pw -p 3306:3306 mariadb:latest
    

    尝试连接,

    mariadb -uroot -pmy-secret-pw -P3306
    
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MariaDB connection id is 3
    Server version: 11.3.2-MariaDB-1:11.3.2+maria~ubu2204 mariadb.org binary distribution
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    MariaDB [(none)]>
    

    连接成功!

    然鹅,我们一般并不会用这样的容器。而是会选择 -v 进行数据卷映射。

  3. 同样的,我们以 官方文档 为主,在 Caveats 中的 Where to Store Data 可以看到关于数据卷映射的相关内容,并且可以看到,官方是更推荐这种方式创建的。

于是,我们先 stoprm 之前没有 -v 映射的 MariaDB 容器,

docker stop some-mariadb && docker rm some-mariadb

然后按照文档创建数据卷映射 -v [local dir]:[container dir] ,并添加上 -p 的端口映射。

docker run --name some-mariadb -v /my/own/datadir:/var/lib/mysql:Z -e MARIADB_ROOT_PASSWORD=my-secret-pw -p 3306:3306 -d mariadb:latest

尝试本地通过端口连接,

mariadb -uroot -pmy-secret-pw -P3306
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 11.3.2-MariaDB-1:11.3.2+maria~ubu2204 mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

连接成功✌️!

但是,我的连接并非这样一帆风顺。

  1. 数据卷映射后无法连接,场景复现。

    1. 创建容器

      docker run --name mariadb1 -v /my/own/datadir:/var/lib/mysql:Z -e MARIADB_ROOT_PASSWORD=my-secret-pw -p 3306:3306 -d mariadb:latest
      
      docker run --name mariadb2 -v /my/own/datadir:/var/lib/mysql:Z -e MARIADB_ROOT_PASSWORD=my-secret-pw -p 3307:3306 -d mariadb:latest
      
    2. 运行测试

      mariadb -uroot -pmy-secret-pw -P3306
      
      mariadb -uroot -pmy-secret-pw -P3307
      

      mariadb1 运行成功,mariadb2 报错,ERROR 2002 (HY000): Can't connect to server on 'localhost' (115)

    3. 停止 mariadb1 容器,再测试连接

      docker stop mariadb1
      
      mariadb -uroot -pmy-secret-pw -P3307
      

      ERROR 2002 (HY000): Can't connect to server on 'localhost' (115) ,报错,连接失败。

    4. 删除 mariadb1 容器,再测试连接

      docker rm mariadb1
      
      mariadb -uroot -pmy-secret-pw -P3307
      

      ERROR 2002 (HY000): Can't connect to server on 'localhost' (115) ,报错相同,仍然失败。

    5. 进入容器内部,测试 MariaDB 是否正常运行

      docker exec -it mariadb2 bash
      

      Error response from daemon: container b54a939866dd471a9efe1f8ec0009bffe8a4115f55c8dec685cc8a5afc638ad3 is not running 进入失败,容器未运行。

      [如果你的容器没有问题,可以跳到 8.问题遗留 看看]

    6. 重启容器

      docker start mariadb2
      
      mariadb -uroot -pmy-secret-pw -P3307
      

      连接成功!😭

    7. 结论

      -v 映射了相同目录,导致容器无法正常启动。

    8. 问题遗留

      当时我记得容器是正常运行的,也可以进入到容器内正常连接到数据库。

      但是,这种情况并没能复现出来?

      我当时用的是 MySQL 和 MariaDB 两种数据库并且都进行了映射。

      应该仍然是 -v 映射的问题,只是懒得再复现了。

      [当时删除了 -v 本地目录下的所有文件,并 restart 一下就 👌 了]

  2. 后日谈

    虽然是个简单的问题,但是当时并没有这样条理清晰的进行测试复现工作,从而浪费几个小时,并且被烦躁的情绪所困扰。