Connettiti a mysql in un contenitore Docker dall'host


109

(Probabilmente è una domanda stupida a causa della mia conoscenza limitata con Docker o amministrazione mysql, ma dato che ho passato un'intera serata su questo problema, ho il coraggio di chiederlo.)

In poche parole

Voglio eseguire mysql in un container Docker e connettermi ad esso dal mio host. Finora, il meglio che ho ottenuto è:

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

Più dettagli

Sto usando quanto segue 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

Nella directory in cui si trova questo file, posso costruire con successo l'immagine ed eseguirla con:

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

Quando allego all'immagine, sembra che funzioni bene:

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

Tuttavia non ho molto successo dall'host:

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

Ancora più dettagli

  • Ho visto che c'è una domanda che somiglia alla mia . Tuttavia, non è lo stesso (e comunque non ha risposte)
    • Ho visto che ci sono immagini dedicate a mysql , ma non ho avuto più successo con esse
    • Il mio grep -vpuò sembrare strano. Certo, potrebbe esserci un modo più pulito per farlo. Ma quando allego la mia immagine, posso osservare che ha effettivamente funzionato come previsto (ad esempio: rimosso il bind-address). E posso vedere nel contenitore /var/log/mysql/error.log:

Nome host del server (indirizzo di associazione): "0.0.0.0"; porta: 3306 - "0.0.0.0" viene risolto in "0.0.0.0"; Socket del server creato su IP: "0.0.0.0".


1
Probabilmente non così stupido. Mi sono imbattuto in questo per la decima volta e finalmente ho avuto il tempo di provarlo a casa.
kiltek

Risposte:


171

Se il tuo host Docker MySQL funziona correttamente, puoi connetterti ad esso dalla macchina locale, ma dovresti specificare host, porta e protocollo in questo modo:

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

Cambia 3306 nel numero di porta che hai inoltrato dal container Docker (nel tuo caso sarà 12345).

Poiché stai eseguendo MySQL all'interno del contenitore Docker, il socket non è disponibile e devi connetterti tramite TCP. L'impostazione "--protocol" nel comando mysql cambierà la situazione.


1
Puoi chiarire perché il socket mysql non è disponibile? Il tuo comando funziona, ma mi chiedo se c'è un modo per montare il socket mysql sull'host dal contenitore.
Lucas

9
Non sono un esperto di comunicazione Unix, ma da quello che ho capito il socket è una connessione rappresentata come un file. Poiché il file socket non è condiviso tra il contenitore Docker e la macchina host, il client MySQL non può utilizzarne uno dall'interno del contenitore Docker. Per connetterti al server MySQL all'interno del contenitore Docker dalla macchina host puoi: 1. Impostare il server MySQL per mettere il socket nella posizione specificata --socket=/var/run/mysqld/mysqld.sock2. Montare questo file fuori dal contenitore Docker 3. Specificare il percorso del socket nel client MySQL con--socket=/host/mysql.sock
maniekq

@maniekq Ottimo commento! Ma hai verificato tutte e tre le possibilità? Funzionano davvero tutti?
Andru

7
Dopo una lunga lotta ho trovato questa risposta d'oro, --protocol=tcpfinalmente ho fatto funzionare la connessione. Grazie @maniekq sia per la bella risposta che per la tua spiegazione sui socket tramite il tuo commento!
panepeter

1
Non dovrebbe essere la risposta accettata, poiché dichiara esplicitamente di non avere idea della comunicazione di file UNIX.
kiltek

50

Se utilizzi "127.0.0.1" invece di localhost, mysql utilizzerà il metodo tcp e dovresti essere in grado di connettere il container con:

mysql -h 127.0.0.1 -P 3306 -u root

4
Posso verificare che una volta modificato localhost in 127.0.0.1 e rimosso il flag del protocollo, ha funzionato allo stesso modo
Craig Wayne

2
Penso che questa sia la risposta breve e migliore;)
rezam

1
Potrebbe essere breve ma non è la risposta, dato che TCP è il metodo più lento per comunicare con mysql. (più CPU e maggiore latenza)
John

1
@ John hai ragione, è più lento ma esiste. Ovviamente puoi condividere /var/run/mysqld/mysqld.sock tra host e container.
Vasili Pascal

