Conéctese a mysql en un contenedor docker desde el host


109

(Probablemente sea una pregunta tonta debido a mi conocimiento limitado con la administración de Docker o mysql, pero como pasé una noche entera con este tema, me atrevo a preguntar).

En una palabra

Quiero ejecutar mysql en un contenedor docker y conectarme a él desde mi host. Hasta ahora, lo mejor que he logrado es:

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

Más detalles

Estoy usando lo siguiente 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

En el directorio donde está este archivo, puedo construir con éxito la imagen y ejecutarla con:

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

Cuando adjunto a la imagen, parece funcionar bien:

# 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.
[...]

Sin embargo, no tengo tanto éxito con el anfitrión:

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

Aún más detalles

  • He visto que hay una pregunta que se parece a la mía . Sin embargo, no es lo mismo (y de todos modos no tiene ninguna respuesta)
    • He visto que hay imagenes dedicadas a mysql , pero no tuve más éxito con ellas
    • Mi grep -vpuede sentirse raro. Es cierto que puede haber una forma más limpia de hacerlo. Pero cuando adjunto mi imagen, puedo observar que realmente funcionó como se esperaba (es decir, eliminó el bind-address). Y puedo ver en el contenedor /var/log/mysql/error.log:

Nombre de host del servidor (dirección de enlace): '0.0.0.0'; puerto: 3306 - '0.0.0.0' se resuelve como '0.0.0.0'; Socket de servidor creado en IP: '0.0.0.0'.


1
Probablemente no tan tonto. Me encontré con esto por décima vez y finalmente tuve tiempo de probarlo en casa.
kiltek

Respuestas:


171

Si su host Docker MySQL se está ejecutando correctamente, puede conectarse a él desde la máquina local, pero debe especificar el host, el puerto y el protocolo de esta manera:

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

Cambie 3306 al número de puerto que ha reenviado desde el contenedor Docker (en su caso, será 12345).

Debido a que está ejecutando MySQL dentro del contenedor Docker, el socket no está disponible y necesita conectarse a través de TCP. Configurar "--protocol" en el comando mysql cambiará eso.


1
¿Puede aclarar por qué el socket mysql no está disponible? Su comando funciona, pero me pregunto si hay una manera de montar el socket mysql en el host desde el contenedor.
Lucas

9
No soy un experto en comunicación Unix, pero por lo que entiendo, socket es una conexión representada como un archivo. Dado que el archivo de socket no se comparte entre el contenedor Docker y la máquina host, el cliente MySQL no puede usar uno desde el interior del contenedor Docker. Para conectarse al servidor MySQL dentro del contenedor Docker desde la máquina host, puede: 1. Configurar el servidor MySQL para que coloque el socket en el lugar especificado --socket=/var/run/mysqld/mysqld.sock2. Montar este archivo fuera del contenedor Docker 3. Especificar la ruta del socket en el cliente MySQL con--socket=/host/mysql.sock
maniekq

@maniekq ¡Gran comentario! Pero, ¿verificó las tres posibilidades? ¿Realmente funcionan todos?
Andru

7
Después de una larga lucha, encontré esta respuesta de oro, --protocol=tcpfinalmente hice que la conexión funcionara. ¡Gracias @maniekq por la buena respuesta y su explicación en sockets a través de su comentario!
panelista

1
No debería ser la respuesta aceptada, ya que afirma explícitamente que no tiene idea de la comunicación de archivos UNIX.
kiltek

50

Si usa "127.0.0.1" en lugar de localhost, mysql usará el método tcp y debería poder conectar el contenedor con:

mysql -h 127.0.0.1 -P 3306 -u root

4
Puedo verificar que una vez que cambié localhost a 127.0.0.1 y eliminé la bandera del protocolo, funcionó igual
Craig Wayne

2
Creo que esta es la mejor y más corta respuesta;)
rezam

1
Puede ser breve, pero no es la respuesta, dado que TCP es el método más lento para comunicarse con mysql. (más CPU y mayor latencia)
Juan

1
@John, tienes razón, es más lento pero existe. Por supuesto, puede compartir /var/run/mysqld/mysqld.sock entre el host y el contenedor.
Vasili Pascal

2
Eso es lo que recomendaría para cualquier DB de mayor servicio. es tan simple como "-v socketfile.sock" y luego mysql --socket /path/file.sock sin contaminar la pila tcp / ip.
John

