Hubungkan ke mysql di kontainer buruh pelabuhan dari host

109

(Ini mungkin pertanyaan bodoh karena pengetahuan saya yang terbatas dengan Docker atau administrasi mysql, tetapi karena saya menghabiskan sepanjang malam untuk masalah ini, saya berani menanyakannya.)

Pendeknya

Saya ingin menjalankan mysql di kontainer buruh pelabuhan dan menghubungkannya dari host saya. Sejauh ini, yang terbaik yang saya capai adalah:

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

Keterangan lebih lanjut

Saya menggunakan yang berikut ini 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

Di direktori tempat ada file ini, saya berhasil membuat gambar dan menjalankannya dengan:

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

Saat saya melampirkan ke gambar, tampaknya berfungsi dengan baik:

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

Namun saya tidak begitu sukses dari tuan rumah:

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

Lebih detail lagi

  • Saya telah melihat bahwa ada pertanyaan yang sepertinya milik saya . Namun, itu tidak sama (dan toh tidak ada jawaban)
    • Saya telah melihat bahwa ada gambar yang didedikasikan untuk mysql , tetapi saya tidak lebih berhasil dengan mereka
    • Saya grep -vmungkin merasa aneh. Memang, mungkin ada cara yang lebih bersih untuk melakukannya. Tetapi ketika saya melampirkan gambar saya, saya dapat mengamati bahwa itu benar-benar berfungsi seperti yang diharapkan (yaitu: menghapus bind-address). Dan saya bisa melihat di wadah /var/log/mysql/error.log:

Nama host server (alamat-bind): '0.0.0.0'; port: 3306 - '0.0.0.0' berubah menjadi '0.0.0.0'; Soket server dibuat pada IP: '0.0.0.0'.

gturri
sumber
1
Mungkin tidak sebodoh itu. Saya menemukan ini untuk yang kesepuluh kalinya sekarang dan akhirnya punya waktu untuk mencobanya di rumah.
kiltek

Jawaban:

171

Jika host Docker MySQL Anda berjalan dengan benar, Anda dapat menyambungkannya dari mesin lokal, tetapi Anda harus menentukan host, port, dan protokol seperti ini:

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

Ubah 3306 ke nomor port yang telah Anda teruskan dari kontainer Docker (dalam kasus Anda, ini adalah 12345).

Karena Anda menjalankan MySQL di dalam container Docker, soket tidak tersedia dan Anda harus terhubung melalui TCP. Pengaturan "--protocol" pada perintah mysql akan mengubahnya.

maniekq
sumber
1
Dapatkah Anda menjelaskan mengapa soket mysql tidak tersedia? Perintah Anda berfungsi, tetapi saya bertanya-tanya apakah ada cara untuk memasang soket mysql ke host dari wadah.
Lucas
9
Saya bukan ahli dalam komunikasi Unix, tetapi dari apa yang saya pahami soket adalah koneksi yang direpresentasikan sebagai file. Karena file socket tidak dibagikan antara container Docker dan mesin host, klien MySQL tidak dapat menggunakan salah satu dari dalam container Docker. Untuk terhubung ke server MySQL di dalam kontainer Docker dari mesin host Anda dapat: 1. Mengatur server MySQL untuk meletakkan soket di tempat yang ditentukan --socket=/var/run/mysqld/mysqld.sock2. Pasang file ini di luar wadah Docker 3. Tentukan jalur ke soket di klien MySQL dengan--socket=/host/mysql.sock
maniekq
@maniekq Komentar yang bagus! Tetapi apakah Anda memverifikasi ketiga kemungkinan Anda? Apakah semuanya benar-benar berfungsi?
Andru
7
Setelah perjuangan panjang saya menemukan jawaban emas ini, --protocol=tcpakhirnya membuat koneksi berhasil. Terima kasih @maniekq atas jawaban yang bagus dan penjelasan Anda di soket melalui komentar Anda!
panepeter
1
Ini seharusnya bukan jawaban yang diterima, karena dia secara eksplisit menyatakan bahwa dia tidak tahu tentang komunikasi file UNIX.
kiltek
50

Jika Anda menggunakan "127.0.0.1" daripada localhost, mysql akan menggunakan metode tcp dan Anda dapat menghubungkan container dengan:

mysql -h 127.0.0.1 -P 3306 -u root
Vasili Pascal
sumber
4
Saya dapat memverifikasi bahwa setelah saya mengubah localhost menjadi 127.0.0.1 dan menghapus bendera protokol, itu berfungsi sama
Craig Wayne
2
Saya pikir ini adalah jawaban singkat dan terbaik;)
rezam
1
Mungkin singkat tapi itu bukan jawabannya, mengingat TCP adalah metode yang lebih lambat untuk berkomunikasi dengan mysql. (lebih banyak cpu dan latensi yang lebih tinggi)
Yohanes
1
@ John Anda benar, ini lebih lambat tapi itu ada. Tentu saja Anda dapat membagikan /var/run/mysqld/mysqld.sock antara host dan container.
Vasili Pascal
2
Itulah yang saya rekomendasikan untuk DB tugas yang lebih tinggi. itu sesederhana "-v socketfile.sock" dan kemudian mysql --socket /path/file.sock tanpa mencemari tumpukan tcp / ip.
Yohanes
27