2
Questo è quello che consiglierei per qualsiasi DB di servizio più elevato. è semplice come "-v socketfile.sock" e poi mysql --socket /path/file.sock senza inquinare lo stack tcp / ip.
John

27

Consiglio di controllare docker-compose. Ecco come funzionerebbe:

Crea un file denominato, docker-compose.yml simile a questo:

version: '2'

services:

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

Quindi, esegui:

$ docker-compose up

Appunti:

Ora puoi accedere alla console mysql in questo modo:

$ 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>

Appunti:

  • Puoi passare il flag -d per eseguire il contenitore mysql / mariadb in modalità scollegata / in background.

  • La password è "wp", definita nel file docker-compose.yml.

  • Stesso consiglio di maniekq ma esempio completo con docker-compose.


3
--protocol=tcpaggiustato tutto per me. Grazie!
Charlie L

Grazie per questa risposta, ho avuto lo stesso problema dell'argomento ma dopo aver usato --protocol = tcp è stato risolto. Ho pensato che qualcosa non andava con la rete Docker.
jiriki

16

Il metodo semplice è condividere il socket mysql unix sulla macchina host. Quindi connettersi tramite la presa

passi:

  • Crea cartella condivisa per la macchina host, ad esempio: mkdir /host
  • Esegui il contenitore Docker con l'opzione di montaggio del volume docker run -it -v /host:/shared <mysql image> .
  • Quindi cambia il file di configurazione mysql /etc/my.cnfe cambia la voce del socket nel file insocket=/shared/mysql.sock
  • Riavvia il servizio MySQL service mysql restart nella finestra mobile
  • Infine connettiti al server MySQL dall'host attraverso il socket mysql -u root --socket=/host/mysql.sock. Se la password usa l'opzione -p

1
Devi farlo se il client MySQL si trova in un altro contenitore?
Stephane

Non lo so. Ho scelto questo metodo perché il metodo della porta tcp-ip non ha funzionato per me. Se stai usando due contenitori per server e client, puoi condividere una directory comune a entrambi i contenitori e usare il socket Unix per connetterti a MySQL.
Jobin

1
La risposta alla mia domanda è no quando utilizzo docker-compose con un collegamento sui contenitori.
Stephane

9

se esegui docker sotto docker-machine?

eseguire per ottenere ip:

docker-machine ip <machine>

restituisce l'ip per la macchina e prova a connettere mysql:

mysql -h<docker-machine-ip>

Risolto in Docker-Toolbox :) Grazie mille.
Vuong

5

Lo faccio eseguendo un container docker temporaneo sul mio server, quindi non devo preoccuparmi di ciò che è installato sul mio host. Innanzitutto, definisco ciò di cui ho bisogno (che dovresti modificare per i tuoi scopi):

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

Creo sempre una nuova rete docker di cui avranno bisogno gli altri container:

docker network create --driver bridge $DB_DOCKER_NETWORK

Avvia un server di database mySQL:

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

Cattura l'indirizzo IP del nuovo contenitore del server

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])')"

Apri un'interfaccia della riga di comando sul server:

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"

Quest'ultimo contenitore si rimuoverà da solo quando esci dall'interfaccia mySQL, mentre il server continuerà a funzionare. È inoltre possibile condividere un volume tra il server e l'host per semplificare l'importazione di dati o script. Spero che questo ti aiuti!


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

Ricordati di cambiare utente, porta e host in modo che corrispondano alle tue configurazioni. Il flag -p è richiesto se l'utente del database è configurato con una password


2

Per la conversione, puoi creare il ~/.my.cnffile nell'host:

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

Quindi la prossima volta esegui semplicemente il mysqlclient mysql per aprire la connessione.


1

Sono stato in grado di connettere il mio sql server5.7 in esecuzione sul mio host utilizzando il comando seguente: mysql -h 10.10.1.7 -P 3307 --protocol = tcp -u root -p dove l'ip dato è il mio host ip e 3307 è il port forwaded in mysql docker .Dopo aver inserito il comando digita la password per myql. che è. Ora sei connesso al container mysql docker dalla tua macchina host


0

eseguire il seguente comando per eseguire container

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

eseguire questo comando per ottenere mysql db nella macchina host

