Docker部署Django的Shell脚本中执行MySQL命令失败如何解决
Shell脚本启动Django关联MariaDB报错解决方案
根因说明
- 容器名不匹配:
docker run命令指定容器名为db_name,但docker exec操作时误用了不存在的容器名container_name,无法找到目标容器。 - MySQL服务未就绪:MariaDB容器启动后,内部数据库服务需要3-10秒完成初始化,脚本无等待逻辑直接执行后续操作,此时服务还未启动完成,自然无法连接。手动执行命令时存在天然操作间隔,刚好等到服务初始化完成,所以不会报错。
- 交互参数不适用脚本场景:
docker exec加了-it交互式终端参数,非交互式Shell脚本运行时没有分配终端,会导致执行失败。 - 特殊字符未转义:密码中的
$符号放在双引号内会被Shell识别为变量进行展开,导致实际传入数据库的密码和预期不符。 - 本地访问无端口映射:使用本地MySQL客户端连接容器内数据库时报错115,是因为启动MariaDB容器时没有做3306端口映射,宿主机网络无法直接访问容器内的数据库服务。
调整方案
- 修正容器名,保证
docker run和docker exec操作的是同一个容器 - 增加MySQL服务就绪探测逻辑,等待服务完全启动后再执行建库建用户操作
- 去掉
docker exec的-it参数 - 转义SQL语句中的
$符号,避免Shell变量解析 - 若使用本地客户端连接,启动容器时增加
-p 3306:3306端口映射配置
修改后完整脚本
#!/bin/bash # 启动MariaDB容器,如需本地访问可加上-p 3306:3306 docker run -e MYSQL_ROOT_PASSWORD=root --name db_name -d mariadb # 等待MySQL服务就绪,最多重试30次 retry_cnt=30 until docker exec db_name mysql -u root -proot -e "select 1" > /dev/null 2>&1 || [ $retry_cnt -eq 0 ] do echo "等待MySQL服务启动,剩余重试次数:$retry_cnt" sleep 1 retry_cnt=$((retry_cnt-1)) done if [ $retry_cnt -eq 0 ]; then echo "MySQL服务启动超时,请检查容器状态" exit 1 fi # 执行建库建用户操作,转义密码中的$符号 docker exec db_name mysql -u root -proot -e "create database db_name CHARACTER SET UTF8; CREATE USER invuser@XXX.17.0.3 IDENTIFIED BY 'root1234\$'; GRANT ALL PRIVILEGES ON db_name.* TO invuser@XXX.17.0.3 IDENTIFIED BY 'root1234\$';" echo "Docker image name will be $1" python3 manage.py makemigrations python3 manage.py migrate docker build . -t $1 docker run -d -p 8000:8000 $1
内容的提问来源于stack exchange,提问作者Sameer Atharkar
相关产品推荐
相关产品推荐

