【Dockerfile 实战:基于 Ubuntu/CentOS 镜像构建 MySQL 8.4自定义镜像】

提示:本文原创作品,良心制作,干货为主,简洁清晰,一看就会

文章目录


前言

MySQL作为主流开源数据库,在容器化部署场景中,基于不同系统镜像构建定制化MySQL镜像尤为关键。本文分别以Ubuntu和CentOS两大主流Linux发行版为基础,详细拆解MySQL镜像的构建流程,从环境配置、依赖安装到非交互式密码设置、服务启动等核心环节逐一讲解,帮助读者掌握跨系统的MySQL容器镜像构建方法,适配不同的部署环境需求

一、基于ubuntu镜像构建mysql镜像

MySQL官网:https://dev.mysql.com/downloads/mysql/

先在mysql官网下载好对应系统版本的tar包

1.1 前置环境准备

bash 复制代码
# 1. 准备前置环境
root@docker1:~# docker pull ubuntu:22.04   #准备基础镜像
root@docker1:~# mkdir -p /data/docker-images/mysql   #准备dockerfile目录
root@docker1:~# cd /data/docker-images/mysql
root@docker1:/data/docker-images/mysql# ls   #下载tar包到该目录
mysql-server_8.4.8-1ubuntu22.04_amd64.deb-bundle.tar

1.2 编写dockerfile

bash 复制代码
# 2. 编写Dockerfile
root@docker1:~# vim /data/docker-images/mysql/Dockerfile 
FROM ubuntu:22.04

# 设置非交互式环境(关键:避免 apt/debconf 弹出交互窗口)
ENV DEBIAN_FRONTEND=noninteractive
# 预先设置 MySQL root 密码(可自定义,建议容器部署时通过 --env 覆盖)
ENV MYSQL_ROOT_PASSWD=qing@123

