Kết nối với mysql trong vùng chứa docker từ máy chủ


109

(Có lẽ đây là một câu hỏi ngớ ngẩn do kiến ​​thức hạn chế của tôi về quản trị Docker hoặc mysql, nhưng vì tôi đã dành cả buổi tối cho vấn đề này, tôi dám hỏi nó.)

Tóm lại

Tôi muốn chạy mysql trong một bộ chứa docker và kết nối với nó từ máy chủ của tôi. Cho đến nay, điều tốt nhất tôi đã đạt được là:

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

Thêm chi tiết

Tôi đang sử dụng như sau 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

Trong thư mục chứa tệp này, tôi có thể tạo thành công hình ảnh và chạy nó bằng:

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

Khi tôi đính kèm vào hình ảnh, nó có vẻ hoạt động tốt:

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

Tuy nhiên, tôi không có được nhiều thành công từ người dẫn chương trình:

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

Chi tiết hơn nữa

  • Tôi đã thấy rằng có một câu hỏi giống như của tôi . Tuy nhiên, nó không giống nhau (và nó không có bất kỳ câu trả lời nào)
    • Tôi đã thấy rằng có những hình ảnh dành riêng cho mysql , nhưng tôi đã không thành công hơn với chúng
    • My grep -vcó thể cảm thấy kỳ lạ. Phải thừa nhận rằng có thể có cách tốt hơn để làm điều đó. Nhưng khi tôi đính kèm hình ảnh của mình, tôi có thể thấy nó thực sự hoạt động như mong đợi (tức là: đã loại bỏ bind-address). Và tôi có thể thấy trong vùng chứa /var/log/mysql/error.log:

Tên máy chủ (địa chỉ ràng buộc): '0.0.0.0'; port: 3306 - '0.0.0.0' giải quyết thành '0.0.0.0'; Ổ cắm máy chủ được tạo trên IP: '0.0.0.0'.


1
Có lẽ không đến nỗi. Tôi tình cờ gặp điều này lần thứ 10 và cuối cùng đã có thời gian để thử nó ở nhà.
kiltek

Câu trả lời:


171

Nếu máy chủ Docker MySQL của bạn đang chạy chính xác, bạn có thể kết nối với nó từ máy cục bộ, nhưng bạn nên chỉ định máy chủ, cổng và giao thức như sau:

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

Thay đổi 3306 thành số cổng bạn đã chuyển tiếp từ vùng chứa Docker (trong trường hợp của bạn, nó sẽ là 12345).

Bởi vì bạn đang chạy MySQL bên trong Docker container, socket không khả dụng và bạn cần kết nối thông qua TCP. Đặt "--protocol" trong lệnh mysql sẽ thay đổi điều đó.


1
Bạn có thể làm rõ lý do tại sao ổ cắm mysql không khả dụng? Lệnh của bạn hoạt động, nhưng tôi tự hỏi liệu có cách nào để gắn socket mysql với máy chủ từ vùng chứa hay không.
Lucas

9
Tôi không phải là chuyên gia về giao tiếp Unix, nhưng theo những gì tôi hiểu thì socket là một kết nối được biểu diễn dưới dạng tệp. Vì tệp socket không được chia sẻ giữa vùng chứa Docker và máy chủ nên máy khách MySQL không thể sử dụng một tệp từ bên trong vùng chứa Docker. Để kết nối với máy chủ MySQL bên trong vùng chứa Docker từ máy chủ, bạn có thể: 1. Đặt máy chủ MySQL để đặt ổ cắm vào vị trí được chỉ định --socket=/var/run/mysqld/mysqld.sock2. Gắn tệp này bên ngoài vùng chứa Docker 3. Chỉ định đường dẫn đến ổ cắm trong máy khách MySQL với--socket=/host/mysql.sock
maniekq

@maniekq Nhận xét tuyệt vời! Nhưng bạn đã xác minh được cả ba khả năng của mình chưa? Tất cả chúng có thực sự hoạt động không?
Andru

