Stellen Sie vom Host aus eine Verbindung zu MySQL in einem Docker-Container her


108

(Es ist wahrscheinlich eine dumme Frage aufgrund meiner begrenzten Kenntnisse mit Docker oder der MySQL-Administration, aber da ich einen ganzen Abend mit diesem Thema verbracht habe, wage ich es, sie zu stellen.)

In einer Nussschale

Ich möchte MySQL in einem Docker-Container ausführen und von meinem Host aus eine Verbindung herstellen. Das Beste, was ich bisher erreicht habe, ist:

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

Mehr Details

Ich benutze folgendes 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

In dem Verzeichnis, in dem sich diese Datei befindet, kann ich das Image erfolgreich erstellen und ausführen mit:

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

Wenn ich das Bild anhänge, scheint es gut zu funktionieren:

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

Allerdings habe ich vom Gastgeber nicht so viel Erfolg:

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

Noch mehr Details

  • Ich habe gesehen, dass es eine Frage gibt, die meiner ähnelt . Es ist jedoch nicht dasselbe (und es gibt sowieso keine Antworten)
    • Ich habe gesehen, dass es Bilder gibt , die MySQL gewidmet sind , aber ich hatte keinen größeren Erfolg damit
    • Ich grep -vmag mich komisch fühlen. Zugegeben, es kann einen saubereren Weg geben, dies zu tun. Aber wenn ich mein Bild anhänge, kann ich beobachten, dass es tatsächlich wie erwartet funktioniert hat (dh: das entfernt bind-address). Und ich kann im Container sehen /var/log/mysql/error.log:

Server-Hostname (Bindungsadresse): '0.0.0.0'; Port: 3306 - '0.0.0.0' wird in '0.0.0.0' aufgelöst; Auf IP erstellter Server-Socket: '0.0.0.0'.


1
Wahrscheinlich nicht so dumm. Ich bin jetzt zum 10. Mal darauf gestoßen und habe endlich die Zeit bekommen, es zu Hause auszuprobieren.
Kiltek

Antworten:


171

Wenn Ihr Docker MySQL-Host ordnungsgemäß ausgeführt wird, können Sie von einem lokalen Computer aus eine Verbindung herstellen. Sie sollten jedoch Host, Port und Protokoll wie folgt angeben:

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

Ändern Sie 3306 in die Portnummer, die Sie vom Docker-Container weitergeleitet haben (in Ihrem Fall 12345).

Da Sie MySQL im Docker-Container ausführen, ist kein Socket verfügbar und Sie müssen eine Verbindung über TCP herstellen. Das Setzen von "--protocol" im Befehl mysql ändert dies.


1
Können Sie erklären, warum der MySQL-Socket nicht verfügbar ist? Ihr Befehl funktioniert, aber ich frage mich, ob es eine Möglichkeit gibt, den MySQL-Socket vom Container aus an den Host zu hängen.
Lucas

9
Ich bin kein Experte für Unix-Kommunikation, aber meines Wissens ist Socket eine Verbindung, die als Datei dargestellt wird. Da die Socket-Datei nicht zwischen dem Docker-Container und dem Host-Computer gemeinsam genutzt wird, kann der MySQL-Client keine Datei innerhalb des Docker-Containers verwenden. So stellen Sie vom Host-Computer aus eine Verbindung zum MySQL-Server im Docker-Container her: 1. Stellen Sie den MySQL-Server so ein, dass der Socket an der angegebenen Stelle abgelegt wird. --socket=/var/run/mysqld/mysqld.sock2. --socket=/host/mysql.sock
Hängen Sie

@maniekq Großartiger Kommentar! Aber haben Sie alle Ihre drei Möglichkeiten überprüft? Arbeiten sie alle wirklich?
Andru

