GitLab CI/CD配置Django项目连接MySQL数据库失败求助
我正在尝试通过GitLab CI/CD为Django项目配置自动化测试,但始终无法连接到MySQL数据库。当前使用的.gitlab-ci.yml配置如下:
services: - mysql:5.7 variables: MYSQL_DATABASE: "db_name" MYSQL_ROOT_PASSWORD: "dbpass" MYSQL_USER: "username" MYSQL_PASSWORD: "dbpass" stages: - test test: stage: test before_script: - apt update -qy && apt-get install -qqy --no-install-recommends default-mysql-client - mysql --user=$MYSQL_USER --password=$MYSQL_PASSWORD --database=$MYSQL_DATABASE --host=$MYSQL_HOST --execute="SHOW DATABASES; ALTER USER '$MYSQL_USER'@'%' IDENTIFIED WITH mysql_native_password BY '$MYSQL_PASSWORD'" script: - apt update -qy - apt install python3 python3-pip virtualenvwrapper -qy - virtualenv --python=python3 venv/ - source venv/bin/activate - pwd - pip install -r requirement.txt - python manage.py test apps
使用该配置时,出现错误:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
我尝试修改连接方式为TCP协议,将命令改为:mysql --protocol=TCP --user=$MYSQL_USER --password=$MYSQL_PASSWORD --database=$MYSQL_DATABASE --host=$MYSQL_HOST --execute="SHOW DATABASES; ALTER USER '$MYSQL_USER'@'%' IDENTIFIED WITH mysql_native_password BY '$MYSQL_PASSWORD'"
但此时又出现错误:
ERROR 2002 (HY000): Can't connect to MySQL server on 'localhost' (99)
请问该如何正确配置才能解决问题?
这俩错误本质都是没搞对GitLab CI里服务容器的访问规则,还有数据库启动时机的问题,我给你拆解一下修复步骤:
1. 先把MySQL的主机地址设对
在GitLab CI里,你配置的mysql:5.7服务是跑在一个独立的容器里的,它的主机名就是服务名mysql,不是你以为的localhost。所以必须在变量里加上MYSQL_HOST: "mysql",这样所有连接命令才知道该找哪个容器:
variables: MYSQL_DATABASE: "db_name" MYSQL_ROOT_PASSWORD: "dbpass" MYSQL_USER: "username" MYSQL_PASSWORD: "dbpass" MYSQL_HOST: "mysql" # 关键:把主机指向mysql服务容器
2. 等MySQL完全启动再连接
数据库启动需要几秒时间,你刚安装完mysql-client就直接跑连接命令,大概率会碰到服务未就绪的情况。加个循环等待脚本,直到能连上为止:
# 放在安装mysql-client之后 - | until mysql --protocol=TCP --user=root --password=$MYSQL_ROOT_PASSWORD --host=$MYSQL_HOST --execute="SELECT 1"; do echo "等MySQL启动中..." sleep 2 done
3. 修正用户权限配置
你原来的ALTER USER命令可能有问题,比如用户还没创建就去修改,或者权限没给全。换成用root用户先创建用户再授权,更稳妥:
# 替换原来的mysql执行命令 - mysql --protocol=TCP --user=root --password=$MYSQL_ROOT_PASSWORD --host=$MYSQL_HOST --execute="CREATE USER IF NOT EXISTS '$MYSQL_USER'@'%' IDENTIFIED WITH mysql_native_password BY '$MYSQL_PASSWORD'; GRANT ALL PRIVILEGES ON $MYSQL_DATABASE.* TO '$MYSQL_USER'@'%'; FLUSH PRIVILEGES;"
4. 别忘改Django的数据库配置
你的Django项目settings.py里的数据库HOST也要用MYSQL_HOST变量的值,不能写死localhost:
import os DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': os.environ.get('MYSQL_DATABASE'), 'USER': os.environ.get('MYSQL_USER'), 'PASSWORD': os.environ.get('MYSQL_PASSWORD'), 'HOST': os.environ.get('MYSQL_HOST'), # 这里必须是mysql,不是localhost 'PORT': '3306', } }
最后给你个完整的配置示例
我把上面的修改都整合进去了,还加了migrate步骤(测试前得先建表对吧):
services: - mysql:5.7 variables: MYSQL_DATABASE: "db_name" MYSQL_ROOT_PASSWORD: "dbpass" MYSQL_USER: "username" MYSQL_PASSWORD: "dbpass" MYSQL_HOST: "mysql" stages: - test test: stage: test before_script: - apt update -qy && apt-get install -qqy --no-install-recommends default-mysql-client # 等待MySQL服务就绪 - | until mysql --protocol=TCP --user=root --password=$MYSQL_ROOT_PASSWORD --host=$MYSQL_HOST --execute="SELECT 1"; do echo "等MySQL启动中..." sleep 2 done # 创建用户并授权 - mysql --protocol=TCP --user=root --password=$MYSQL_ROOT_PASSWORD --host=$MYSQL_HOST --execute="CREATE USER IF NOT EXISTS '$MYSQL_USER'@'%' IDENTIFIED WITH mysql_native_password BY '$MYSQL_PASSWORD'; GRANT ALL PRIVILEGES ON $MYSQL_DATABASE.* TO '$MYSQL_USER'@'%'; FLUSH PRIVILEGES;" script: - apt update -qy - apt install python3 python3-pip virtualenv -qy - virtualenv --python=python3 venv/ - source venv/bin/activate - pip install -r requirement.txt - python manage.py migrate # 测试前必须执行迁移创建表 - python manage.py test apps
这样应该就能解决连接问题了,你试试!
内容的提问来源于stack exchange,提问作者Jekson

