Conecte-se ao mysql em um contêiner docker do host

109

(É provavelmente uma pergunta idiota devido ao meu conhecimento limitado com a administração do Docker ou do mysql, mas como passei uma noite inteira neste assunto, atrevo-me a perguntar.)

Em poucas palavras

Eu quero executar o mysql em um contêiner docker e me conectar a ele do meu host. Até agora, o melhor que consegui foi:

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

Mais detalhes

Estou usando o seguinte Dockerfile:

FROM ubuntu:14.04.3
RUN apt-get update && apt-get install -y mysql-server

# Ensure we won't bind to localhost only
RUN grep -v bind-address /etc/mysql/my.cnf > temp.txt \
  && mv temp.txt /etc/mysql/my.cnf

# It doesn't seem needed since I'll use -p, but it can't hurt
EXPOSE 3306

CMD /etc/init.d/mysql start && tail -F /var/log/mysql.log

No diretório onde está este arquivo, posso construir a imagem com sucesso e executá-la com:

> docker build -t my-image .
> docker run -d -p 12345:3306 my-image

Quando anexo à imagem, parece funcionar muito bem:

# from the host
> docker exec -it <my_image_name> bash

#inside of the container now
$ mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
[...]

No entanto, não tenho muito sucesso do anfitrião:

> mysql -P 12345 -uroot
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

Ainda mais detalhes

  • Eu vi que há uma pergunta que se parece com a minha . No entanto, não é o mesmo (e não tem nenhuma resposta de qualquer maneira)
    • Eu vi que existem imagens dedicadas ao mysql , mas não tive mais sucesso com elas
    • Minha grep -vpodem se sentir estranho. É verdade que pode haver uma maneira mais limpa de fazer isso. Mas quando anexo minha imagem, posso observar que ela realmente funcionou conforme o esperado (ou seja: removi o bind-address). E posso ver no contêiner /var/log/mysql/error.log:

Nome do host do servidor (endereço de ligação): '0.0.0.0'; porta: 3306 - '0.0.0.0' resolve para '0.0.0.0'; Soquete do servidor criado no IP: '0.0.0.0'.

gturri
fonte
1
Provavelmente não tão burro. Me deparei com isso pela décima vez e finalmente tive tempo de experimentar em casa.
kiltek

Respostas:

171

Se o seu host Docker MySQL estiver funcionando corretamente, você pode se conectar a ele a partir da máquina local, mas deve especificar o host, a porta e o protocolo assim:

mysql -h localhost -P 3306 --protocol=tcp -u root

Altere 3306 para o número da porta que você encaminhou do contêiner Docker (no seu caso, será 12345).

Como você está executando o MySQL dentro do contêiner Docker, o soquete não está disponível e você precisa se conectar por meio de TCP. Configurar "--protocol" no comando mysql mudará isso.

maniekq
fonte
1
Você pode esclarecer porque o socket mysql não está disponível? Seu comando funciona, mas estou me perguntando se há uma maneira de montar o soquete mysql para o host a partir do contêiner.
Lucas
9
Não sou um especialista em comunicação Unix, mas pelo que entendi socket é uma conexão representada como um arquivo. Como o arquivo de soquete não é compartilhado entre o contêiner Docker e a máquina host, o cliente MySQL não pode usar um de dentro do contêiner Docker. Para se conectar ao servidor MySQL dentro do contêiner Docker da máquina host, você pode: 1. Configurar o servidor MySQL para colocar o soquete no local especificado --socket=/var/run/mysqld/mysqld.sock2. Monte este arquivo fora do contêiner Docker 3. Especifique o caminho para o soquete no cliente MySQL com--socket=/host/mysql.sock
maniekq
@maniekq Ótimo comentário! Mas você verificou todas as suas três possibilidades? Todos eles realmente funcionam?
Andru
7
Depois de uma longa luta, encontrei esta resposta de ouro, --protocol=tcpfinalmente fiz a conexão funcionar. Obrigado @maniekq pela boa resposta e sua explicação sobre sockets via seu comentário!
panepeter de
1
Não deve ser a resposta aceita, já que ele afirma explicitamente que não tem nenhuma idéia da comunicação de arquivos UNIX.
kiltek
50

