Підключіться до mysql в докер-контейнері від хоста


109

(Це, мабуть, німецьке питання через мої обмежені знання з адміністрацією Докера чи mysql, але оскільки я цілий вечір провів цю проблему, я смію її задати.)

Коротко

Я хочу запустити mysql в докерному контейнері і підключитися до нього від свого хоста. Поки що найкраще я досяг:

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

Детальніше

Я використовую наступне 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

У каталозі, де є цей файл, я можу успішно скласти зображення та запустити його:

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

Коли я додаю зображення, воно, здається, працює просто:

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

Однак у мене не так багато успіху від господаря:

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

Ще більше деталей

  • Я бачив, що є питання, схоже на моє . Однак це не те саме (і відповіді все одно немає)
    • Я бачив, що є зображення, присвячені mysql , але я не мав більше успіху з ними
    • Моя grep -vможе відчувати себе дивно. Справді, може бути більш чистий спосіб зробити це. Але коли я додаю своє зображення, я можу спостерігати, як воно справді працювало так, як очікувалося (тобто: видалено bind-address). І я бачу в контейнері /var/log/mysql/error.log:

Ім'я хоста сервера (bind-address): '0.0.0.0'; порт: 3306 - '0.0.0.0' дозволено до '0.0.0.0'; Серверний сокет, створений на IP: '0.0.0.0'.


1
Напевно, не такий німий. Я натрапив на це вже в 10-й раз і нарешті отримав час спробувати це вдома.
kiltek

Відповіді:


171

Якщо ваш хокер Docker MySQL працює правильно, ви можете підключитися до нього з локальної машини, але вам слід вказати хост, порт і протокол, як це:

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

Змініть 3306 на номер порту, який ви переслали з контейнера Docker (у вашому випадку це буде 12345).

Оскільки ви використовуєте MySQL всередині контейнера Docker, сокет недоступний, і вам потрібно підключитися через TCP. Встановлення "--protocol" в команді mysql змінить це.


1
Чи можете ви уточнити, чому розетка mysql недоступна? Ваша команда працює, але мені цікаво, чи є спосіб встановити MySQL-сокет на хост з контейнера.
Лукас

9
Я не фахівець у галузі комунікації Unix, але з того, що я розумію, сокет - це з'єднання, представлене як файл. Оскільки файл сокета не поділяється між контейнером Docker і хост-машиною, клієнт MySQL не може використовувати його зсередини контейнера Docker. Для підключення до MySQL-сервера всередині контейнера Docker від хост-машини ви можете: 1. Встановити MySQL-сервер розмістити сокет у вказаному місці --socket=/var/run/mysqld/mysqld.sock2. Встановити цей файл поза контейнером Docker 3. Вкажіть шлях до сокета в клієнті MySQL за допомогою--socket=/host/mysql.sock
maniekq

@maniekq Чудовий коментар! Але ви перевірили всі свої три можливості? Вони справді працюють?
Андру

7
Після довгої боротьби я знайшов цю золоту відповідь, --protocol=tcpнарешті змусив зв’язок працювати. Дякую @maniekq і за гарну відповідь, і за ваше пояснення на розетках через ваш коментар!
панепетер

1
Це не має бути прийнятою відповіддю, оскільки він прямо заявляє, що не має уявлення про зв’язок файлів UNIX.
kiltek

50

Якщо ви використовуєте "127.0.0.1" замість localhost mysql, буде використовувати tcp метод, і ви повинні мати можливість з'єднати контейнер з:

mysql -h 127.0.0.1 -P 3306 -u root

4
Я можу перевірити, що як тільки я змінив localhost на 127.0.0.1 і видалив прапор протоколу, він працював так само
Крейг Уейн

2
Я думаю, що це коротка і найкраща відповідь;)
rezam

1
Може бути коротким, але це не відповідь, враховуючи, що TCP - це більш повільний метод спілкування з mysql. (більше процесора та більша затримка)
Іван,

1
@John ви праві, це повільніше, але він існує. Звичайно, ви можете поділитись /var/run/mysqld/mysqld.sock між хостом і контейнером.
Василь Паскаль

2
Ось що я б рекомендував для будь-яких БД з вищими обов'язками. це так просто, як "-v socketfile.sock", а потім mysql --socket /path/file.sock, не забруднюючи стек tcp / ip.
Іван

