Jenkinsfile调用Docker MySQL镜像时启动失败的问题排查
解决Jenkins Docker Agent中MySQL初始化失败的问题
问题背景
在Windows 11的WSL环境上部署了Docker-in-Docker的Jenkins容器,通过Jenkinsfile创建node:14、mysql:8容器执行测试任务。JavaScript阶段运行正常,但MySQL阶段出现以下异常:
- 执行mysql命令返回错误:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) - 查看mysqld状态发现InnoDB初始化失败,报错无法找到指定路径、无法打开ibdata1文件
- 直接在Jenkins外部运行mysql:8镜像容器并通过
docker exec进入操作时,MySQL可正常运行
原Jenkinsfile
pipeline { agent none stages { stage('Checkout code from github') { agent any steps { git branch: 'main', url: 'https://github.com/OzMashiah/learningjenkins.git' } } stage('Run JavaScript') { agent { docker { image 'node:14' } } steps { script { sh 'ls -l' sh 'node script.js' } } } stage('Run MySQL Query') { agent { docker { image 'mysql:8' } } environment { MYSQL_USER = 'root' MYSQL_DB = 'test_db' MYSQL_ALLOW_EMPTY_PASSWORD = true } steps { script { // Ensure MySQL is initialized before running commands sh 'sleep 15' sh '/usr/sbin/mysqld status' sh ''' mysql -u ${MYSQL_USER} -e "CREATE DATABASE IF NOT EXISTS ${MYSQL_DB};" mysql -u ${MYSQL_USER} ${MYSQL_DB} -e " CREATE TABLE IF NOT EXISTS users ( id INT PRIMARY KEY, name VARCHAR(50) ); INSERT INTO users (id, name) VALUES (1, 'John Doe'); INSERT INTO users (id, name) VALUES (2, 'Jane Doe'); " ''' sh ''' mysql -u ${MYSQL_USER} ${MYSQL_DB} -e "SELECT * FROM users;" ''' } } } } post { always { // Clean up resources after the build echo 'Cleaning up resources...' } } }
错误日志
MySQL连接错误
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
mysqld状态日志
+ /usr/sbin/mysqld status 2024-12-12T10:12:15.290153Z 0 [System] [MY-015015] [Server] MySQL Server - start. 2024-12-12T10:12:15.564828Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.4.3) starting as process 46 2024-12-12T10:12:15.600460Z 0 [Warning] [MY-010075] [Server] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 8fd96474-b871-11ef-a35e-0242ac110002. 2024-12-12T10:12:15.621615Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. 2024-12-12T10:12:15.639907Z 1 [ERROR] [MY-012592] [InnoDB] Operating system error number 2 in a file operation. 2024-12-12T10:12:15.639958Z 1 [ERROR] [MY-012593] [InnoDB] The error means the system cannot find the path specified. 2024-12-12T10:12:15.639972Z 1 [ERROR] [MY-012594] [InnoDB] If you are installing InnoDB, remember that you must create directories yourself, InnoDB does not create them. 2024-12-12T10:12:15.639980Z 1 [ERROR] [MY-012646] [InnoDB] File ./ibdata1: 'open' returned OS error 71. Cannot continue operation 2024-12-12T10:12:15.640283Z 1 [ERROR] [MY-012981] [InnoDB] Cannot continue operation. script returned exit code 3
问题原因
Jenkins的Docker Agent默认会覆盖容器的ENTRYPOINT/CMD,直接以shell模式启动容器。而mysql:8镜像的默认ENTRYPOINT是一个初始化脚本,会自动处理数据目录权限、创建必要路径、启动mysqld服务等流程。当以Jenkins Agent方式运行时,这个初始化流程被跳过,导致:
- mysqld服务未自动启动
- 数据目录(如
/var/lib/mysql、/var/run/mysqld)不存在或权限不足,InnoDB无法创建ibdata1文件
解决方案
方案一:修正MySQL Agent阶段的初始化流程
手动创建必要目录、设置权限、启动mysqld服务,并等待服务就绪后执行SQL命令:
stage('Run MySQL Query') { agent { docker { image 'mysql:8' } } environment { MYSQL_USER = 'root' MYSQL_DB = 'test_db' MYSQL_ALLOW_EMPTY_PASSWORD = true } steps { script { // 创建MySQL所需的目录并设置权限 sh 'mkdir -p /var/lib/mysql /var/run/mysqld' sh 'chown -R mysql:mysql /var/lib/mysql /var/run/mysqld' sh 'chmod 777 /var/run/mysqld' // 后台启动mysqld服务 sh '/usr/sbin/mysqld --daemonize' // 等待MySQL服务就绪(比固定sleep更可靠) sh 'until mysqladmin ping -u ${MYSQL_USER} --silent; do sleep 2; done' // 执行SQL操作 sh ''' mysql -u ${MYSQL_USER} -e "CREATE DATABASE IF NOT EXISTS ${MYSQL_DB};" mysql -u ${MYSQL_USER} ${MYSQL_DB} -e " CREATE TABLE IF NOT EXISTS users ( id INT PRIMARY KEY, name VARCHAR(50) ); INSERT INTO users (id, name) VALUES (1, 'John Doe'); INSERT INTO users (id, name) VALUES (2, 'Jane Doe'); " ''' sh ''' mysql -u ${MYSQL_USER} ${MYSQL_DB} -e "SELECT * FROM users;" ''' } } }
方案二:使用独立MySQL容器(推荐)
避免将MySQL镜像作为Jenkins Agent,而是在Pipeline中启动独立的MySQL容器,通过容器网络访问:
stage('Run MySQL Query') { agent any environment { MYSQL_CONTAINER = 'mysql-test' MYSQL_USER = 'root' MYSQL_DB = 'test_db' MYSQL_ALLOW_EMPTY_PASSWORD = true } steps { script { // 启动独立的MySQL容器 sh "docker run -d --name ${MYSQL_CONTAINER} -e MYSQL_ALLOW_EMPTY_PASSWORD=${MYSQL_ALLOW_EMPTY_PASSWORD} -e MYSQL_DATABASE=${MYSQL_DB} mysql:8" // 等待MySQL服务就绪 sh "until docker exec ${MYSQL_CONTAINER} mysqladmin ping -u ${MYSQL_USER} --silent; do sleep 2; done" // 在容器内执行SQL命令 sh "docker exec ${MYSQL_CONTAINER} mysql -u ${MYSQL_USER} ${MYSQL_DB} -e \" CREATE TABLE IF NOT EXISTS users ( id INT PRIMARY KEY, name VARCHAR(50) ); INSERT INTO users (id, name) VALUES (1, 'John Doe'); INSERT INTO users (id, name) VALUES (2, 'Jane Doe'); SELECT * FROM users; \"" } } post { always { // 清理测试用的MySQL容器 sh "docker stop ${MYSQL_CONTAINER} && docker rm ${MYSQL_CONTAINER}" } } }
补充说明
直接在Jenkins外部运行mysql:8镜像时,Docker会执行默认的ENTRYPOINT脚本,自动完成目录创建、权限配置、服务启动等步骤,因此可以正常运行。而Jenkins Agent模式会跳过这个初始化流程,导致服务无法正常启动。
内容的提问来源于stack exchange,提问作者user28749644
相关产品推荐
相关产品推荐