Se você usar "127.0.0.1" em vez de localhost, o mysql usará o método tcp e você deverá ser capaz de conectar o contêiner com:

mysql -h 127.0.0.1 -P 3306 -u root
Vasili Pascal
fonte
4
Posso verificar que, depois de alterar localhost para 127.0.0.1 e remover o sinalizador de protocolo, funcionou da mesma maneira
Craig Wayne
2
Acho que esta é a resposta mais curta e melhor;)
rezam
1
Pode ser curto, mas não é a resposta, visto que o TCP é o método mais lento para se comunicar com o mysql. (mais CPU e latência mais alta)
João
1
@John você tem razão, é mais lento, mas existe. Claro que você pode compartilhar /var/run/mysqld/mysqld.sock entre o host e o contêiner.
Vasili Pascal
2
Isso é o que eu recomendaria para qualquer DB de serviço mais elevado. é tão simples quanto "-v socketfile.sock" e então mysql --socket /path/file.sock sem poluir a pilha tcp / ip.
João
27

Eu recomendo verificar docker-compose. Veja como isso funcionaria:

Crie um arquivo chamado docker-compose.yml parecido com este:

version: '2'

services:

  mysql:
    image: mariadb:10.1.19
    ports:
      - 8083:3306
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: wp

Em seguida, execute:

$ docker-compose up

Notas:

Agora, você pode acessar o console mysql desta forma:

$ mysql -P 8083 --protocol = tcp -u root -p

Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 5.5.5-10.1.19-MariaDB-1~jessie mariadb.org binary distribution

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

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>

Notas:

  • Você pode passar o sinalizador -d para executar o contêiner mysql / mariadb no modo separado / plano de fundo.

  • A senha é "wp", que é definida no arquivo docker-compose.yml.

  • Mesmo conselho de maniekq, mas exemplo completo com docker-compose.

13x
fonte
3
--protocol=tcpconsertou tudo para mim. Obrigado!
Charlie L
Obrigado por esta resposta, eu tive o mesmo problema que no tópico, mas depois de usar --protocol = tcp ele corrigiu. Achei que algo estava errado com a rede docker.
jiriki
16

O método simples é compartilhar o socket unix mysql com a máquina host. Em seguida, conecte através do soquete

Passos:

  • Crie uma pasta compartilhada para a máquina host, por exemplo: mkdir /host
  • Execute o contêiner do docker com a opção de montagem de volume docker run -it -v /host:/shared <mysql image>.
  • Então mude o arquivo de configuração mysql /etc/my.cnfe mude a entrada de socket no arquivo parasocket=/shared/mysql.sock
  • Reinicie o serviço MySQL service mysql restartno docker
  • Finalmente, conecte-se ao servidor MySQL do host através do soquete mysql -u root --socket=/host/mysql.sock. Se a senha usar a opção -p
Jobin
fonte
1
Você precisa fazer isso se o cliente MySQL estiver em outro contêiner?
Stephane,
Eu não sei disso. Optei por esse método porque o método da porta tcp-ip não funcionou para mim. Se estiver usando dois contêineres para servidor e cliente, você pode compartilhar um diretório comum para ambos os contêineres e usar soquete Unix para se conectar ao MySQL.
Jobin
1
A resposta à minha pergunta é não quando uso docker-compose com um link nos contêineres.
Stephane
9

se você está executando docker em docker-machine?

execute para obter o ip:

docker-machine ip <machine>

retorna o ip da máquina e tenta conectar o mysql:

mysql -h<docker-machine-ip>
Gerardo Rochín
fonte
Resolvido no Docker-Toolbox :) Muito obrigado.
Vuong
5

Eu faço isso executando um contêiner docker temporário em meu servidor para que não precise me preocupar com o que está instalado em meu host. Primeiro, eu defino o que preciso (o que você deve modificar para seus propósitos):

