Connectez-vous à mysql dans un conteneur docker depuis l'hôte


109

(C'est probablement une question stupide en raison de ma connaissance limitée de Docker ou de l'administration mysql, mais comme j'ai passé une soirée entière sur ce problème, j'ose le poser.)

En un mot

Je veux exécuter mysql dans un conteneur docker et me connecter à celui-ci depuis mon hôte. Jusqu'à présent, le meilleur que j'ai réalisé est:

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

Plus de détails

J'utilise ce qui suit 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

Dans le répertoire où se trouve ce fichier, je peux créer avec succès l'image et l'exécuter avec:

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

Lorsque je m'attache à l'image, cela semble fonctionner très 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.
[...]

Cependant, je n'ai pas beaucoup de succès de la part de l'hôte:

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

Encore plus de détails

  • J'ai vu qu'il y a une question qui ressemble à la mienne . Cependant, ce n'est pas pareil (et il n'a pas de réponse de toute façon)
    • J'ai vu qu'il y a des images dédiées à mysql , mais je n'ai pas eu plus de succès avec elles
    • Je grep -vpeux me sentir bizarre. Certes, il existe peut-être un moyen plus propre de le faire. Mais lorsque j'attache mon image, je peux observer qu'elle a réellement fonctionné comme prévu (c'est-à-dire supprimée bind-address). Et je peux voir dans le conteneur /var/log/mysql/error.log:

Nom d'hôte du serveur (adresse de liaison): '0.0.0.0'; port: 3306 - '0.0.0.0' se résout en '0.0.0.0'; Socket serveur créé sur IP: '0.0.0.0'.


1
Probablement pas si stupide. Je suis tombé dessus pour la dixième fois maintenant et j'ai finalement eu le temps de l'essayer à la maison.
kiltek

Réponses:


171

Si votre hôte Docker MySQL fonctionne correctement, vous pouvez vous y connecter à partir de la machine locale, mais vous devez spécifier l'hôte, le port et le protocole comme ceci:

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

Remplacez 3306 par le numéro de port que vous avez transféré du conteneur Docker (dans votre cas, ce sera 12345).

Étant donné que vous exécutez MySQL dans le conteneur Docker, le socket n'est pas disponible et vous devez vous connecter via TCP. La définition de "--protocol" dans la commande mysql changera cela.


1
Pouvez-vous clarifier pourquoi le socket mysql n'est pas disponible? Votre commande fonctionne, mais je me demande s'il existe un moyen de monter le socket mysql sur l'hôte à partir du conteneur.
Lucas

9
Je ne suis pas un expert en communication Unix, mais d'après ce que je comprends, socket est une connexion représentée sous forme de fichier. Étant donné que le fichier socket n'est pas partagé entre le conteneur Docker et la machine hôte, le client MySQL ne peut pas en utiliser un depuis l'intérieur du conteneur Docker. Pour vous connecter au serveur MySQL à l'intérieur du conteneur Docker à partir de la machine hôte, vous pouvez: 1. Configurer le serveur MySQL pour qu'il place le socket à l'endroit spécifié --socket=/var/run/mysqld/mysqld.sock2. Monter ce fichier en dehors du conteneur Docker 3. Spécifier le chemin du socket dans le client MySQL avec--socket=/host/mysql.sock
maniekq

@maniekq Super commentaire! Mais avez-vous vérifié vos trois possibilités? Fonctionnent-ils tous vraiment?
Andru

7
Après avoir longtemps lutté, j'ai trouvé cette réponse en or, --protocol=tcpenfin fait fonctionner la connexion. Merci @maniekq pour la belle réponse et votre explication sur les sockets via votre commentaire!
panepeter

1
Cela ne devrait pas être la réponse acceptée, car il déclare explicitement qu'il n'a aucune idée de la communication de fichiers UNIX.
kiltek

50

Si vous utilisez "127.0.0.1" au lieu de localhost, mysql utilisera la méthode tcp et vous devriez pouvoir connecter le conteneur avec:

mysql -h 127.0.0.1 -P 3306 -u root

4
Je peux vérifier qu'une fois que j'ai changé localhost en 127.0.0.1 et supprimé l'indicateur de protocole, cela a fonctionné de la même manière
Craig Wayne

2
Je pense que c'est la meilleure et courte réponse;)
rezam

1
Peut-être court mais ce n'est pas la réponse, étant donné que TCP est la méthode la plus lente pour communiquer avec mysql. (plus de processeur et une latence plus élevée)
John

1
@John tu as raison, c'est plus lent mais ça existe. Bien sûr, vous pouvez partager /var/run/mysqld/mysqld.sock entre l'hôte et le conteneur.
Vasili Pascal

2
C'est ce que je recommanderais pour tout DB de service plus élevé. c'est aussi simple que "-v socketfile.sock" puis mysql --socket /path/file.sock sans polluer la pile tcp / ip.
John

27

Je recommande de vérifier docker-compose. Voici comment cela fonctionnerait:

Créez un fichier nommé, docker-compose.yml qui ressemble à ceci:

version: '2'

services:

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

Ensuite, exécutez:

$ docker-compose up

Remarques:

Maintenant, vous pouvez accéder à la console mysql ainsi:

$ mysql -P 8083 --protocol = tcp -u racine -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>

Remarques:

  • Vous pouvez passer l'indicateur -d pour exécuter le conteneur mysql / mariadb en mode détaché / arrière-plan.

  • Le mot de passe est "wp" qui est défini dans le fichier docker-compose.yml.

  • Même conseil que maniekq mais exemple complet avec docker-compose.


3
--protocol=tcptout réparé pour moi. Je vous remercie!
Charlie L

Merci pour cette réponse, j'ai eu le même problème que dans le sujet mais après avoir utilisé --protocol = tcp, il a été corrigé. Je pensais que quelque chose n'allait pas avec le réseau docker.
jiriki

16

La méthode simple consiste à partager le socket mysql unix avec la machine hôte. Puis connectez via la prise

Pas:

  • Créez un dossier partagé pour la machine hôte, par exemple: mkdir /host
  • Exécuter le conteneur Docker avec l'option de montage de volume docker run -it -v /host:/shared <mysql image> .
  • Puis changez le fichier de configuration mysql /etc/my.cnf et changez l'entrée de socket dans le fichier ensocket=/shared/mysql.sock
  • Redémarrez le service MySQL service mysql restartdans le docker
  • Enfin, connectez-vous au serveur MySQL depuis l'hôte via le socket mysql -u root --socket=/host/mysql.sock. Si le mot de passe utilise l'option -p

1
Devez-vous faire cela si le client MySQL est dans un autre conteneur?
Stephane

Je ne sais pas ça. J'ai opté pour cette méthode car la méthode de port tcp-ip ne fonctionnait pas pour moi. Si vous utilisez deux conteneurs pour le serveur et le client, vous pouvez partager un répertoire commun aux deux conteneurs et utiliser le socket Unix pour vous connecter à MySQL.
Jobin

1
La réponse à ma question est non lorsque j'utilise docker-compose avec un lien sur les conteneurs.
Stephane

9

si vous exécutez docker sous docker-machine?

exécuter pour obtenir ip:

docker-machine ip <machine>

renvoie l'adresse IP de la machine et essayez de connecter mysql:

mysql -h<docker-machine-ip>

Résolu dans Docker-Toolbox :) Merci beaucoup.
Vuong