Saya sarankan untuk memeriksa penulisan docker. Begini cara kerjanya:

Buat file bernama, docker-compose.yml yang terlihat seperti ini:

version: '2'

services:

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

Selanjutnya, jalankan:

$ buruh pelabuhan-menulis

Catatan:

Sekarang, Anda dapat mengakses konsol mysql sebagai berikut:

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

Catatan:

  • Anda dapat meneruskan flag -d untuk menjalankan container mysql / mariadb dalam mode detached / background.

  • Kata sandinya adalah "wp" yang didefinisikan dalam file docker-compose.yml.

  • Saran yang sama dengan maniekq tetapi contoh lengkap dengan buruh pelabuhan-menulis.

l3x
sumber
3
--protocol=tcpmemperbaiki segalanya untukku. Terima kasih!
Charlie L
Terima kasih atas jawaban ini, saya memiliki masalah yang sama seperti pada topik tetapi setelah menggunakan --protocol = tcp, itu diperbaiki. Saya pikir ada yang salah dengan jaringan buruh pelabuhan.
jiriki
16

Metode sederhana adalah dengan membagikan soket mysql unix ke mesin host. Kemudian hubungkan melalui soket

Langkah:

  • Buat folder bersama untuk mesin host misalnya: mkdir /host
  • Jalankan kontainer buruh pelabuhan dengan opsi pemasangan volume docker run -it -v /host:/shared <mysql image>.
  • Kemudian ubah file konfigurasi mysql /etc/my.cnfdan ubah entri soket di file menjadisocket=/shared/mysql.sock
  • Mulai ulang layanan MySQL service mysql restartdi buruh pelabuhan
  • Terakhir Hubungkan ke server MySQL dari host melalui soket mysql -u root --socket=/host/mysql.sock. Jika kata sandi gunakan opsi -p
Jobin
sumber
1
Apakah Anda harus melakukan ini jika klien MySQL ada di penampung lain?
Stephane
Saya tidak tahu itu. Saya memilih metode ini karena metode port tcp-ip tidak berfungsi untuk saya. Jika Anda menggunakan dua kontainer untuk server dan klien, Anda dapat berbagi direktori umum ke kedua kontainer dan menggunakan soket Unix untuk terhubung ke MySQL.
Jobin pada
1
Jawaban atas pertanyaan saya adalah tidak saat saya menggunakan docker-compose dengan link di container.
Stephane
9

jika Anda menjalankan buruh pelabuhan di bawah mesin buruh pelabuhan?

jalankan untuk mendapatkan ip:

docker-machine ip <machine>

mengembalikan ip untuk mesin dan mencoba menghubungkan mysql:

mysql -h<docker-machine-ip>
Gerardo Rochín
sumber
Dipecahkan di Docker-Toolbox :) Terima kasih banyak.
Vuong
5

Saya melakukan ini dengan menjalankan kontainer buruh pelabuhan sementara di server saya jadi saya tidak perlu khawatir tentang apa yang diinstal di host saya. Pertama, saya mendefinisikan apa yang saya butuhkan (yang harus Anda modifikasi untuk tujuan Anda):

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

Saya selalu membuat jaringan buruh pelabuhan baru yang akan dibutuhkan oleh wadah lain:

docker network create --driver bridge $DB_DOCKER_NETWORK

Mulai server 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

Tangkap alamat IP dari penampung server baru

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

Buka antarmuka baris perintah ke 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"

Penampung terakhir ini akan menghapus dirinya sendiri saat Anda keluar dari antarmuka mySQL, sementara server akan terus berjalan. Anda juga dapat berbagi volume antara server dan host untuk mempermudah mengimpor data atau skrip. Semoga ini membantu!

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

Ingatlah untuk mengubah pengguna, port dan host agar sesuai dengan konfigurasi Anda. Bendera -p diperlukan jika pengguna database Anda dikonfigurasi dengan kata sandi

Hamfri
sumber
2

Untuk konversi, Anda dapat membuat ~/.my.cnffile di host:

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

Kemudian lain kali jalankan mysqlklien mysql untuk membuka koneksi.

lupguo
sumber
1

Saya dapat menghubungkan server sql5.7 saya yang berjalan di host saya menggunakan perintah di bawah ini: mysql -h 10.10.1.7 -P 3307 --protocol = tcp -u root -p di mana ip yang diberikan adalah ip host saya dan 3307 adalah port forwaded di mysql docker. Setelah memasukkan perintah ketikkan kata sandi untuk myql. itu dia.Sekarang Anda terhubung ke kontainer buruh pelabuhan mysql dari mesin host Anda

Rajesh k
sumber
0

jalankan perintah berikut untuk menjalankan container

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

jalankan perintah ini untuk mendapatkan db mysql di mesin host

mysql -h 127.0.0.1 -P 8306 -uroot  -pPASS