export MYSQL_SERVER_CONTAINER=mysql-db
export MYSQL_ROOT_PASSWORD=pswd 
export DB_DOCKER_NETWORK=db-net
export MYSQL_PORT=6604

Sempre crio uma nova rede docker da qual todos os outros contêineres precisarão:

docker network create --driver bridge $DB_DOCKER_NETWORK

Inicie um servidor de banco de dados mySQL:

docker run --detach --name=$MYSQL_SERVER_CONTAINER --net=$DB_DOCKER_NETWORK --env="MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD" -p ${MYSQL_PORT}:3306 mysql

Capture o endereço IP do novo container do servidor

export DBIP="$(docker inspect ${MYSQL_SERVER_CONTAINER} | grep -i 'ipaddress' | grep -oE '((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])')"

Abra uma interface de linha de comando para o servidor:

docker run -it -v ${HOST_DATA}:/data --net=$DB_DOCKER_NETWORK --link ${MYSQL_SERVER_CONTAINER}:mysql --rm mysql sh -c "exec mysql -h${DBIP} -uroot -p"

Este último contêiner será removido quando você sair da interface mySQL, enquanto o servidor continuará em execução. Você também pode compartilhar um volume entre o servidor e o host para facilitar a importação de dados ou scripts. Espero que isto ajude!

COwnby
fonte
5
mysql -u root -P 4406 -h localhost --protocol=tcp -p

Lembre-se de alterar o usuário, porta e host para que correspondam às suas configurações. O sinalizador -p é necessário se o usuário do seu banco de dados estiver configurado com uma senha

Hamfri
fonte
2

Para conversão, você pode criar o ~/.my.cnfarquivo no host:

[Mysql]
user=root
password=yourpass
host=127.0.0.1
port=3306

Então, da próxima vez, basta executar o mysqlcliente mysql para abrir a conexão.

lupguo
fonte
1

Consegui conectar meu sql server5.7 rodando em meu host usando o comando abaixo: mysql -h 10.10.1.7 -P 3307 --protocol = tcp -u root -p onde o ip fornecido é meu ip host e 3307 é o porta forwaded no mysql docker. Depois de inserir o comando digite a senha para myql. é isso. Agora você está conectado ao contêiner do mysql docker da sua máquina host

Rajesh k
fonte
0

execute o seguinte comando para executar o contêiner

docker run --name db_name -e MYSQL_ROOT_PASSWORD=PASS--publish 8306:3306 db_name

execute este comando para obter mysql db na máquina host

mysql -h 127.0.0.1 -P 8306 -uroot  -pPASS

no seu caso é