mysql -h 127.0.0.1 -P 8306 -uroot  -pPASS

nel tuo caso lo è

mysql -h 127.0.0.1 -P 12345 -uroot  -pPASS

Funziona solo se utilizzi 127.0.0.1 come indirizzo. Se utilizzi l'indirizzo non locale dell'host, devi aggiungere il --protocol=tcpflag come descritto in molti altri commenti / risposte. Nel mio caso è stato molto complicato perché avevo anche un'istanza mysql locale, non dockerizzata. Per impostazione predefinita, anche quando viene specificata la porta, anche se la porta non è corretta, il comando "mysql" si connetterà tramite il file socket all'istanza locale.
Rich

@Rich quindi cosa hai fatto per risolvere quel problema? Anche io ho una configurazione simile, un MySql in esecuzione sull'host e un altro nel container Docker.
NITHIN RAJ T

@NITHINRAJT ci sono 2 modi per farlo DOPO esserti assicurato che la tua istanza docker non sia in ascolto sulla stessa porta (ad esempio, come in questa risposta, 8306). (1) Prova questa risposta, quella su cui stiamo commentando (ad esempio, connettendoti a 127.0.0.1. (2) Prova la risposta successiva - mysql -u root -P <EXPOSED_DOCKER_PORT_HERE> -h <YOUR_HOST_IP_ADDRESS_HERE> --protocol=tcp -p. La bandiera, --protocol=tcpè la chiave per farlo funzionare.
Rich


0

OK. Finalmente ho risolto questo problema. Di seguito la mia soluzione utilizzata in https://sqlflow.org/sqlflow .

La soluzione completa

Per rendere la demo autonoma, ho spostato tutto il codice necessario su https://github.com/wangkuiyi/mysql-server-in-docker .

La chiave per la soluzione

Non utilizzo l'immagine ufficiale su DockerHub.com https://hub.docker.com/r/mysql/mysql-server . Invece, ho creato il mio installando MySQL su Ubuntu 18.04. Questo approccio mi dà la possibilità di avviare mysqld e collegarlo a 0.0.0.0 (tutti gli IP) .

Per i dettagli, fare riferimento a queste righe nel mio repository 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

Per verificare la mia soluzione

  1. Git clona il suddetto repo.
    git clone https://github.com/wangkuiyi/mysql-server-in-docker
    cd mysql-server-in-docker
  2. Crea l'immagine Docker del server MySQL
    docker build -t mysql:yi .
  3. Avvia il server MySQL in un contenitore
    docker run --rm -d -p 23306:3306 mysql:yi
  4. Installa il client MySQL sull'host, se non ancora. Sto eseguendo Ubuntu 18.04 sull'host (la mia workstation), quindi uso apt-get.
    sudo apt-get install -y mysql-client
  5. Connettiti dall'host al server MySQL in esecuzione nel contenitore.
    mysql --host 127.0.0.1 --port 23306 --user root -proot

Connetti da un altro contenitore sullo stesso host

Possiamo eseguire il client MySQL anche da un altro contenitore (sullo stesso host).

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

Connettiti da un altro host

Sul mio iMac, installo il client MySQL usando Homebrew.

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

Quindi, posso accedere all'host Ubuntu sopra (192.168.1.22).

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

Connettiti da un container in esecuzione su un altro host

Posso persino eseguire il client MySQL in un contenitore in esecuzione su iMac per connettermi al server MySQL in un contenitore sulla mia workstation Ubuntu.

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

Un caso speciale

Nel caso in cui eseguiamo client e server MySQL in contenitori separati in esecuzione sullo stesso host, ciò potrebbe accadere quando stiamo configurando un elemento della configurazione, non è necessario creare la nostra immagine Docker del server MySQL. Invece, possiamo usare --net=container:mysql_server_container_namequando eseguiamo il client container.

Per avviare il server

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

Per avviare il client

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

-1
  • docker run -e MYSQL_ROOT_PASSWORD = passare --name sql-db -p 3306: 3306 mysql

  • docker exec -it sql-db bash

  • mysql -u root -p


che terminerà conERROR 1524 (HY000): Plugin 'unix_socket' is not loaded
Enerccio

@Enerccio Potresti riprovare?
Ajay Singh

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.