5

Je fais cela en exécutant un conteneur docker temporaire sur mon serveur afin de ne pas avoir à m'inquiéter de ce qui est installé sur mon hôte. Tout d'abord, je définis ce dont j'ai besoin (que vous devez modifier selon vos besoins):

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

Je crée toujours un nouveau réseau docker dont tous les autres conteneurs auront besoin:

docker network create --driver bridge $DB_DOCKER_NETWORK

Démarrez un serveur de base de données mySQL:

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

Capturer l'adresse IP du nouveau conteneur de serveur

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

Ouvrez une interface de ligne de commande vers le serveur:

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"

Ce dernier conteneur se supprimera lorsque vous quitterez l'interface mySQL, tandis que le serveur continuera de fonctionner. Vous pouvez également partager un volume entre le serveur et l'hôte pour faciliter l'importation de données ou de scripts. J'espère que cela t'aides!


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

N'oubliez pas de modifier l'utilisateur, le port et l'hôte afin qu'ils correspondent à vos configurations. L'indicateur -p est requis si l'utilisateur de votre base de données est configuré avec un mot de passe


2

Pour la conversion, vous pouvez créer un ~/.my.cnffichier dans l'hôte:

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

Ensuite, la prochaine fois, lancez simplement le mysqlclient mysql pour ouvrir la connexion.


1

J'ai pu connecter mon sql server5.7 en cours d'exécution sur mon hôte en utilisant la commande ci-dessous: mysql -h 10.10.1.7 -P 3307 --protocol = tcp -u root -p où l'adresse IP donnée est mon adresse IP d'hôte et 3307 est le port forwaded dans mysql docker .Après avoir entré la commande, tapez le mot de passe pour myql.that is it.Maintenant, vous êtes connecté au conteneur de docker mysql depuis votre machine hôte


0

exécuter la commande suivante pour exécuter le conteneur

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