7
Sau một thời gian dài đấu tranh, tôi đã tìm ra câu trả lời vàng này, --protocol=tcpcuối cùng thì kết nối cũng hoạt động. Cảm ơn @maniekq vì cả câu trả lời hay và lời giải thích của bạn về ổ cắm qua bình luận của bạn!
panepeter

1
Nó không phải là câu trả lời được chấp nhận, vì anh ta nói rõ ràng rằng anh ta không có ý tưởng về giao tiếp tệp UNIX.
kiltek

50

Nếu bạn sử dụng "127.0.0.1" thay vì localhost, mysql sẽ sử dụng phương thức tcp và bạn có thể kết nối vùng chứa với:

mysql -h 127.0.0.1 -P 3306 -u root

4
Tôi có thể xác minh rằng sau khi tôi thay đổi localhost thành 127.0.0.1 và xóa cờ giao thức, nó vẫn hoạt động như cũ
Craig Wayne

2
Tôi nghĩ đây là câu trả lời ngắn gọn và hay nhất;)
rezam 10/09/18

1
Có thể ngắn gọn nhưng đó không phải là câu trả lời, vì TCP là phương pháp giao tiếp với mysql chậm hơn. (nhiều cpu hơn và độ trễ cao hơn)
John

1
@John bạn nói đúng, nó chậm hơn nhưng nó tồn tại. Tất nhiên bạn có thể chia sẻ /var/run/mysqld/mysqld.sock giữa máy chủ và vùng chứa.
Vasili Pascal

2
Đó là những gì tôi muốn đề xuất cho bất kỳ DB nhiệm vụ cao hơn nào. nó đơn giản như "-v socketfile.sock" và sau đó mysql --socket /path/file.sock mà không làm ô nhiễm ngăn xếp tcp / ip.
John

27

Tôi khuyên bạn nên kiểm tra docker-soạn. Đây là cách hoạt động:

Tạo một tệp có tên, docker-compo.yml trông giống như sau:

version: '2'

services:

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

Tiếp theo, chạy:

$ docker-soạn lên

Ghi chú:

Bây giờ, bạn có thể truy cập bảng điều khiển mysql do đó:

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

Ghi chú:

  • Bạn có thể chuyển cờ -d để chạy vùng chứa mysql / mariadb ở chế độ tách rời / nền.

  • Mật khẩu là "wp" được xác định trong tệp docker-compost.yml.

  • Lời khuyên tương tự như maniekq nhưng đầy đủ ví dụ với docker-soạn.


3
--protocol=tcpđã sửa mọi thứ cho tôi. Cảm ơn bạn!
Charlie L

Cảm ơn câu trả lời này, tôi đã gặp vấn đề tương tự như trong chủ đề nhưng sau khi sử dụng --protocol = tcp, nó đã được khắc phục. Tôi nghĩ có điều gì đó không ổn với mạng docker.
jiriki

16

Phương pháp đơn giản là chia sẻ ổ cắm unix mysql với máy chủ. Sau đó kết nối qua ổ cắm

Các bước:

  • Tạo thư mục chia sẻ cho máy chủ, ví dụ: mkdir /host
  • Chạy bộ chứa docker với tùy chọn gắn khối lượng docker run -it -v /host:/shared <mysql image>.
  • Sau đó thay đổi tệp cấu hình mysql /etc/my.cnfvà thay đổi mục nhập ổ cắm trong tệp thànhsocket=/shared/mysql.sock
  • Khởi động lại dịch vụ MySQL service mysql restarttrong docker
  • Cuối cùng Kết nối với MySQL servver từ máy chủ thông qua socket mysql -u root --socket=/host/mysql.sock. Nếu mật khẩu sử dụng tùy chọn -p

1
Bạn có phải làm điều này nếu máy khách MySQL nằm trong vùng chứa khác không?
Stephane

Tôi không biết điều đó. Tôi đã chọn phương pháp này vì phương thức cổng tcp-ip không hoạt động với tôi. Nếu bạn đang sử dụng hai vùng chứa cho máy chủ và máy khách, bạn có thể chia sẻ một thư mục chung cho cả hai vùng chứa và sử dụng Unix socket để kết nối với MySQL.
Jobin