dalam kasusmu itu

mysql -h 127.0.0.1 -P 12345 -uroot  -pPASS
Nitin
sumber
Ini hanya berfungsi jika Anda menggunakan 127.0.0.1 sebagai alamat. Jika Anda menggunakan alamat non-lokal tuan rumah Anda perlu menambahkan --protocol=tcpbendera seperti yang dijelaskan dalam beberapa komentar / jawaban lainnya. Dalam kasus saya, itu sangat membingungkan karena saya memiliki instance mysql lokal, non-docker, dan juga berjalan. Secara default, meskipun port ditentukan, meskipun portnya salah, perintah 'mysql' akan terhubung melalui file socket ke instance lokal.
Kaya
@ Kaya jadi apa yang Anda lakukan untuk memecahkan masalah itu? Bahkan saya memiliki pengaturan serupa, satu MySql berjalan di host dan satu lagi di kontainer buruh pelabuhan.
NITHIN RAJ T
@NITHINRAJT ada 2 cara untuk mencapai ini SETELAH Anda memastikan instance docker Anda tidak mendengarkan pada port yang sama (misalnya, seperti dalam jawaban ini, 8306). (1) Coba jawaban ini, yang kami komentari (mis., Menyambung ke 127.0.0.1. (2) Coba jawaban berikutnya - mysql -u root -P <EXPOSED_DOCKER_PORT_HERE> -h <YOUR_HOST_IP_ADDRESS_HERE> --protocol=tcp -p. Bendera, --protocol=tcpadalah kunci untuk membuat ini berfungsi.
Rich
0

Di terminal Anda, jalankan: docker exec -it container_name /bin/bash Kemudian:mysql

Denis Prescornic
sumber
0

BAIK. Saya akhirnya memecahkan masalah ini. Berikut solusi saya yang digunakan di https://sqlflow.org/sqlflow .

Solusi Lengkap

Untuk membuat demo mandiri, saya memindahkan semua kode yang diperlukan ke https://github.com/wangkuiyi/mysql-server-in-docker .

Kunci Solusi

Saya tidak menggunakan gambar resmi di DockerHub.com https://hub.docker.com/r/mysql/mysql-server . Sebagai gantinya, saya membuatnya sendiri dengan menginstal MySQL di Ubuntu 18.04. Pendekatan ini memberi saya kesempatan untuk memulai mysqld dan mengikatnya ke 0.0.0.0 (semua IP) .

Untuk detailnya, lihat baris ini di repo GitHub saya.

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

Untuk Memverifikasi Solusi Saya

  1. Git mengkloning repo yang disebutkan di atas.
    git clone https://github.com/wangkuiyi/mysql-server-in-docker
    cd mysql-server-in-docker
  2. Buat image Docker server MySQL
    docker build -t mysql:yi .
  3. Mulai server MySQL dalam sebuah wadah
    docker run --rm -d -p 23306:3306 mysql:yi
  4. Instal klien MySQL di host, jika belum. Saya menjalankan Ubuntu 18.04 pada host (workstation saya), jadi saya gunakan apt-get.
    sudo apt-get install -y mysql-client
  5. Hubungkan dari host ke server MySQL yang berjalan di penampung.
    mysql --host 127.0.0.1 --port 23306 --user root -proot

Terhubung dari Penampung Lain di Host yang Sama

Kita dapat menjalankan klien MySQL bahkan dari container lain (di host yang sama).

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

Terhubung dari Host Lain

Di iMac saya, saya menginstal klien MySQL menggunakan Homebrew.

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

Kemudian, saya dapat mengakses host Ubuntu di atas (192.168.1.22).

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

Terhubung dari Penampung yang Berjalan di Host Lain

Saya bahkan dapat menjalankan klien MySQL dalam wadah yang berjalan di iMac untuk terhubung ke server MySQL dalam wadah di workstation Ubuntu saya.

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

Kasus Khusus

Jika kita menjalankan klien dan server MySQL dalam wadah terpisah yang berjalan pada host yang sama - ini bisa terjadi saat kita menyiapkan CI, kita tidak perlu membuat image Docker server MySQL kita sendiri. Sebagai gantinya, kita bisa menggunakan--net=container:mysql_server_container_name saat kita menjalankan wadah klien.

Untuk memulai server

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

Untuk memulai klien

docker run --rm -it --net=container:mysql mysql/mysql-server mysql \
 -h 127.0.0.1 -P 3306 -u root -proot
cxwangyi
sumber
-1
  • docker run -e MYSQL_ROOT_PASSWORD = pass --name sql-db -p 3306: 3306 mysql

  • buruh pelabuhan exec -it sql-db bash

  • mysql -u root -p

Ajay Singh
sumber
yang akan berakhir denganERROR 1524 (HY000): Plugin 'unix_socket' is not loaded
Enerccio
@Enerccio Bisakah Anda mencoba lagi?
Ajay Singh
-5

ubah "localhost" ke alamat ip asli Anda
karena ke mysql_connect ()

spdreamin dante
sumber