Diretório de artigos
Este artigo irá resumir como criar um contêiner mysql por meio do docker e conectar o banco de dados do contêiner mysql por meio do host ou ferramenta de visualização mysql (houve problemas no meio e finalmente foram resolvidos com sucesso)
- Erro 1:
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 2
- Erro 2:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
Observação:
estou usando docker desktop for windows
, com base WSL2 后端的
e WSL2
distribuindo usando Ubuntu
, a maioria dos comandos nos exemplos de demonstração a seguir são Ubuntu
acessados por meio de Docker
.
1. Docker cria um contêiner MySQL
1. Extraia a imagem MySQL
Obtenha a versão mais recente do mysql
docker pull mysql
ou
Extraia a versão especificada do mysql (como 5.7)
docker pull mysql:5.7
A seguir, use docker images mysql
para visualizar a imagem mysql extraída
root@GC:~# docker images mysql
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql latest 99afc808f15b 4 weeks ago 577MB
mysql 5.7 92034fe9a41f 5 weeks ago 581MB
root@GC:~#
2. Crie e execute o contêiner MySQL
Use para docker run
criar e executar contêiner mysql
Use docker ps
para visualizar contêineres em execução
root@GC:~# docker run -d --name mysql5.7 -p 33065:33065 -e MYSQL_ROOT_PASSWORD=1234qwer mysql:5.7
10124d6b026e8442e7250196a1c979ff3fdd7ad5021fc50865cb871cfa662ee6
root@GC:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
10124d6b026e mysql:5.7 "docker-entrypoint.s…" About a minute ago Up About a minute 3306/tcp, 33060/tcp, 0.0.0.0:33065->33065/tcp mysql5.7
docker run
: Crie e execute o contêiner
-d
: Modo de execução em segundo plano
--name mysql5.7
: Dê um nome ao contêiner criado, se não for especificado, um nome padrão será gerado aleatoriamente
-p 33065:33065
: Mapeie a porta do contêiner para a porta do host (a primeira é a porta do host, e o último é a porta mysql exposta pelo contêiner)
-e MYSQL_ROOT_PASSWORD=1234qwer
: Defina uma variável de ambiente para o contêiner (defina a senha do usuário root do myslq)
mysql:5.7
: Especifique o nome e a tag da imagem usada para criar o contêiner, você também pode usar a imagem em vez disso, id
Nota: Há um problema com "-p 33065:33065" usado aqui, que será discutido posteriormente.
(Esta também é uma armadilha que eu mesmo criei e me prendi por um dia...)
3. Crie e execute o contêiner MySQL (mapeamento de diretório)
No uso real, diretórios importantes, como dados, logs e arquivos de configuração no contêiner do docker, precisam ser mapeados para o host local para evitar perda de dados após a exclusão do contêiner do docker.
Mapeando para o modo de diretório do Windows:
docker run -d -p 3306:3306 --name mysql5.7 ^
-v /e/mysql/docker-mysql/my.cnf:/etc/my.cnf ^
-v /e/mysql/docker-mysql/logs:/var/log/mysql ^
-v /e/mysql/docker-mysql/data:/var/lib/mysql ^
-e MYSQL_ROOT_PASSWORD=1234qwer ^
mysql:5.7
Método de mapeamento para diretório Linux:
docker run -d -p 3306:3306 --name mysql \
-v /mydata/mysql/log:/var/log/mysql \
-v /mydata/mysql/data:/var/lib/mysql \
-v /mydata/mysql/my.cnf:/etc/my.cnf \
-e MYSQL_ROOT_PASSWORD=1234qwer \
mysql:5.7
No comando acima,
:
a parte antes dos dois pontos são as informações de configuração do host e a parte após os dois pontos são as informações de configuração do contêiner.
2. Conecte-se ao banco de dados MySQL
1. No contêiner MySQL, conecte-se ao MySQL
Entre no contêiner MySQL e conecte o mysql dentro do contêiner
root@GC:~# docker exec -it mysql5.7 /bin/bash
bash-4.2# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.43 MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> exit
Bye
bash-4.2#
Como acima, você pode se conectar ao banco de dados mysql normalmente no contêiner mysql.
2. Conecte-se ao MySQL na máquina host (problemas encontrados e soluções)
root@GC:~# mysql -h 127.0.0.1 -P 33065 -u root -p
Enter password:
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 2
Este problema está me incomodando há um dia. Pesquisei na Internet a palavra-chave [ERROR 2013 (HY000): Lost connection to MySQL server at 'reading Initial Communication Pack', system error: 2] e encontrei muitos artigos relacionados, mas nenhum um deles poderia resolver a questão.
Soluções tentadas (falharam)
(Embora nenhum deles tenha resolvido meu problema, ainda listo aqui):
1) Autorize o usuário root do mysql a acessar a rede externa;
root@GC:~# docker exec -it mysql5.7 /bin/bash
bash-4.2# mysql -u root -p
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '1234qwer' WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;
Na verdade, isso é um pouco redundante. Depois que o contêiner mysql é criado, essa permissão é dada por padrão
(você pode descobrir através da seguinte instrução sql. Observe que o comando grant acima não é executado após a criação do contêiner mysql. Os resultados são os seguintes)
mysql> select user,host from mysql.user;
+---------------+-----------+
| user | host |
+---------------+-----------+
| root | % |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+---------------+-----------+
4 rows in set (0.00 sec)
mysql>
2) Modifique my.cnf
o arquivo de configuração
(Localização geral: /etc/my.cnf
ou /etc/mysql/my.cnf
)
Comente no arquivo de configuração bind-address = 127.0.0.1
e [mysqld]
adicione-o na configuraçãoskip-name-resolve
Esta solução não funciona para mim, pois na minha configuração ela não existe bind-address = 127.0.0.1
e, ao mesmo [mysqld]
tempo já está skip-name-resolve
configurada por padrão.
Aqui está minha my.cnf
configuração padrão:
bash-4.2# cat /etc/my.cnf
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
skip-host-cache
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
#log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
3) Desligue o firewall do host onde o contêiner mysql está localizado
(Estou aqui Windows docker desktop(Use the WSL 2 based engine)
, a distribuição padrão do Linux é Ubuntu)
Desliguei Windows
o firewall (o Ubuntu não iniciou o firewall) e depois acessei através do Windows cmd ou Ubuntu bash, mysql -h 127.0.0.1 -P 33065 -u root -p
todos os erros foram relatados: Lost connection to MySQL server at 'reading initial communication packet'
.
Portanto a solução de desligar o firewall também é inválida para mim.
4) Reinicie o serviço MySQL
Também se diz na Internet que reiniciar o serviço mysql resolverá o problema.
Mas reiniciei o container mysql aqui, e até reiniciei o sistema Windows, mas não funcionou.
Também tentei algumas outras soluções, mas não consigo me lembrar delas agora. De qualquer forma, demorei um dia inteiro.
Solução final para o problema (bem-sucedida)
Depois de terminar o jantar, recriei um contêiner mysql, e o mysql desse contêiner poderia ser conectado a partir da janela cmd ou do ubuntu bash.
Aqui estão as causas raízes e soluções:
Qual é a diferença entre este contêiner mysql recém-criado e aquele criado originalmente?
A questão é: portos, portos, portos! ! !
O comando inicial de criação do contêiner mysql:
root@GC:~$ docker run -d --name mysql5.7 -p 33065:33065 -e MYSQL_ROOT_PASSWORD=1234qwer mysql:5.7
O comando de criação de contêiner mysql criado posteriormente:
root@GC:~$ docker run -d --name mysql5.7-2 -p 33062:3306 -e MYSQL_ROOT_PASSWORD=1234qwer mysql:5.7
O foco está -p <宿主机端口>:<容器的端口>
nos parâmetros.
<容器的端口>
Deve ser especificada como a porta que o mysql escuta. O padrão é 3306
;
<宿主机端口>
pode ser qualquer número de porta (desde que não esteja ocupada por outros programas);
No mysql, você pode show variables like 'port';
visualizar a porta de escuta do mysql por meio de instruções
root@GC:~$ mysql -h 127.0.0.1 -P 33062 -uroot -p
mysql> show variables like 'port';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port | 3306 |
+---------------+-------+
1 row in set (0.00 sec)
Se você modificar a porta de escuta do contêiner mysql da seguinte maneira (alguns comentários foram excluídos), especifique-a [mysqld]
abaixo port=33065
( port
este campo não é configurado por padrão e o serviço mysql escutará a porta 3306 por padrão)
root@GC:~$ docker exec -it mysql5.7 /bin/bash
bash-4.2# vim /etc/my.cnf
bash-4.2# cat /etc/my.cnf
[mysqld]
port=33065
skip-host-cache
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
symbolic-links=0
#log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[client]
socket=/var/run/mysqld/mysqld.sock
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
Após a modificação, reinicie o contêiner mysql.
Em seguida, verifique a porta em que o mysql está escutando, ela foi alterada para33065
root@GC:~$ docker restart mysql5.7
root@GC:~$ docker exec -it mysql5.7 /bin/bash
bash-4.2# mysql -uroot -p
mysql> show variables like 'port';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port | 33065 |
+---------------+-------+
1 row in set (0.00 sec)
mysql>
-p 33605:33605
Neste momento, você pode se conectar ao banco de dados mysql do contêiner mysql que você criou inicialmente por meio do window cmd ou ubuntu bash ou ferramenta de conexão remota .
root@GC:~$ mysql -h127.0.0.1 -P33065 -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.43 MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.00 sec)
mysql>
Nota: Certifique-se de especificar -h
os parâmetros e o valor é 127.0.0.1
ou<宿主机的网桥IP地址>
Outro erro de conexão
Quando o host se conecta ao contêiner mysql, se -h
os parâmetros não forem especificados, ou se forem especificados -h localhost
, o seguinte erro será relatado:
root@GC:~$ mysql -P33065 -uroot -p
Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
cyinl@GC:~$ mysql -hlocalhost -P33065 -uroot -p
Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
Isso ocorre porque quando os -h
parâmetros padrão (ou -h localhost
) são usados, o cliente MySQL usa o método de arquivo Unix Socket para se conectar ao servidor de banco de dados local por padrão , e a porta exposta pelo contêiner mysql é o protocolo TCP 127.0.0.1
. <宿主机的网桥IP地址>
name pode forçar o cliente MySQL a usar TCP/IP
o método para conectar. Em vez Unix Socket文件
de conectar, a conexão pode ser bem-sucedida.
Concluindo, a razão pela qual encontrei o problema acima é que tomei como certo que se fosse passado -p <宿主机端口>:<容器端口>
e <容器端口>
especificado como 33065
, então o mysql criado e executado escutaria 33065
a porta e durante todo o processo de solução de problemas, não pensei sobre verificando qual porta o mysql estava escutando. (É muito bobo agora que penso nisso)