首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Docker中运行MySQL/MariaDB时的django.db.utils.OperationalError :在“读取初始通信包”时失去与MySQL服务器的连接

问在Docker中运行MySQL/MariaDB时的django.db.utils.OperationalError :在“读取初始通信包”时失去与MySQL服务器的连接
EN

Stack Overflow用户
提问于 2022-07-19 19:24:47
回答 2查看 120关注 0票数 0

在Docker容器中运行MySQL/MariaDB:

代码语言:javascript
复制
docker run -p 3306:3306 --name $(DATABASE_NAME) -v /tmp/mysql:/var/lib/mysql -e MYSQL_DATABASE=$(DATABASE_NAME) -e MYSQL_USER=$(DATABASE_USER) -e MYSQL_ROOT_PASSWORD=$(DATABASE_PASSWORD) -d mariadb:latest > /dev/null

然后在本地运行Django版本4,使用:

代码语言:javascript
复制
manage.py runserver 127.0.0.1:8000

错误

代码语言:javascript
复制
django.db.utils.OperationalError: (2013, "Lost connection to MySQL server at 'reading initial communication packet', system error: 2")

我可以使用MySQL工作台和命令成功地连接到数据库:

代码语言:javascript
复制
mysql -h 127.0.0.1 -P 3306 -u root -p <database>

我将从Makefile启动Django和MySQL/MariaDB Docker容器。

Makefile

代码语言:javascript
复制
SHELL := /bin/bash

.PHONY: dj-start-local
dj-start-local: start-mysql
    PYTHONPATH=. django_project/src/manage.py runserver 127.0.0.1:8000

.PHONY: start-mysql
start-mysql:
    docker run -p 3306:3306 --name $(DATABASE_NAME) \
        -v /tmp/mysql:/var/lib/mysql \
        -e MYSQL_DATABASE=$(DATABASE_NAME) \
        -e MYSQL_USER=$(DATABASE_USER) \
        -e MYSQL_ROOT_PASSWORD=$(DATABASE_PASSWORD) \
        -d mariadb:latest > /dev/null
EN

回答 2

Stack Overflow用户

发布于 2022-07-19 23:10:20

在容器中使用healthcheck.sh。使用MARIADB_MYSQL_LOCALHOST_USER=1创建脚本可用于访问数据库的mysql@localhost用户,

无论何时,健康检查都要等到完全启动。

Makefile:

代码语言:javascript
复制
.PHONY: start-mariadb
start-mariadb:
    docker run -p 3306:3306 --name $(DATABASE_NAME) \
        -e MARIADB_DATABASE=$(DATABASE_NAME) \
        -e MARIADB_USER=$(DATABASE_USER) \
        -e MARIADB_PASSWORD=$(DATABASE_PASSWORD) \
        -e MARIADB_ROOT_PASSWORD=$(DATABASE_PASSWORD) \
        -e MARIADB_MYSQL_LOCALHOST_USER=1 \
        -v /tmp/mysql:/var/lib/mysql \
        -d mariadb:latest
    while ! docker exec $(DATABASE_NAME) healthcheck.sh --su=mysql --connect --innodb_initialized; do sleep 1; done
    docker exec --user mysql $(DATABASE_NAME) mariadb -e 'select "hello world"'

测试运行:

代码语言:javascript
复制
$ make start-mariadb 
docker run -p 3306:3306 --name dd \
    -e MARIADB_DATABASE=dd \
    -e MARIADB_USER=dd \
    -e MARIADB_PASSWORD=dd \
    -e MARIADB_ROOT_PASSWORD=dd \
    -e MARIADB_MYSQL_LOCALHOST_USER=1 \
    -d mariadb:latest
53066fffa293ed061743024e387bd7fb6f1c664efd603c7a657ba88e307be308
while ! docker exec dd healthcheck.sh --su=mysql --connect --innodb_initialized; do sleep 1; done
healthcheck connect failed
healthcheck connect failed
healthcheck connect failed
healthcheck connect failed
docker exec --user mysql dd mariadb -e 'select "hello world"'
hello world
hello world

注意:添加了MARIADB_PASSWORD,否则将不会创建数据库/用户。

票数 1
EN

Stack Overflow用户

发布于 2022-07-19 19:24:47

这个问题可能是由于争用条件造成的,Django试图在数据库准备好之前连接到数据库。试着在启动码头集装箱后等待几秒钟。

简单解

Makefile

代码语言:javascript
复制
.PHONY: start-mysql
start-mysql:
    docker run -p 3306:3306 --name $(DATABASE_NAME) \
        -v /tmp/mysql:/var/lib/mysql \
        -e MYSQL_DATABASE=$(DATABASE_NAME) \
        -e MYSQL_USER=$(DATABASE_USER) \
        -e MYSQL_ROOT_PASSWORD=$(DATABASE_PASSWORD) \
        -d mariadb:latest
    sleep 4

使用healthcheck.sh的更好解决方案

在中,他指出MariaDB停靠容器包括一个脚本。

如果您只想检查MariaDB容器是否可以接收连接,则可以在不指定用户的情况下运行healthcheck.sh (避免了授权复杂性)。

下面的Makefile将每秒钟检查一次数据库连接,直到数据库准备就绪。

Makefile (高级版本)

代码语言:javascript
复制
.PHONY: mysql-start
mysql-start: mysql-stop
    docker run -p 3306:3306 --name $(DATABASE_NAME) \
        -v /tmp/mysql:/var/lib/mysql \
        -e MYSQL_DATABASE=$(DATABASE_NAME) \
        -e MYSQL_USER=$(DATABASE_USER) \
        -e MYSQL_ROOT_PASSWORD=$(DATABASE_PASSWORD) \
        -d mariadb:latest
    while ! docker exec $(DATABASE_NAME) healthcheck.sh --connect 2> /dev/null; do sleep 1; done
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73042480

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档