7
Nachdem ich lange gekämpft hatte, fand ich diese goldene Antwort und --protocol=tcpließ die Verbindung endlich funktionieren. Vielen Dank an @maniekq für die nette Antwort und Ihre Erklärung zu den Steckdosen über Ihren Kommentar!
Panepeter

1
Dies sollte nicht die akzeptierte Antwort sein, da er ausdrücklich angibt, dass er keine Ahnung von der UNIX-Dateikommunikation hat.
Kiltek

49

Wenn Sie "127.0.0.1" anstelle von localhost verwenden, verwendet mysql die TCP-Methode und Sie sollten in der Lage sein, den Container mit folgenden Verbindungen zu verbinden:

mysql -h 127.0.0.1 -P 3306 -u root

4
Ich kann überprüfen, ob es funktioniert hat, nachdem ich localhost auf 127.0.0.1 geändert und das Protokollflag entfernt habe
Craig Wayne,

2
Ich denke, das ist die kurze und beste Antwort;)
Rezam

1
Könnte kurz sein, ist aber nicht die Antwort, da TCP die langsamere Methode zur Kommunikation mit MySQL ist. (mehr CPU und höhere Latenz)
John

1
@ John du hast recht, es ist langsamer, aber es existiert. Natürlich können Sie /var/run/mysqld/mysqld.sock zwischen Host und Container freigeben.
Vasili Pascal

2
Das würde ich jedem DB mit höherer Leistung empfehlen. Es ist so einfach wie "-v socketfile.sock" und dann mysql --socket /path/file.sock, ohne den tcp / ip-Stack zu verschmutzen.
John

27

Ich empfehle Docker-Compose. So würde das funktionieren:

Erstellen Sie eine Datei mit dem Namen docker-compose.yml, die folgendermaßen aussieht:

version: '2'

services:

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

Führen Sie als Nächstes Folgendes aus:

$ docker-compose up

Anmerkungen:

Jetzt können Sie folgendermaßen auf die MySQL-Konsole zugreifen:

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

Anmerkungen:

  • Sie können das Flag -d übergeben, um den mysql / mariadb-Container im getrennten / Hintergrundmodus auszuführen.

  • Das Passwort lautet "wp" und ist in der Datei docker-compose.yml definiert.

  • Gleicher Rat wie maniekq, aber vollständiges Beispiel mit Docker-Compose.


3
--protocol=tcphat alles für mich repariert. Danke dir!
Charlie L

Vielen Dank für diese Antwort, ich hatte das gleiche Problem wie im Thema, aber nach der Verwendung von --protocol = tcp wurde es behoben. Ich dachte, mit Docker-Netzwerk stimmt etwas nicht.
Jiriki

16

Die einfache Methode besteht darin, den MySQL-Unix-Socket für den Host-Computer freizugeben. Schließen Sie dann über die Steckdose an

Schritte:

  • Erstellen Sie einen freigegebenen Ordner für den Hostcomputer, z. mkdir /host
  • Führen Sie den Docker-Container mit der Option zum Einhängen des Volumes aus docker run -it -v /host:/shared <mysql image>.
  • Ändern Sie dann die MySQL-Konfigurationsdatei /etc/my.cnfund den Socket-Eintrag in der Datei insocket=/shared/mysql.sock
  • Starten Sie den MySQL-Dienst service mysql restartim Docker neu
  • Stellen Sie schließlich über den Socket eine Verbindung zum MySQL-Servver vom Host her her mysql -u root --socket=/host/mysql.sock. Wenn das Passwort verwendet wird, verwenden Sie die Option -p

1
Müssen Sie dies tun, wenn sich der MySQL-Client in einem anderen Container befindet?
Stephane

Das weiß ich nicht. Ich habe mich für diese Methode entschieden, weil die TCP-IP-Port-Methode bei mir nicht funktioniert hat. Wenn Sie zwei Container für Server und Client verwenden, können Sie ein gemeinsames Verzeichnis für beide Container freigeben und mithilfe des Unix-Sockets eine Verbindung zu MySQL herstellen.
Jobin