# 安装基础依赖和工具
RUN apt update && \
    apt install -y \
    libaio1 \
    libmecab2 \
    libnuma1 \
    lsb-release \
    perl \
    psmisc \
    libsasl2-2 \
    libsasl2-modules \
    libsasl2-modules-db \
    wget \
    && rm -rf /var/lib/apt/lists/*

RUN mkdir /mysql-install
ADD mysql-server_8.4.8-1ubuntu22.04_amd64.deb-bundle.tar /mysql-install

# 设置 MySQL root 密码
RUN debconf-set-selections <<EOF
mysql-community-server mysql-community-server/root-pass password ${MYSQL_ROOT_PASSWD}
mysql-community-server mysql-community-server/re-root-pass password ${MYSQL_ROOT_PASSWD}
EOF

WORKDIR /mysql-install

# 按正确顺序安装所有 MySQL 包
RUN dpkg -i mysql-common_8.4.8-1ubuntu22.04_amd64.deb && \
    dpkg -i mysql-community-client-plugins_8.4.8-1ubuntu22.04_amd64.deb && \
    dpkg -i libmysqlclient24_8.4.8-1ubuntu22.04_amd64.deb && \
    dpkg -i mysql-community-client-core_8.4.8-1ubuntu22.04_amd64.deb && \
    dpkg -i mysql-community-client_8.4.8-1ubuntu22.04_amd64.deb && \
    dpkg -i mysql-client_8.4.8-1ubuntu22.04_amd64.deb && \
    dpkg -i mysql-community-server-core_8.4.8-1ubuntu22.04_amd64.deb && \
    dpkg -i mysql-community-server_8.4.8-1ubuntu22.04_amd64.deb || true

# 修复可能存在的依赖问题
RUN apt-get install -f -y

# 确保 MySQL 正确安装
RUN dpkg -l | grep mysql

EXPOSE 3306

# 创建 MySQL 数据目录
RUN mkdir -p /var/lib/mysql /var/run/mysqld && \
    chown -R mysql:mysql /var/lib/mysql /var/run/mysqld

CMD ["mysqld", "--user=mysql"]

1.3 运行容器

bash 复制代码
# 4. 构建镜像
root@docker1:/data/docker-images/mysql# docker build -t mysql:v1 .

# 5. 运行容器
root@docker1:/data/docker-images/mysql# docker run -itd --name mysql1 -p 3306:3306 mysql:v1 
root@docker1:/data/docker-images/mysql# docker ps
CONTAINER ID   IMAGE      COMMAND                 CREATED         STATUS         PORTS                                       NAMES
65e5ceea89c8   mysql:v1   "mysqld --user=mysql"   6 seconds ago   Up 5 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp   mysql1

# 6. 进入容器,查看mysql版本
root@docker1:/data/docker-images/mysql# docker exec -it mysql1 /bin/bash
root@65e5ceea89c8:/mysql-install# mysql -uroot -p'qing@123'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.4.8 MySQL Community Server - GPL

Copyright (c) 2000, 2026, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

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

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.4.8     |
+-----------+

二、基于centos镜像构建mysql镜像

MySQL官网:https://dev.mysql.com/downloads/mysql/

选择对应自己系统版本的tar包

2.1 前置环境准备

bash 复制代码
#前置环境准备
[root@docker ~]# docker pull centos:7   #拉取基础镜像
[root@docker ~]# mkdir -p /data/docker-images/mysql  #准备mysql镜像目录
[root@docker ~]# cd /data/docker-images/mysql  
[root@docker mysql]# ls   #下载tar包到该目录
mysql-8.4.8-linux-glibc2.17-x86_64.tar.xz

2.2 编写dockerfile

bash 复制代码
# 编写dockerfile
[root@docker mysql]# vim Dockerfile 
# 1. 基础镜像
FROM centos:7

# 2. 更换成阿里源
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && \
    yum clean all && \
    yum makecache

# 安装相关依赖
RUN yum install -y libaio-devel numactl-devel perl xz

# 3. 创建 mysql 系统用户,创建 mysql 的安装目录和数据存放目录
RUN useradd -r -M -s /sbin/nologin mysql && mkdir -p /mysql/install && mkdir /mysql/data

# 4. 复制 mysql tar 包并解压
COPY mysql-8.4.8-linux-glibc2.17-x86_64.tar.xz /tmp/
RUN tar -xf /tmp/mysql-8.4.8-linux-glibc2.17-x86_64.tar.xz -C /mysql/install --strip-components=1

# 5. 创建相关项目并授权
RUN mkdir -p /var/lib/mysql /var/log/mysql /etc/my.cnf.d && \
    chown -R mysql:mysql /mysql && chmod 755 /mysql && \
    chown -R mysql:mysql /var/lib/mysql && chmod 755 /var/lib/mysql && \
    chown -R mysql:mysql /var/log/mysql && chmod 755 /var/log/mysql

# 6. 设置 mysql 配置文件
RUN echo '[mysqld]' > /etc/my.cnf && \
    echo 'user=mysql' >> /etc/my.cnf && \
    echo 'basedir=/mysql/install' >> /etc/my.cnf && \
    echo 'datadir=/mysql/data' >> /etc/my.cnf && \
    echo 'socket=/var/lib/mysql/mysql.sock' >> /etc/my.cnf && \
    echo 'port=3306' >> /etc/my.cnf && \
    echo 'log-error=/var/log/mysql/mysqld.log' >> /etc/my.cnf && \
    echo 'pid-file=/var/run/mysqld/mysqld.pid' >> /etc/my.cnf && \
    echo '' >> /etc/my.cnf && \
    echo '[client]' >> /etc/my.cnf && \
    echo 'socket=/var/lib/mysql/mysql.sock' >> /etc/my.cnf

# 7. 创建 pid 目录并设置权限
RUN mkdir -p /var/run/mysqld && \
    chown -R mysql:mysql /var/run/mysqld && \
    chmod 755 /var/run/mysqld

# 8. 拷贝脚本,暴露端口,做持久化
COPY start-mysql.sh /usr/local/
RUN chmod +x /usr/local/start-mysql.sh
EXPOSE 3306
VOLUME ["/mysql/data"]
WORKDIR /mysql/install
CMD ["/usr/local/start-mysql.sh"]

2.3 编写启动脚本

bash 复制代码
# 编写启动脚本
[root@docker mysql]# cat start-mysql.sh 
#!/bin/bash
set -e

# 设置客户端参数,指定socket路径
export MYSQL_UNIX_PORT=/var/lib/mysql/mysql.sock

# 检查数据目录是否已初始化(避免重复初始化)
if [ ! -f /mysql/data/ibdata1 ]; then
    echo "Initializing MySQL data directory..."
    
    # 初始化MySQL,生成临时密码
    /mysql/install/bin/mysqld --initialize --user=mysql --datadir=/mysql/data --basedir=/mysql/install
    
    echo "Starting MySQL temporarily to set root password..."
    
    # 启动MySQL服务(临时)- 指定socket路径
    /mysql/install/bin/mysqld_safe --user=mysql --socket=/var/lib/mysql/mysql.sock &
    
    # 等待MySQL启动
    echo "Waiting for MySQL to start..."
    sleep 15
    
    # 提取临时密码 - 从配置的日志位置读取
    LOG_FILE="/var/log/mysql/mysqld.log"
    if [ -f "$LOG_FILE" ]; then
        echo "Reading temporary password from $LOG_FILE"
        # 显示日志内容的前几行用于调试
        echo "Log file content (first 20 lines):"
        head -20 "$LOG_FILE"
        
        # 提取临时密码
        TEMP_PASS=$(grep 'temporary password' "$LOG_FILE" | awk '{print $NF}')
        if [ -z "$TEMP_PASS" ]; then
            echo "Error: Could not find temporary password in log file"
            echo "Full log file content:"
            cat "$LOG_FILE"
            exit 1
        fi
        echo "Temporary password found: $TEMP_PASS"
    else
        echo "Error: Cannot find log file at $LOG_FILE"
        # 尝试在其他位置查找
        echo "Searching for log files..."
        find / -name "*.log" -type f 2>/dev/null | head -10
        exit 1
    fi
    
    # 等待MySQL完全启动
    echo "Waiting for MySQL to be ready..."
    sleep 10
    
    # 测试连接
    echo "Testing connection to MySQL..."
    for i in {1..5}; do
        if /mysql/install/bin/mysql -uroot -p"$TEMP_PASS" --connect-expired-password --socket=/var/lib/mysql/mysql.sock -e "SELECT 1" 2>/dev/null; then
            echo "Connection successful!"
            break
        else
            echo "Connection attempt $i failed, waiting..."
            sleep 3
        fi
    done
    
    # 修改root密码
    echo "Setting new root password..."
    /mysql/install/bin/mysql -uroot -p"$TEMP_PASS" --connect-expired-password --socket=/var/lib/mysql/mysql.sock <<EOF
ALTER USER 'root'@'localhost' IDENTIFIED BY 'qing@123';
FLUSH PRIVILEGES;
EOF
    
    # 允许远程访问
    echo "Creating remote root user..."
    /mysql/install/bin/mysql -uroot -p'qing@123' --socket=/var/lib/mysql/mysql.sock <<EOF
CREATE USER IF NOT EXISTS 'root'@'%' IDENTIFIED BY 'qing@123';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EOF
    
    # 停止临时MySQL进程
    echo "Stopping temporary MySQL instance..."
    /mysql/install/bin/mysqladmin -uroot -p'qing@123' --socket=/var/lib/mysql/mysql.sock shutdown
    sleep 5
fi

echo "Starting MySQL in foreground..."
# 以前台方式启动MySQL
exec /mysql/install/bin/mysqld_safe --user=mysql --socket=/var/lib/mysql/mysql.sock

2.4 运行容器

bash 复制代码
[root@docker mysql]# docker build -t mysql8.4:v1 .  #构建镜像
[root@docker mysql]# docker run -itd --name mysql1 -p 3306:3306 mysql8.4:v1
[root@docker mysql]# docker exec -it mysql1 /bin/bash  #进入容器
[root@bdbc575eb3a1 install]# bin/mysql -uroot -p'qing@123'   #连接mysql
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.4.8 MySQL Community Server - GPL

Copyright (c) 2000, 2026, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

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

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.4.8     |
+-----------+

mysql> exit
Bye
[root@bdbc575eb3a1 install]# read escape sequence

# 直接通过宿主机也可以连接容器内的mysql
[root@docker mysql]# /usr/local/mysql/bin/mysql -h 127.0.0.1 -P 3306 -uroot -p'qing@123'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.4.8 MySQL Community Server - GPL

Copyright (c) 2000, 2026, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

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

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.4.8     |
+-----------+

注:

文中若有疏漏,欢迎大家指正赐教。

本文为100%原创,转载请务必标注原创作者,尊重劳动成果。

求赞、求关注、求评论!你的支持是我更新的最大动力,评论区等你~

相关推荐
ruanyongjing2 小时前
Navicat for MySQL下载安装教程
数据库·mysql
Y001112362 小时前
Day7-MySQL-约束
数据库·sql·mysql
q***75182 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
泯仲3 小时前
从零起步学习MySQL || 第十五章:MySQL 可重复读隔离级别:它是如何工作的?是否完全解决幻读?
android·学习·mysql
代码AC不AC3 小时前
在 Ubuntu 环境下安装 MySQL
mysql·ubuntu·安装配置
maqiang_7203 小时前
为什么centos+vmware虚机 用NAT 模式总连不上外网
linux·运维·centos
草莓熊Lotso3 小时前
MySQL CRUD 核心指南:查询、插入、更新、删除全实战
android·开发语言·数据库·c++·人工智能·mysql
轩情吖3 小时前
MySQL之表的约束
android·数据库·c++·后端·mysql·开发·约束
Yupureki3 小时前
《MySQL数据库基础》4. 数据类型
c语言·开发语言·数据结构·数据库·c++·mysql