1
Câu trả lời cho câu hỏi của tôi là không khi tôi sử dụng docker-soạn với một liên kết trên các vùng chứa.
Stephane

9

nếu bạn chạy docker dưới docker-máy?

thực thi để lấy ip:

docker-machine ip <machine>

trả lại ip cho máy và thử kết nối mysql:

mysql -h<docker-machine-ip>

Đã giải quyết trong Docker-Toolbox :) Cảm ơn bạn rất nhiều.
Vương

5

Tôi thực hiện việc này bằng cách chạy một vùng chứa docker tạm thời dựa trên máy chủ của mình để tôi không phải lo lắng về những gì được cài đặt trên máy chủ của mình. Đầu tiên, tôi xác định những gì tôi cần (mà bạn nên sửa đổi cho mục đích của mình):

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

Tôi luôn tạo một mạng docker mới mà bất kỳ vùng chứa nào khác sẽ cần:

docker network create --driver bridge $DB_DOCKER_NETWORK

Khởi động máy chủ cơ sở dữ liệu mySQL:

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

Chụp địa chỉ IP của vùng chứa máy chủ mới

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

Mở giao diện dòng lệnh tới máy chủ:

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"

Vùng chứa cuối cùng này sẽ tự xóa khi bạn thoát khỏi giao diện mySQL, trong khi máy chủ sẽ tiếp tục chạy. Bạn cũng có thể chia sẻ một khối lượng giữa máy chủ và máy chủ lưu trữ để giúp nhập dữ liệu hoặc tập lệnh dễ dàng hơn. Hi vọng điêu nay co ich!


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

Hãy nhớ thay đổi người dùng, cổng và máy chủ để phù hợp với cấu hình của bạn. Cờ -p là bắt buộc nếu người dùng cơ sở dữ liệu của bạn được định cấu hình bằng mật khẩu


2

Để chuyển đổi , bạn có thể tạo ~/.my.cnftệp trong máy chủ:

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

Sau đó, lần sau chỉ cần chạy mysqlcho máy khách mysql để mở kết nối.


1

Tôi đã có thể kết nối sql server5.7 của mình đang chạy trên máy chủ của mình bằng lệnh dưới đây: mysql -h 10.10.1.7 -P 3307 --protocol = tcp -u root -p trong đó ip được cung cấp là ip máy chủ của tôi và 3307 là port bị chèn trong mysql docker.


0

chạy lệnh sau để chạy vùng chứa

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

chạy lệnh này để lấy mysql db trong máy chủ

mysql -h 127.0.0.1 -P 8306 -uroot  -pPASS

trong trường hợp của bạn thì nó là

mysql -h 127.0.0.1 -P 12345 -uroot  -pPASS

Điều này chỉ hoạt động nếu bạn sử dụng 127.0.0.1 làm địa chỉ. Nếu bạn sử dụng địa chỉ không phải địa phương của máy chủ, bạn cần thêm --protocol=tcpcờ như được mô tả trong một số nhận xét / câu trả lời khác. Trong trường hợp của tôi, điều đó thật khó hiểu bởi vì tôi cũng có một phiên bản mysql cục bộ, không được làm dày đặc, đang chạy. Theo mặc định, ngay cả khi cổng được chỉ định, ngay cả khi cổng không chính xác, lệnh 'mysql' sẽ kết nối qua tệp socket với phiên bản cục bộ.
Phong phú

@Rich vậy bạn đã làm gì để giải quyết vấn đề đó? Ngay cả khi tôi đang có thiết lập tương tự, một MySql chạy trên máy chủ và một MySql khác trong bộ chứa docker.
NITHIN RAJ T