1
Die Antwort auf meine Frage lautet Nein, wenn ich Docker-Compose mit einem Link auf den Containern verwende.
Stephane

9

Wenn Sie Docker unter Docker-Maschine ausführen?

ausführen, um IP zu erhalten:

docker-machine ip <machine>

Gibt die IP für den Computer zurück und versucht, mysql zu verbinden:

mysql -h<docker-machine-ip>

In Docker-Toolbox gelöst :) Vielen Dank.
Vuong

5

Dazu führe ich einen temporären Docker-Container auf meinem Server aus, damit ich mir keine Gedanken darüber machen muss, was auf meinem Host installiert ist. Zuerst definiere ich, was ich brauche (was Sie für Ihre Zwecke ändern sollten):

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

Ich erstelle immer ein neues Docker-Netzwerk, das alle anderen Container benötigen:

docker network create --driver bridge $DB_DOCKER_NETWORK

Starten Sie einen mySQL-Datenbankserver:

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

Erfassen Sie die IP-Adresse des neuen Servercontainers

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

Öffnen Sie eine Befehlszeilenschnittstelle zum 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"

Dieser letzte Container entfernt sich selbst, wenn Sie die mySQL-Schnittstelle verlassen, während der Server weiter ausgeführt wird. Sie können auch ein Volume zwischen Server und Host freigeben, um den Import von Daten oder Skripten zu vereinfachen. Hoffe das hilft!


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

Denken Sie daran, Benutzer, Port und Host so zu ändern, dass sie Ihren Konfigurationen entsprechen. Das Flag -p ist erforderlich, wenn Ihr Datenbankbenutzer mit einem Kennwort konfiguriert ist


2

Für die Konvertierung , können Sie eine ~/.my.cnfDatei im Host erstellen :

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

Führen Sie das nächste Mal einfach den mysqlMySQL-Client aus, um die Verbindung herzustellen.


1

Ich konnte meinen SQL Server5.7, der auf meinem Host ausgeführt wird, mit dem folgenden Befehl verbinden: mysql -h 10.10.1.7 -P 3307 --protocol = tcp -u root -p wobei die angegebene IP meine Host-IP und 3307 die ist Port in MySQL Docker forwaded. Nachdem Sie den Befehl eingegeben haben, geben Sie das Passwort für MyQL ein. Das ist es. Jetzt sind Sie mit dem MySQL Docker Container von Ihrer Host-Maschine verbunden


0

Führen Sie den folgenden Befehl aus, um den Container auszuführen

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

Führen Sie diesen Befehl aus, um die MySQL-Datenbank auf dem Host-Computer abzurufen

mysql -h 127.0.0.1 -P 8306 -uroot  -pPASS

in deinem Fall ist es

mysql -h 127.0.0.1 -P 12345 -uroot  -pPASS

Dies funktioniert nur, wenn Sie 127.0.0.1 als Adresse verwenden. Wenn Sie die nicht lokale Adresse des Hosts verwenden, müssen Sie das --protocol=tcpFlag hinzufügen, wie in mehreren anderen Kommentaren / Antworten beschrieben. In meinem Fall war es besonders verwirrend, weil auch eine lokale, nicht dockerisierte MySQL-Instanz ausgeführt wurde. Selbst wenn der Port angegeben ist, stellt der Befehl 'mysql' standardmäßig über die Socket-Datei eine Verbindung zur lokalen Instanz her, auch wenn der Port angegeben ist.
Rich

@Rich also was hast du getan, um dieses Problem zu lösen? Sogar ich habe ein ähnliches Setup, eine MySQL läuft auf dem Host und eine andere im Docker-Container.
NITHIN RAJ T