27

Я рекомендую перевірити докер-композицію. Ось як це буде працювати:

Створіть файл з назвою docker-compose.yml, який виглядає приблизно так:

version: '2'

services:

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

Далі, запустіть:

$ docker-скласти

Примітки:

Тепер ви можете отримати доступ до консолі mysql таким чином:

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

Примітки:

  • Ви можете передати прапор -d, щоб запустити контейнер mysql / mariadb у відключеному / фоновому режимі.

  • Пароль - "wp", який визначається у файлі docker-compose.yml.

  • Така сама порада, як maniekq, але повний приклад із докер-композитом.


3
--protocol=tcpвсе зафіксував для мене. Дякую!
Чарлі Л

Дякую за цю відповідь, у мене була така ж проблема, як у темі, але після використання --protocol = tcp це виправлено. Я думав, що з докерською мережею щось не так.
jiriki

16

Найпростіший метод - це спільний доступ до socket mysql unix для хост-машини. Потім підключіть через розетку

Кроки:

  • Створіть спільну папку для хост-машини, наприклад: mkdir /host
  • Запустіть докер-контейнер з опцією кріплення гучності docker run -it -v /host:/shared <mysql image> .
  • Потім змініть файл конфігурації mysql /etc/my.cnf і змініть запис сокета у файлі наsocket=/shared/mysql.sock
  • Перезапустіть службу MySQL service mysql restartу докері
  • Нарешті підключіться до сервера MySQL від хоста через сокет mysql -u root --socket=/host/mysql.sock. Якщо пароль використовувати -p варіант

1
Чи потрібно це робити, якщо клієнт MySQL знаходиться в іншому контейнері?
Стефан

Я цього не знаю. Я вибрав цей метод, оскільки метод порту tcp-ip не працював для мене. Якщо ви використовуєте два контейнери для сервера та клієнта, ви можете поділитися загальним каталогом на обидва контейнери і використовувати сокет Unix для підключення до MySQL.
Джобін

1
Відповідь на моє запитання - ні, коли я використовую docker-compose із посиланням на контейнери.
Стефан

9

якщо ви працюєте докер під докер-машиною?

виконати, щоб отримати ip:

docker-machine ip <machine>

повертає ip для машини та спробуйте підключити mysql:

mysql -h<docker-machine-ip>

Вирішено в Docker-Toolbox :) Дуже дякую.
Вуонг

5

Я роблю це, запускаючи тимчасовий контейнер докера проти мого сервера, тому мені не потрібно турбуватися про те, що встановлено на моєму хості. Спочатку я визначаю, що мені потрібно (що ви повинні змінити для своїх цілей):

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

Я завжди створюю нову докерську мережу, яка потрібна будь-яким іншим контейнерам:

docker network create --driver bridge $DB_DOCKER_NETWORK

Запустіть сервер баз даних mySQL:

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

Захоплення IP-адреси нового контейнера сервера

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

Відкрийте сервер інтерфейсу командного рядка:

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"

Цей останній контейнер видалить себе, коли ви вийдете з інтерфейсу mySQL, поки сервер продовжить працювати. Ви також можете поділити обсяг між сервером і хостом, щоб полегшити імпорт даних або сценаріїв. Сподіваюся, це допомагає!


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

Не забудьте змінити користувача, порт і хост так, щоб він відповідав вашим конфігураціям. Прапор -p потрібен, якщо користувач вашої бази даних налаштований паролем


2

Для перетворення , ви можете створити ~/.my.cnfфайл у хості:

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

Потім наступного разу просто запустіть mysqlдля клієнта mysql, щоб відкрити з'єднання.


1

Мені вдалося підключити свій сервер sql5.7, який працює на моєму хості, використовуючи команду нижче: mysql -h 10.10.1.7 -P 3307 --protocol = tcp -u root -p, де ip наданий мій хост ip, а 3307 - це Порт перейшов у докер mysql. Після введення команди введіть пароль для myql. Це так. Тепер ви підключили контейнер докер-mysql від вашого hostmachine


0

запустити наступну команду для запуску контейнера

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

запустіть цю команду, щоб отримати mysql db в хост-машині

mysql -h 127.0.0.1 -P 8306 -uroot  -pPASS

