x86 平台使用 Docker buildx 构建 MySQL Arm64 镜像
·
x86 平台使用 Docker buildx 构建 MySQL Arm64 镜像
一、基于源码构建 MySQL 5.7.44 Arm64 镜像
创建一个shell
#!/bin/bash
set -e # 添加错误处理
imageTag=mysql-openeuler:5.7.44
# 2. 设置环境变量
export DOCKER_BUILDKIT=1
export DOCKER_CLI_EXPERIMENTAL=enabled
# 3. 清理和设置构建器
echo "设置 Docker Buildx 构建器..."
rm -rf /tmp/buildkitd.toml
cat > /tmp/buildkitd.toml << 'EOF'
debug = true
root = "/var/lib/buildkit"
[registry."docker.io"]
mirrors = [
"https://e2zfh98i.mirror.aliyuncs.com",
"https://mirror.baidubce.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker-cf.registry.cyou",
"https://dockercf.jsdelivr.fyi",
"https://docker.jsdelivr.fyi",
"https://dockertest.jsdelivr.fyi",
"https://dockerproxy.com",
"https://docker.m.daocloud.io",
"https://docker.nju.edu.cn",
"https://docker.mirrors.sjtug.sjtu.edu.cn",
"https://mirror.iscas.ac.cn",
"https://docker.rainbond.cc",
"https://do.nark.eu.org",
"https://dc.j8.work",
"https://dockerproxy.com",
"https://gst6rzl9.mirror.aliyuncs.com",
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"http://mirrors.ustc.edu.cn/",
"https://mirrors.tuna.tsinghua.edu.cn/",
"http://mirrors.sohu.com/"
]
EOF
# 清理现有构建器
docker buildx rm mybuilder 2>/dev/null || true
# 创建构建器
if ! docker buildx create \
--name mybuilder \
--driver docker-container \
--driver-opt "image=moby/buildkit:master" \
--platform linux/arm64 \
--config /tmp/buildkitd.toml \
--use; then
echo "错误:创建构建器失败"
exit 1
fi
# 启动构建器
docker buildx inspect --bootstrap
# 4. 创建正确的 Dockerfile
echo "创建 Dockerfile..."
cat > Dockerfile << 'EOF'
# 使用华为云镜像源
FROM openeuler/openeuler:20.03-lts-sp4 AS builder
# 设置参数
ARG MYSQL_VERSION=5.7.44
ARG TARGETARCH=arm64
ARG MYSQL_HOME=/usr/local/mysql
ARG MYSQL_DATA_DIR=/var/lib/mysql
# 安装编译和构建依赖
RUN dnf install -y \
tar \
xz \
gzip \
bzip2 \
wget \
curl \
cmake \
gcc \
gcc-c++ \
gcc-gfortran \
make \
openssl openssl-devel \
ncurses-devel \
libaio-devel \
openssl-devel \
numactl-devel \
zlib-devel \
bison \
flex \
libedit-devel \
readline-devel \
pkg-config \
libtirpc \
libtirpc-devel \
perl \
perl-Data-Dumper \
perl-Env \
perl-ExtUtils-MakeMaker \
perl-ExtUtils-Embed \
&& dnf clean all
# 为 RPC 创建必要的符号链接
RUN ln -sf /usr/include/tirpc /usr/include/rpc 2>/dev/null || true \
&& ln -sf /usr/include/tirpc/rpc /usr/include/rpc 2>/dev/null || true
# 下载 MySQL 5.7.44 源码
RUN wget https://downloads.mysql.com/archives/get/p/23/file/mysql-boost-${MYSQL_VERSION}.tar.gz \
&& tar -xzf mysql-boost-${MYSQL_VERSION}.tar.gz \
&& rm -f mysql-boost-${MYSQL_VERSION}.tar.gz
# 编译 MySQL
WORKDIR /mysql-${MYSQL_VERSION}
RUN sed -i '/INCLUDE(cmake\/abi_check.cmake)/d' CMakeLists.txt
# 可选:添加调试信息查看修改结果
RUN echo "=== 查看 CMakeLists.txt 修改结果(包含 abi_check 的行)===" \
&& grep -n "abi_check" CMakeLists.txt || echo "未找到 abi_check 相关行"
RUN cmake . \
-DCMAKE_INSTALL_PREFIX=${MYSQL_HOME} \
-DMYSQL_DATADIR=${MYSQL_DATA_DIR} \
-DSYSCONFDIR=/etc \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_READLINE=1 \
-DWITH_SSL=system \
-DWITH_ZLIB=system \
-DWITH_LIBWRAP=0 \
-DENABLED_LOCAL_INFILE=1 \
-DMYSQL_UNIX_ADDR=/tmp/mysql.sock \
-DEXTRA_CHARSETS=all \
-DDEFAULT_CHARSET=utf8mb4 \
-DDEFAULT_COLLATION=utf8mb4_general_ci \
-DWITH_EMBEDDED_SERVER=1 \
-DENABLE_DOWNLOADS=1 \
-DDOWNLOAD_BOOST=1 \
-DWITH_BOOST=/mysql-${MYSQL_VERSION}/boost \
-DBUILD_CONFIG=mysql_release \
-DWITH_NUMA=ON \
-DWITH_DEBUG=OFF \
-DWITH_RAPID=OFF
RUN make -j$(nproc) && make install
# 第二阶段:最终镜像
FROM openeuler/openeuler:20.03-lts-sp4
# 设置参数
ARG MYSQL_VERSION=5.7.44
ARG MYSQL_HOME=/usr/local/mysql
ARG MYSQL_DATA_DIR=/var/lib/mysql
ARG MYSQL_LOG_DIR=/var/log/mysql
ENV PATH=${MYSQL_HOME}/bin:${PATH}
ENV TZ=Asia/Shanghai
ENV LANG=en_US.utf8
# 设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装运行时依赖
RUN dnf install -y \
tar \
xz \
perl \
perl-Data-Dumper \
libaio \
numactl shadow-utils \
ncurses-compat-libs \
procps-ng \
hostname \
&& dnf clean all
# 创建 MySQL 用户和组
RUN groupadd -r mysql \
&& useradd -r -g mysql -s /bin/false -d ${MYSQL_DATA_DIR} mysql \
&& mkdir -p ${MYSQL_HOME} ${MYSQL_DATA_DIR} ${MYSQL_LOG_DIR} \
&& chown -R mysql:mysql ${MYSQL_HOME} ${MYSQL_DATA_DIR} ${MYSQL_LOG_DIR}
# 从构建阶段复制 MySQL
COPY --from=builder ${MYSQL_HOME} ${MYSQL_HOME}
# 复制配置文件
COPY my.cnf /etc/my.cnf
COPY docker-entrypoint.sh /usr/local/bin/
# 设置权限
RUN chmod +x /usr/local/bin/docker-entrypoint.sh \
&& mkdir -p /var/run/mysql \
&& chown -R mysql:mysql /var/run/mysql \
&& ln -sf ${MYSQL_HOME}/bin/* /usr/local/bin/ 2>/dev/null || true
# 验证架构
RUN echo "Building for architecture: $(uname -m)"
# 暴露端口
EXPOSE 3306
EXPOSE 33060
# 设置数据卷
VOLUME ["${MYSQL_DATA_DIR}", "${MYSQL_LOG_DIR}"]
# 设置工作目录
WORKDIR ${MYSQL_HOME}
# 设置入口点
ENTRYPOINT ["docker-entrypoint.sh"]
# 默认命令
CMD ["mysqld"]
EOF
echo "创建my.cnf..."
cat > my.cnf << 'EOF'
[mysqld]
user=mysql
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/error.log
pid-file=/var/run/mysql/mysql.pid
# 字符集设置
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
init-connect='SET NAMES utf8mb4'
# 连接设置
max_connections=1000
max_connect_errors=1000
connect_timeout=60
wait_timeout=28800
interactive_timeout=28800
# 缓冲池设置
innodb_buffer_pool_size=256M
innodb_log_file_size=128M
innodb_log_buffer_size=16M
innodb_flush_log_at_trx_commit=1
innodb_lock_wait_timeout=50
# 查询缓存设置
query_cache_type=1
query_cache_size=32M
query_cache_limit=1M
# 二进制日志
server-id=1
log-bin=mysql-bin
expire_logs_days=7
binlog_format=ROW
# 慢查询日志
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
log_queries_not_using_indexes=1
# 安全设置
skip-name-resolve
local-infile=0
symbolic-links=0
[client]
default-character-set=utf8mb4
socket=/var/lib/mysql/mysql.sock
[mysql]
default-character-set=utf8mb4
EOF
# 5. 创建修复后的启动脚本
echo "创建启动脚本..."
cat > docker-entrypoint.sh << 'EOF'
#!/bin/bash
set -e
# 设置环境变量
MYSQL_HOME=${MYSQL_HOME:-/usr/local/mysql}
MYSQL_DATA_DIR=${MYSQL_DATA_DIR:-/var/lib/mysql}
MYSQL_LOG_DIR=${MYSQL_LOG_DIR:-/var/log/mysql}
# 设置权限
chown -R mysql:mysql ${MYSQL_DATA_DIR} ${MYSQL_LOG_DIR} /var/run/mysql
# 如果数据目录为空,则初始化数据库
if [ ! -d "${MYSQL_DATA_DIR}/mysql" ]; then
echo "初始化 MySQL 数据库..."
# 初始化数据库
${MYSQL_HOME}/bin/mysqld \
--initialize-insecure \
--user=mysql \
--datadir=${MYSQL_DATA_DIR} \
--basedir=${MYSQL_HOME}
echo "MySQL 初始化完成"
# 启动临时服务来设置 root 密码
${MYSQL_HOME}/bin/mysqld \
--user=mysql \
--datadir=${MYSQL_DATA_DIR} \
--skip-networking \
--socket=/tmp/mysql.sock &
pid="$!"
# 等待 MySQL 启动
for i in {30..0}; do
if ${MYSQL_HOME}/bin/mysqladmin ping --socket=/tmp/mysql.sock >/dev/null 2>&1; then
break
fi
echo '等待 MySQL 启动...'
sleep 1
done
if [ "$i" = 0 ]; then
echo >&2 'MySQL 启动失败'
exit 1
fi
# 设置 root 密码
if [ -n "${MYSQL_ROOT_PASSWORD}" ]; then
mysql --socket=/tmp/mysql.sock -u root -e \
"ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';"
else
mysql --socket=/tmp/mysql.sock -u root -e \
"ALTER USER 'root'@'localhost' IDENTIFIED BY '';"
fi
# 创建远程 root 用户
if [ -n "${MYSQL_ROOT_HOST}" ] && [ "${MYSQL_ROOT_HOST}" != "localhost" ]; then
mysql --socket=/tmp/mysql.sock -u root -p"${MYSQL_ROOT_PASSWORD}" -e \
"CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" || true
mysql --socket=/tmp/mysql.sock -u root -p"${MYSQL_ROOT_PASSWORD}" -e \
"GRANT ALL PRIVILEGES ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION;" || true
fi
# 停止临时服务
if ! kill -s TERM "$pid" || ! wait "$pid"; then
echo >&2 'MySQL 初始化进程失败'
exit 1
fi
echo "MySQL 已成功初始化"
fi
# 在后台启动 MySQL
echo "启动 MySQL..."
"$@" &
# 获取 MySQL 进程 ID
MYSQL_PID=$!
# 等待 MySQL 启动并开始生成日志
sleep 2
# 在前台运行 tail 查看日志
echo "开始输出 MySQL 日志..."
tail -f /var/log/mysql/error.log &
# 捕获退出信号
trap "echo '收到停止信号,停止 MySQL...'; kill $MYSQL_PID" TERM INT
# 等待 MySQL 进程
wait $MYSQL_PID
EOF
chmod +x docker-entrypoint.sh
# 6. 构建镜像(添加错误处理)
echo "开始构建镜像..."
if ! docker buildx build \
--platform linux/arm64 \
-t ${imageTag} \
--load --progress=plain \
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
.; then
echo "错误:镜像构建失败"
exit 1
fi
echo "镜像构建成功: ${imageTag}"
二、基于 glibc2 包构建 MySQL 8.0.44 Arm64 镜像
创建一个shell
#!/bin/bash
set -e # 添加错误处理
# 1. 下载 MySQL(添加错误检查)
if [ ! -f "mysql-8.0.44-linux-glibc2.28-aarch64.tar.xz" ]; then
echo "下载 MySQL 安装包..."
if ! wget -O "mysql-8.0.44-linux-glibc2.28-aarch64.tar.xz" "https://cdn.mysql.com/archives/mysql-8.0/mysql-8.0.44-linux-glibc2.28-aarch64.tar.xz"; then
echo "错误:MySQL 安装包下载失败"
exit 1
fi
fi
imageTag=mysql-openeuler:8.0.44
# 2. 设置环境变量
export DOCKER_BUILDKIT=1
export DOCKER_CLI_EXPERIMENTAL=enabled
# 3. 清理和设置构建器
echo "设置 Docker Buildx 构建器..."
rm -rf /tmp/buildkitd.toml
cat > /tmp/buildkitd.toml << 'EOF'
debug = true
root = "/var/lib/buildkit"
[registry."docker.io"]
mirrors = [
"https://e2zfh98i.mirror.aliyuncs.com",
"https://mirror.baidubce.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker-cf.registry.cyou",
"https://dockercf.jsdelivr.fyi",
"https://docker.jsdelivr.fyi",
"https://dockertest.jsdelivr.fyi",
"https://dockerproxy.com",
"https://docker.m.daocloud.io",
"https://docker.nju.edu.cn",
"https://docker.mirrors.sjtug.sjtu.edu.cn",
"https://mirror.iscas.ac.cn",
"https://docker.rainbond.cc",
"https://do.nark.eu.org",
"https://dc.j8.work",
"https://dockerproxy.com",
"https://gst6rzl9.mirror.aliyuncs.com",
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"http://mirrors.ustc.edu.cn/",
"https://mirrors.tuna.tsinghua.edu.cn/",
"http://mirrors.sohu.com/"
]
EOF
# 清理现有构建器
docker buildx rm mybuilder 2>/dev/null || true
# 创建构建器
if ! docker buildx create \
--name mybuilder \
--driver docker-container \
--driver-opt "image=moby/buildkit:master" \
--platform linux/arm64 \
--config /tmp/buildkitd.toml \
--use; then
echo "错误:创建构建器失败"
exit 1
fi
# 启动构建器
docker buildx inspect --bootstrap
# 4. 创建正确的 Dockerfile
echo "创建 Dockerfile..."
cat > Dockerfile << 'EOF'
# 使用 ARM64 基础镜像
FROM openeuler/openeuler:24.03-lts-sp3
# 设置参数
ARG TARGETARCH
ARG TARGETPLATFORM
RUN echo "目标架构: $TARGETARCH, 目标平台: $TARGETPLATFORM"
# 设置环境变量
ENV MYSQL_VERSION=8.0.44
ENV MYSQL_HOME=/usr/local/mysql
ENV MYSQL_DATA_DIR=/var/lib/mysql
ENV MYSQL_LOG_DIR=/var/log/mysql
ENV PATH=$MYSQL_HOME/bin:$PATH
ENV TZ=Asia/Shanghai
# 安装依赖
RUN dnf install -y \
perl \
perl-Data-Dumper \
libaio \
numactl \
ncurses-compat-libs \
shadow-utils \
procps-ng \
tar \
xz \
gzip \
wget \
hostname \
&& dnf clean all
# 确保 bash 是默认 shell
RUN ln -sf /bin/bash /bin/sh
# 设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 复制 MySQL 安装包
COPY mysql-8.0.44-linux-glibc2.28-aarch64.tar.xz /tmp/
# 安装 MySQL
RUN tar -xf /tmp/mysql-*.tar.xz -C /usr/local/ && \
mv /usr/local/mysql-${MYSQL_VERSION}-linux-glibc2.28-aarch64 ${MYSQL_HOME} && \
rm -f /tmp/mysql-*.tar.xz && \
ln -sf ${MYSQL_HOME}/bin/* /usr/local/bin/
# 创建用户和目录
RUN groupadd -r mysql && \
useradd -r -g mysql -s /bin/false mysql && \
mkdir -p ${MYSQL_DATA_DIR} ${MYSQL_LOG_DIR} /var/run/mysql && \
chown -R mysql:mysql ${MYSQL_DATA_DIR} ${MYSQL_LOG_DIR} /var/run/mysql
# 创建配置文件
RUN echo "[mysqld]" > /etc/my.cnf \
&& echo "datadir=${MYSQL_DATA_DIR}" >> /etc/my.cnf \
&& echo "socket=/var/lib/mysql/mysql.sock" >> /etc/my.cnf \
&& echo "log-error=${MYSQL_LOG_DIR}/error.log" >> /etc/my.cnf \
&& echo "pid-file=/var/run/mysql/mysql.pid" >> /etc/my.cnf \
&& echo "user=mysql" >> /etc/my.cnf \
&& echo "default_authentication_plugin=mysql_native_password" >> /etc/my.cnf \
&& echo "[client]" >> /etc/my.cnf \
&& echo "socket=/var/lib/mysql/mysql.sock" >> /etc/my.cnf
# 复制启动脚本
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
# 暴露端口
EXPOSE 3306 33060
# 数据卷
VOLUME ["${MYSQL_DATA_DIR}", "${MYSQL_LOG_DIR}"]
# 设置工作目录
WORKDIR ${MYSQL_HOME}
# 正确的 ENTRYPOINT 和 CMD
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["mysqld"]
EOF
# 5. 创建修复后的启动脚本
echo "创建启动脚本..."
cat > docker-entrypoint.sh << 'EOF'
#!/bin/bash
set -e
# 如果数据目录为空,则初始化数据库
if [ -z "$(ls -A ${MYSQL_DATA_DIR})" ]; then
echo "初始化 MySQL 数据库..."
# 初始化数据库
mysqld --initialize-insecure \
--user=mysql \
--datadir=${MYSQL_DATA_DIR} \
--basedir=${MYSQL_HOME}
# 启动临时服务来设置 root 密码
mysqld --user=mysql --datadir=${MYSQL_DATA_DIR} --skip-networking &
pid="$!"
# 等待 MySQL 启动
for i in {30..0}; do
if mysqladmin ping --silent; then
break
fi
echo '等待 MySQL 启动...'
sleep 1
done
if [ "$i" = 0 ]; then
echo >&2 'MySQL 启动失败'
exit 1
fi
# 设置 root 密码
if [ -n "${MYSQL_ROOT_PASSWORD}" ]; then
mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';"
else
mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '';"
fi
# 创建远程 root 用户
if [ -n "${MYSQL_ROOT_HOST}" ]; then
mysql -u root -p${MYSQL_ROOT_PASSWORD:-''} -e \
"CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';"
mysql -u root -p${MYSQL_ROOT_PASSWORD:-''} -e \
"GRANT ALL PRIVILEGES ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION;"
fi
# 停止临时服务
if ! kill -s TERM "$pid" || ! wait "$pid"; then
echo >&2 'MySQL 初始化进程失败'
exit 1
fi
echo "MySQL 已成功初始化,等待启动"
fi
# 设置权限
chown -R mysql:mysql ${MYSQL_DATA_DIR} ${MYSQL_LOG_DIR}
# 在后台启动 MySQL
echo "启动 MySQL..."
"$@" &
# 获取 MySQL 进程 ID
MYSQL_PID=$!
# 等待 MySQL 启动并开始生成日志
sleep 2
# 在前台运行 tail 查看日志
echo "开始输出 MySQL 日志..."
tail -f /var/log/mysql/error.log &
# 捕获退出信号
trap "echo '收到停止信号,停止 MySQL...'; kill $MYSQL_PID" TERM INT
# 等待 MySQL 进程
wait $MYSQL_PID
EOF
chmod +x docker-entrypoint.sh
# 6. 构建镜像(添加错误处理)
echo "开始构建镜像..."
if ! docker buildx build \
--platform linux/arm64 \
-t ${imageTag} \
--load \
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
.; then
echo "错误:镜像构建失败"
exit 1
fi
echo "镜像构建成功: ${imageTag}"
三、运行容器
# 基本运行
docker run -d \
--name mysql-server \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql-openeuler:8.0.44
# 带数据持久化
docker run -d \
--name mysql-server \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /path/to/mysql/data:/var/lib/mysql \
-v /path/to/mysql/logs:/var/log/mysql \
mysql-openeuler:8.0.44
# 自定义配置
docker run -d \
--name mysql-server \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_ROOT_HOST=% \
-v /my/custom/my.cnf:/etc/my.cnf \
mysql-openeuler:8.0.44
四、环境变量配置
- MYSQL_ROOT_PASSWORD:root用户密码(必须)
- MYSQL_ROOT_HOST:root远程访问主机,默认为localhost
- TZ:时区设置,默认为 Asia/Shanghai
- LANG:语言设置,需要设置为 zh_CN.UTF-8 容器才支持中文
更多推荐


所有评论(0)