27

Recomiendo revisar docker-compose. Así es como funcionaría:

Cree un archivo llamado docker-compose.yml que tenga este aspecto:

version: '2'

services:

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

A continuación, ejecute:

$ docker-componer

Notas:

Ahora, puede acceder a la consola mysql de la siguiente manera:

$ mysql -P 8083 --protocolo = tcp -u raíz -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:

  • Puede pasar la marca -d para ejecutar el contenedor mysql / mariadb en modo separado / en segundo plano.

  • La contraseña es "wp", que se define en el archivo docker-compose.yml.

  • El mismo consejo que maniekq pero ejemplo completo con docker-compose.


3
--protocol=tcparregló todo para mí. ¡Gracias!
Charlie L

Gracias por esta respuesta, tuve el mismo problema que en el tema, pero después de usar --protocol = tcp se solucionó. Pensé que algo andaba mal con la red Docker.
jiriki

16

El método simple es compartir el socket mysql unix con la máquina host. Luego conecte a través del enchufe

Pasos:

  • Cree una carpeta compartida para la máquina host, por ejemplo: mkdir /host
  • Ejecute el contenedor docker con la opción de montaje de volumen docker run -it -v /host:/shared <mysql image>.
  • Luego cambie el archivo de configuración de mysql /etc/my.cnfy cambie la entrada de socket en el archivo asocket=/shared/mysql.sock
  • Reinicie el servicio MySQL service mysql restarten la ventana acoplable
  • Finalmente, conéctese al servidor MySQL desde el host a través del socket mysql -u root --socket=/host/mysql.sock. Si la contraseña usa la opción -p

1
¿Tiene que hacer esto si el cliente MySQL está en otro contenedor?
Stephane

No lo se. Opté por este método porque el método de puerto tcp-ip no me funcionó. Si está utilizando dos contenedores para el servidor y el cliente, puede compartir un directorio común con ambos contenedores y usar el socket Unix para conectarse a MySQL.
Jobin

1
La respuesta a mi pregunta es no cuando utilizo docker-compose con un enlace en los contenedores.
Stephane

9

si está ejecutando docker bajo docker-machine?

ejecutar para obtener ip:

docker-machine ip <machine>

devuelve la ip de la máquina e intenta conectar mysql:

mysql -h<docker-machine-ip>

Resuelto en Docker-Toolbox :) Muchas gracias.
Vuong

5

Hago esto ejecutando un contenedor de ventana acoplable temporal en mi servidor para no tener que preocuparme por lo que está instalado en mi host. Primero, defino lo que necesito (que debe modificar para sus propósitos):

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

Siempre creo una nueva red Docker que cualquier otro contenedor necesitará:

docker network create --driver bridge $DB_DOCKER_NETWORK

Inicie un servidor de base de datos mySQL:

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

Capturar la dirección IP del nuevo contenedor del 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 una interfaz de línea de comandos al 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 contenedor se eliminará solo cuando salga de la interfaz mySQL, mientras que el servidor seguirá funcionando. También puede compartir un volumen entre el servidor y el host para facilitar la importación de datos o scripts. ¡Espero que esto ayude!


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

Recuerde cambiar el usuario, el puerto y el host para que coincida con sus configuraciones. La marca -p es necesaria si el usuario de su base de datos está configurado con una contraseña


2

Para la conversión, puede crear un ~/.my.cnfarchivo en el host:

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

Luego, la próxima vez, ejecute el mysqlcliente mysql para abrir la conexión.


1

Pude conectar mi servidor sql5.7 ejecutándose en mi host usando el siguiente comando: mysql -h 10.10.1.7 -P 3307 --protocol = tcp -u root -p donde la ip dada es mi ip de host y 3307 es la puerto forwaded en mysql docker.Después de ingresar el comando, escriba la contraseña para myql.Eso es.Ahora está conectado el contenedor de mysql docker desde su hostmachine


0

ejecutar el siguiente comando para ejecutar el contenedor

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

ejecute este comando para obtener mysql db en la máquina host

mysql -h 127.0.0.1 -P 8306 -uroot  -pPASS

en tu caso es

mysql -h 127.0.0.1 -P 12345 -uroot  -pPASS