@NITHINRAJT Es gibt zwei Möglichkeiten, dies zu erreichen, nachdem Sie sichergestellt haben, dass Ihre Docker-Instanz nicht denselben Port überwacht (z. B. wie in dieser Antwort 8306). (1) Versuchen Sie diese Antwort, die wir kommentieren (z. B. Verbindung zu 127.0.0.1 herstellen.) (2) Versuchen Sie die nächste Antwort mysql -u root -P <EXPOSED_DOCKER_PORT_HERE> -h <YOUR_HOST_IP_ADDRESS_HERE> --protocol=tcp -p. Die Flagge --protocol=tcpist der Schlüssel, damit dies funktioniert.
Rich


0

OK. Ich habe dieses Problem endlich gelöst. Hier folgt meine in https://sqlflow.org/sqlflow verwendete Lösung .

Die Komplettlösung

Um die Demo in sich geschlossen zu machen, habe ich den gesamten erforderlichen Code nach https://github.com/wangkuiyi/mysql-server-in-docker verschoben .

Der Schlüssel zur Lösung

Ich verwende das offizielle Bild auf DockerHub.com https://hub.docker.com/r/mysql/mysql-server nicht . Stattdessen habe ich es mir selbst gemacht, indem ich MySQL unter Ubuntu 18.04 installiert habe. Dieser Ansatz gibt mir die Möglichkeit, mysqld zu starten und an 0.0.0.0 (alle IPs) zu binden. .

Einzelheiten finden Sie in meinen Zeilen in meinem GitHub-Repo.

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

So überprüfen Sie meine Lösung

  1. Git klonen das oben genannte Repo.
    git clone https://github.com/wangkuiyi/mysql-server-in-docker
    cd mysql-server-in-docker
  2. Erstellen Sie das MySQL Server Docker-Image
    docker build -t mysql:yi .
  3. Starten Sie den MySQL-Server in einem Container
    docker run --rm -d -p 23306:3306 mysql:yi
  4. Installieren Sie den MySQL-Client auf dem Host, falls noch nicht geschehen. Ich verwende Ubuntu 18.04 auf dem Host (meiner Workstation), also benutze ich apt-get.
    sudo apt-get install -y mysql-client
  5. Stellen Sie vom Host aus eine Verbindung zum MySQL-Server her, der im Container ausgeführt wird.
    mysql --host 127.0.0.1 --port 23306 --user root -proot

Stellen Sie eine Verbindung von einem anderen Container auf demselben Host her

Wir können den MySQL-Client sogar von einem anderen Container (auf demselben Host) ausführen.

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

Stellen Sie eine Verbindung von einem anderen Host her

Auf meinem iMac installiere ich den MySQL-Client mit Homebrew.

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

Dann kann ich auf den obigen Ubuntu-Host (192.168.1.22) zugreifen.

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

Stellen Sie eine Verbindung von einem Container her, der auf einem anderen Host ausgeführt wird

Ich kann den MySQL-Client sogar in einem Container ausführen, der auf dem iMac ausgeführt wird, um eine Verbindung zum MySQL-Server in einem Container auf meiner Ubuntu-Workstation herzustellen.

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

Ein Sonderfall

Für den Fall, dass wir MySQL-Client und -Server in separaten Containern ausführen, die auf demselben Host ausgeführt werden. Dies kann passieren, wenn wir ein CI einrichten. Wir müssen kein eigenes MySQL-Server-Docker-Image erstellen. Stattdessen können wir das verwenden, --net=container:mysql_server_container_namewenn wir den Client-Container ausführen.

So starten Sie den Server

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

Client starten

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 = pass --name sql-db -p 3306: 3306 mysql

  • Docker Exec -it SQL-DB Bash

  • mysql -u root -p


das endet mitERROR 1524 (HY000): Plugin 'unix_socket' is not loaded
Enerccio

@Enerccio Könnten Sie es noch einmal versuchen?
Ajay Singh

-5

Ändern Sie "localhost" in Ihre echte Con-IP-Adresse,
da es sich um mysql_connect () handelt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.