mysql -h 127.0.0.1 -P 12345 -uroot  -pPASS
Nitin
fonte
Isso só funciona se você usar 127.0.0.1 como o endereço. Se você usar o endereço não local do host, será necessário adicionar o --protocol=tcpsinalizador conforme descrito em vários outros comentários / respostas. No meu caso, foi ainda mais confuso porque eu tinha uma instância local, não dockerizada, do mysql rodando também. Por padrão, mesmo quando a porta é especificada, mesmo se a porta estiver incorreta, o comando 'mysql' se conectará por meio do arquivo de soquete à instância local.
Rich
@Rich então o que você fez para resolver esse problema? Mesmo eu tendo uma configuração semelhante, um MySql rodando no host e outro no docker container.
NITHIN RAJ T
@NITHINRAJT existem 2 maneiras de fazer isso DEPOIS de certificar-se de que sua instância do docker não esteja escutando na mesma porta (por exemplo, como nesta resposta, 8306). (1) Tente esta resposta, aquela que estamos comentando (por exemplo, conectando-se a 127.0.0.1. (2) Tente a próxima resposta - mysql -u root -P <EXPOSED_DOCKER_PORT_HERE> -h <YOUR_HOST_IP_ADDRESS_HERE> --protocol=tcp -p. O sinalizador --protocol=tcpé a chave para fazer este trabalho.
Rich,
0

Em seu terminal, execute: docker exec -it container_name /bin/bash Então:mysql

Denis Prescornic
fonte
0

ESTÁ BEM. Eu finalmente resolvi esse problema. Aqui segue minha solução usada em https://sqlflow.org/sqlflow .

A Solução Completa

Para tornar a demonstração independente, movi todo o código necessário para https://github.com/wangkuiyi/mysql-server-in-docker .

A chave para a solução

Não uso a imagem oficial no DockerHub.com https://hub.docker.com/r/mysql/mysql-server . Em vez disso, criei meu próprio instalando o MySQL no Ubuntu 18.04. Essa abordagem me dá a chance de iniciar o mysqld e vinculá-lo a 0.0.0.0 (todos os IPs) .

Para obter detalhes, consulte essas linhas em meu repositório GitHub.

SQLFLOW_MYSQL_HOST=${SQLFLOW_MYSQL_HOST:-0.0.0.0}

echo "Start mysqld ..."
sed -i "s/.*bind-address.*/bind-address = ${SQLFLOW_MYSQL_HOST}/" \
    /etc/mysql/mysql.conf.d/mysqld.cnf
service mysql start

Para verificar minha solução

  1. Git clone o repositório mencionado anteriormente.
    git clone https://github.com/wangkuiyi/mysql-server-in-docker
    cd mysql-server-in-docker
  2. Crie a imagem Docker do servidor MySQL
    docker build -t mysql:yi .
  3. Inicie o servidor MySQL em um contêiner
    docker run --rm -d -p 23306:3306 mysql:yi
  4. Instale o cliente MySQL no host, se ainda não. Estou executando o Ubuntu 18.04 no host (minha estação de trabalho), então eu o uso apt-get.
    sudo apt-get install -y mysql-client
  5. Conecte-se do host ao servidor MySQL em execução no contêiner.
    mysql --host 127.0.0.1 --port 23306 --user root -proot

Conecte-se de outro contêiner no mesmo host

Podemos executar o cliente MySQL até mesmo de outro contêiner (no mesmo host).

docker run --rm -it --net=host mysql/mysql-server mysql \
   -h 127.0.0.1 -P 13306 -u root -proot

Conecte-se de outro host

No meu iMac, instalo o cliente MySQL usando o Homebrew.

brew install mysql-client
export PATH="/usr/local/opt/mysql-client/bin:$PATH"

Então, posso acessar o host Ubuntu acima (192.168.1.22).

mysql -h 192.168.1.22 -P 13306 -u root -proot

Conectar de um contêiner em execução em outro host

Posso até executar o cliente MySQL em um contêiner em execução no iMac para me conectar ao servidor MySQL em um contêiner na minha estação de trabalho Ubuntu.

docker run --rm -it --net=host mysql/mysql-server mysql \
    -h 192.168.1.22 -P 13306 -u root -proot

Um Caso Especial

No caso de executarmos o cliente e o servidor MySQL em contêineres separados em execução no mesmo host - isso pode acontecer quando estamos configurando um CI, não precisamos construir nossa própria imagem Docker do servidor MySQL. Em vez disso, podemos usar o --net=container:mysql_server_container_namequando executamos o contêiner do cliente.

Para iniciar o servidor

docker run --rm -d --name mysql mysql/mysql-server

Para iniciar o cliente

docker run --rm -it --net=container:mysql mysql/mysql-server mysql \
 -h 127.0.0.1 -P 3306 -u root -proot
cxwangyi
fonte
-1
  • docker run -e MYSQL_ROOT_PASSWORD = pass --name sql-db -p 3306: 3306 mysql

  • docker exec -it sql-db bash

  • mysql -u root -p

Ajay Singh
fonte
que terminará comERROR 1524 (HY000): Plugin 'unix_socket' is not loaded
Enerccio
@Enerccio Você poderia tentar novamente?
Ajay Singh
-5

mude "localhost" para seu endereço de con ip real
porque é para mysql_connect ()

spdreamin dante
fonte