exécutez cette commande pour obtenir la base de données mysql sur la machine hôte

mysql -h 127.0.0.1 -P 8306 -uroot  -pPASS

dans ton cas c'est

mysql -h 127.0.0.1 -P 12345 -uroot  -pPASS

Cela ne fonctionne que si vous utilisez 127.0.0.1 comme adresse. Si vous utilisez l'adresse non locale de l'hôte, vous devez ajouter l' --protocol=tcpindicateur comme décrit dans plusieurs autres commentaires / réponses. Dans mon cas, c'était très déroutant car j'avais également une instance mysql locale non dockerisée. Par défaut, même lorsque le port est spécifié, même si le port est incorrect, la commande 'mysql' se connectera via le fichier socket à l'instance locale.
Riche le

@Rich alors qu'avez-vous fait pour résoudre ce problème? Même si j'ai une configuration similaire, un MySql s'exécutant sur l'hôte et un autre dans le conteneur Docker.
NITHIN RAJ T le

@NITHINRAJT il y a 2 façons d'accomplir cela APRÈS vous être assuré que votre instance de docker n'écoute pas sur le même port (par exemple, comme dans cette réponse, 8306). (1) Essayez cette réponse, celle que nous commentons (par exemple, connexion à 127.0.0.1. (2) Essayez la réponse suivante - mysql -u root -P <EXPOSED_DOCKER_PORT_HERE> -h <YOUR_HOST_IP_ADDRESS_HERE> --protocol=tcp -p. L'indicateur, --protocol=tcpest la clé pour que cela fonctionne.
Riche


0

D'ACCORD. J'ai finalement résolu ce problème. Voici ma solution utilisée dans https://sqlflow.org/sqlflow .

La solution complète

Pour rendre la démo autonome, j'ai déplacé tout le code nécessaire vers https://github.com/wangkuiyi/mysql-server-in-docker .

La clé de la solution

Je n'utilise pas l'image officielle sur DockerHub.com https://hub.docker.com/r/mysql/mysql-server . Au lieu de cela, j'ai créé le mien en installant MySQL sur Ubuntu 18.04. Cette approche me donne la chance de démarrer mysqld et de le lier à 0.0.0.0 (toutes les adresses IP) .

Pour plus de détails, veuillez vous référer à ces lignes dans mon dépôt 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

Pour vérifier ma solution

  1. Git clone le référentiel susmentionné.
    git clone https://github.com/wangkuiyi/mysql-server-in-docker
    cd mysql-server-in-docker
  2. Construire l'image Docker du serveur MySQL
    docker build -t mysql:yi .
  3. Démarrer le serveur MySQL dans un conteneur
    docker run --rm -d -p 23306:3306 mysql:yi
  4. Installez le client MySQL sur l'hôte, sinon encore. J'utilise Ubuntu 18.04 sur l'hôte (ma station de travail), donc j'utilise apt-get.
    sudo apt-get install -y mysql-client
  5. Connectez-vous de l'hôte au serveur MySQL exécuté dans le conteneur.
    mysql --host 127.0.0.1 --port 23306 --user root -proot

Se connecter à partir d'un autre conteneur sur le même hôte

Nous pouvons exécuter le client MySQL à partir d'un autre conteneur (sur le même hôte).

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

Se connecter depuis un autre hôte

Sur mon iMac, j'installe le client MySQL à l'aide de Homebrew.

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

Ensuite, je peux accéder à l'hôte Ubuntu ci-dessus (192.168.1.22).

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

Se connecter à partir d'un conteneur s'exécutant sur un autre hôte

Je peux même exécuter un client MySQL dans un conteneur fonctionnant sur l'iMac pour me connecter au serveur MySQL dans un conteneur sur mon poste de travail Ubuntu.

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

Un cas spécial

Dans le cas où nous exécutons le client et le serveur MySQL dans des conteneurs séparés s'exécutant sur le même hôte - cela peut se produire lorsque nous mettons en place un CI, nous n'avons pas besoin de créer notre propre image Docker de serveur MySQL. Au lieu de cela, nous pouvons utiliser le--net=container:mysql_server_container_name lorsque nous exécutons le conteneur client.

Pour démarrer le serveur

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

Pour démarrer le 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 = pass --name sql-db -p 3306: 3306 mysql

  • docker exec -it sql-db bash

  • mysql -u racine -p


qui se terminera parERROR 1524 (HY000): Plugin 'unix_socket' is not loaded
Enerccio

@Enerccio Pouvez-vous réessayer?
Ajay Singh

-5

changez "localhost" en votre véritable adresse IP con
car c'est en mysql_connect ()

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.