Esto solo funciona si usa 127.0.0.1 como dirección. Si usa la dirección no local del host, debe agregar la --protocol=tcpbandera como se describe en varios otros comentarios / respuestas. En mi caso, fue más confuso porque también tenía una instancia de mysql local, no acoplada, ejecutándose. De forma predeterminada, incluso cuando se especifica el puerto, incluso si el puerto es incorrecto, el comando 'mysql' se conectará a través del archivo de socket a la instancia local.
Rich

@Rich, entonces, ¿qué hiciste para resolver ese problema? Incluso tengo una configuración similar, un MySql ejecutándose en el host y otro en el contenedor de la ventana acoplable.
NITHIN RAJ T

@NITHINRAJT hay 2 formas de lograr esto DESPUÉS de asegurarse de que su instancia de Docker no esté escuchando en el mismo puerto (por ejemplo, como en esta respuesta, 8306). (1) Pruebe esta respuesta, la que estamos comentando (por ejemplo, conectándose a 127.0.0.1. (2) Pruebe la siguiente respuesta - mysql -u root -P <EXPOSED_DOCKER_PORT_HERE> -h <YOUR_HOST_IP_ADDRESS_HERE> --protocol=tcp -p. La bandera, --protocol=tcpes la clave para hacer que esto funcione.
Rich


0

OKAY. Finalmente resolví este problema. A continuación, mi solución utilizada en https://sqlflow.org/sqlflow .

La solución completa

Para que la demostración sea autónoma, moví todo el código necesario a https://github.com/wangkuiyi/mysql-server-in-docker .

La clave de la solución

No uso la imagen oficial en DockerHub.com https://hub.docker.com/r/mysql/mysql-server . En cambio, hice el mío instalando MySQL en Ubuntu 18.04. Este enfoque me da la oportunidad de iniciar mysqld y vincularlo a 0.0.0.0 (todas las direcciones IP) .

Para obtener más detalles, consulte estas líneas en mi repositorio de 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 mi solución

  1. Git clona el repositorio mencionado anteriormente.
    git clone https://github.com/wangkuiyi/mysql-server-in-docker
    cd mysql-server-in-docker
  2. Cree la imagen de Docker del servidor MySQL
    docker build -t mysql:yi .
  3. Inicie el servidor MySQL en un contenedor
    docker run --rm -d -p 23306:3306 mysql:yi
  4. Instale el cliente MySQL en el host, si aún no lo está. Estoy ejecutando Ubuntu 18.04 en el host (mi estación de trabajo), así que uso apt-get.
    sudo apt-get install -y mysql-client
  5. Conéctese desde el host al servidor MySQL que se ejecuta en el contenedor.
    mysql --host 127.0.0.1 --port 23306 --user root -proot

Conectarse desde otro contenedor en el mismo host

Podemos ejecutar el cliente MySQL incluso desde otro contenedor (en el mismo host).

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

Conectarse desde otro host

En mi iMac, instalo el cliente MySQL usando Homebrew.

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

Luego, puedo acceder al host de Ubuntu anterior (192.168.1.22).

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

Conectarse desde un contenedor que se ejecuta en otro host

Incluso puedo ejecutar el cliente MySQL en un contenedor que se ejecuta en el iMac para conectarme al servidor MySQL en un contenedor en mi estación de trabajo Ubuntu.

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

Un caso especial

En el caso de que ejecutemos el cliente y el servidor MySQL en contenedores separados que se ejecutan en el mismo host, esto podría suceder cuando estamos configurando un CI, no necesitamos construir nuestra propia imagen de Docker del servidor MySQL. En su lugar, podemos usar el--net=container:mysql_server_container_name cuando ejecutamos el contenedor del cliente.

Para iniciar el servidor

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

Para iniciar el cliente

docker run --rm -it --net=container:mysql mysql/mysql-server mysql \
 -h 127.0.0.1 -P 3306 -u root -proot

-1
  • Docker ejecutar -e MYSQL_ROOT_PASSWORD = pass --name sql-db -p 3306: 3306 mysql

  • docker exec -it sql-db bash

  • mysql -u root -p


que terminará conERROR 1524 (HY000): Plugin 'unix_socket' is not loaded
Enerccio

@Enerccio ¿Podrías intentarlo de nuevo?
Ajay Singh

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.