@NITHINRAJT có 2 cách để thực hiện điều này SAU KHI bạn đảm bảo rằng phiên bản docker của bạn không nghe trên cùng một cổng (ví dụ: như trong câu trả lời này, 8306). (1) Hãy thử câu trả lời này, câu trả lời mà chúng tôi đang bình luận (ví dụ: kết nối với 127.0.0.1. (2) Hãy thử câu trả lời tiếp theo - mysql -u root -P <EXPOSED_DOCKER_PORT_HERE> -h <YOUR_HOST_IP_ADDRESS_HERE> --protocol=tcp -p. Lá cờ, --protocol=tcplà chìa khóa để làm cho câu trả lời này thành công.
Giàu

0

Khi chạy thiết bị đầu cuối của bạn docker exec -it container_name /bin/bash :mysql


0

ĐỒNG Ý. Cuối cùng tôi đã giải quyết được vấn đề này. Đây là giải pháp của tôi được sử dụng trong https://sqlflow.org/sqlflow .

Giải pháp hoàn chỉnh

Để tạo bản trình diễn độc lập, tôi đã chuyển tất cả mã cần thiết đến https://github.com/wangkuiyi/mysql-server-in-docker .

Chìa khóa cho giải pháp

Tôi không sử dụng hình ảnh chính thức trên DockerHub.com https://hub.docker.com/r/mysql/mysql-server . Thay vào đó, tôi đã tự tạo bằng cách cài đặt MySQL trên Ubuntu 18.04. Cách tiếp cận này cho tôi cơ hội khởi động mysqld và liên kết nó với 0.0.0.0 (tất cả các IP) .

Để biết chi tiết, vui lòng tham khảo những dòng này trong repo GitHub của tôi.

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

Để xác minh giải pháp của tôi

  1. Git sao chép repo nói trên.
    git clone https://github.com/wangkuiyi/mysql-server-in-docker
    cd mysql-server-in-docker
  2. Xây dựng hình ảnh Docker máy chủ MySQL
    docker build -t mysql:yi .
  3. Khởi động máy chủ MySQL trong vùng chứa
    docker run --rm -d -p 23306:3306 mysql:yi
  4. Cài đặt ứng dụng khách MySQL trên máy chủ, nếu chưa. Tôi đang chạy Ubuntu 18.04 trên máy chủ lưu trữ (máy trạm của tôi), vì vậy tôi sử dụng apt-get.
    sudo apt-get install -y mysql-client
  5. Kết nối từ máy chủ tới máy chủ MySQL đang chạy trong vùng chứa.
    mysql --host 127.0.0.1 --port 23306 --user root -proot

Kết nối từ một vùng chứa khác trên cùng một máy chủ

Chúng tôi có thể chạy máy khách MySQL từ ngay cả một vùng chứa khác (trên cùng một máy chủ).

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

Kết nối từ Máy chủ khác

Trên iMac của mình, tôi cài đặt ứng dụng khách MySQL bằng Homebrew.

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

Sau đó, tôi có thể truy cập máy chủ Ubuntu ở trên (192.168.1.22).

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

Kết nối từ một vùng chứa đang chạy trên một máy chủ khác

Tôi thậm chí có thể chạy ứng dụng khách MySQL trong một vùng chứa chạy trên iMac để kết nối với máy chủ MySQL trong một vùng chứa trên máy trạm Ubuntu của tôi.

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

Một trường hợp đặc biệt

Trong trường hợp chúng tôi chạy máy khách và máy chủ MySQL trong các vùng chứa riêng biệt chạy trên cùng một máy chủ - điều này có thể xảy ra khi chúng tôi thiết lập CI, chúng tôi không cần phải xây dựng hình ảnh Docker máy chủ MySQL của riêng mình. Thay vào đó, chúng ta có thể sử dụng --net=container:mysql_server_container_namekhi chúng ta chạy vùng chứa khách hàng.

Để khởi động máy chủ

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

Để bắt đầu khách hàng

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 executive -it sql-db bash

  • mysql -u root -p


điều đó sẽ kết thúc vớiERROR 1524 (HY000): Plugin 'unix_socket' is not loaded
Enerccio

@Enerccio Bạn có thể thử lại không?
Ajay Singh

-5

thay đổi "localhost" thành trình cắm ip con thực của bạn
vì nó là mysql_connect ()

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.