You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器内MariaDB服务无法停止的问题求助

问题:基于Debian构建MariaDB Docker容器启动/停止失败

环境配置

Dockerfile

FROM debian:buster

RUN apt-get update -y && apt-get upgrade -y && apt-get install wget mariadb-server procps -y
COPY ./tools/init.sh /tmp/init.sh
RUN chmod +x /tmp/init.sh 
EXPOSE 3306
RUN sed -i 's/^bind-address\s*=.*/bind-address=0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf
ENTRYPOINT [ "sh", "/tmp/init.sh" ]
CMD [ "mysqld_safe" , "--verbose"]

初始化脚本 init.sh

service mysql start && service mysql stop

错误现象

容器启动后出现如下报错:

db             | Starting MariaDB database server: mysqld.
db             | ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
db             | Stopping MariaDB database server: mysqld failed!
db exited with code 1

已尝试的排查动作

  • 手动进入Debian容器,逐行执行Dockerfile中的指令,能正常启动、停止数据库服务
  • 在Dockerfile中添加RUN指令尝试重置root密码,未解决问题:
    RUN service mysql start &&  mysql -u root -e  "ALTER USER 'root'@'localhost' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD'; FLUSH PRIVILEGES;"
    

原因分析

  1. Docker构建与运行阶段的差异:RUN指令在镜像构建时执行,此时启动的mysql服务不会保留到容器运行阶段。运行阶段启动的是全新的数据库实例,未完成初始化流程。
  2. service命令的适配问题:service mysql stop本质是调用mysqladmin连接数据库发送停止信号,但容器首次启动时,数据库刚完成启动初始化,root用户默认使用unix_socket认证方式(而非密码),mysqladmin默认尝试TCP连接,导致认证失败,无法停止服务。
  3. 容器主进程设计问题:Docker容器应直接以数据库进程为主进程,而非通过service命令启停管理,否则无法正确处理信号、保证容器生命周期与进程一致。

解决方案

修改初始化脚本 init.sh

将脚本改为首次启动时完成数据库初始化,直接运行数据库主进程,而非启停服务:

#!/bin/sh

# 检查数据库是否已初始化(判断mysql系统库是否存在)
if [ ! -d "/var/lib/mysql/mysql" ]; then
    # 初始化无密码的root用户
    mysqld --initialize-insecure
    
    # 启动临时数据库实例,用于配置权限
    mysqld_safe &
    # 等待数据库完全启动
    until mysqladmin ping -h localhost --silent; do
        sleep 1
    done

    # 配置root本地无密码访问(保持默认行为)
    mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY ''; FLUSH PRIVILEGES;"
    # 可选:允许root远程访问(根据需求开启)
    # mysql -u root -e "CREATE USER 'root'@'%' IDENTIFIED BY ''; GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES;"

    # 停止临时实例
    mysqladmin -u root shutdown
fi

# 以exec方式启动数据库主进程,确保容器能接收信号
exec mysqld_safe --verbose

调整Dockerfile(可选优化)

可以移除CMD指令,因为初始化脚本最后已经用exec启动了主进程,或者保持原配置不影响:

FROM debian:buster

RUN apt-get update -y && apt-get upgrade -y && apt-get install mariadb-server procps -y && rm -rf /var/lib/apt/lists/*
COPY ./tools/init.sh /tmp/init.sh
RUN chmod +x /tmp/init.sh 
EXPOSE 3306
RUN sed -i 's/^bind-address\s*=.*/bind-address=0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf
ENTRYPOINT [ "sh", "/tmp/init.sh" ]

验证方式

构建镜像后启动容器:

docker build -t my-mariadb .
docker run -d -p 3306:3306 --name db my-mariadb

查看容器日志确认无报错,即可通过mysql -h localhost -u root连接数据库。

内容的提问来源于stack exchange,提问作者interesting

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:10:41