у вашому випадку це так

mysql -h 127.0.0.1 -P 12345 -uroot  -pPASS

Це працює лише в тому випадку, якщо ви використовуєте в якості адреси 127.0.0.1. Якщо ви використовуєте не локальну адресу хоста, вам потрібно додати --protocol=tcpпрапор, як описано в кількох інших коментарях / відповідях. У моєму випадку це було дуже заплутано, оскільки в мене також працював локальний, недокеркізований, екземпляр mysql. За замовчуванням, навіть якщо порт вказаний, навіть якщо порт невірний, команда 'mysql' підключиться через файл socket до локального екземпляра.
Багатий

@Rich, що ти зробив, щоб вирішити цю проблему? Навіть у мене подібні налаштування, один MySql працює на хості та інший у контейнері docker.
NITHIN RAJ T

@NITHINRAJT є два способи досягти цього ПІСЛЯ ви переконаєтесь, що ваш екземпляр докера не слухає той самий порт (наприклад, як у цій відповіді, 8306). (1) Спробуйте цю відповідь, таку, яку ми коментуємо (наприклад, підключення до 127.0.0.1. (2) Спробуйте наступну відповідь - mysql -u root -P <EXPOSED_DOCKER_PORT_HERE> -h <YOUR_HOST_IP_ADDRESS_HERE> --protocol=tcp -p. Прапор --protocol=tcp- це ключ до створення цієї роботи.
Багатий


0

ГАРАЗД. Нарешті я вирішив цю проблему. Тут випливає моє рішення, яке використовується на https://sqlflow.org/sqlflow .

Повне рішення

Щоб зробити демонстрацію самодостатньою, я перемістив весь необхідний код на https://github.com/wangkuiyi/mysql-server-in-docker .

Ключ до рішення

Я не використовую офіційний образ на DockerHub.com https://hub.docker.com/r/mysql/mysql-server . Натомість я зробив своє, встановивши MySQL на Ubuntu 18.04. Такий підхід дає мені можливість запустити mysqld і прив’язати його до 0,0.0.0 (всі IP-адреси) .

Для детальної інформації зверніться до цих рядків у моєму репортажі 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

Щоб перевірити моє рішення

  1. Гіт клонував вищезгадане репо.
    git clone https://github.com/wangkuiyi/mysql-server-in-docker
    cd mysql-server-in-docker
  2. Створіть зображення Docker на сервері MySQL
    docker build -t mysql:yi .
  3. Запустіть MySQL-сервер у контейнері
    docker run --rm -d -p 23306:3306 mysql:yi
  4. Встановіть клієнт MySQL на хост, якщо ще немає. Я працюю на Ubuntu 18.04 на хості (моя робоча станція), тому я використовую apt-get.
    sudo apt-get install -y mysql-client
  5. Підключіться з хоста до сервера MySQL, який працює в контейнері.
    mysql --host 127.0.0.1 --port 23306 --user root -proot

Підключіться з іншого контейнера на тому ж хості

Ми можемо запустити клієнт MySQL навіть з іншого контейнера (на тому ж хості).

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

Підключення від іншого хоста

На своєму iMac я встановлюю клієнт MySQL за допомогою Homebrew.

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

Тоді я можу отримати доступ до вищевказаного хоста Ubuntu (192.168.1.22).

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

Підключіться з контейнера, який працює на іншому хості

Я навіть можу запустити клієнт MySQL у контейнері, що працює на iMac, щоб підключитися до сервера MySQL в контейнері на моїй робочій станції Ubuntu.

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

Особливий випадок

У випадку, якщо ми запускаємо клієнт і сервер MySQL в окремих контейнерах, що працюють на одному хості - це може статися, коли ми встановлюємо CI, нам не потрібно будувати власний образ Docker сервера MySQL. Натомість ми можемо використовувати те, --net=container:mysql_server_container_nameколи ми запускаємо клієнтський контейнер.

Для запуску сервера

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

Для запуску клієнта

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 - ім'я sql-db -p 3306: 3306 mysql

  • docker exec -it sql-db bash

  • mysql -u корінь -p


це закінчитьсяERROR 1524 (HY000): Plugin 'unix_socket' is not loaded
Enerccio

@Enerccio Чи можете ви спробувати ще раз?
Аджай Сінгх

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.