我在自己的mac上安装了docker,并在docker中运行了mysql5.6容器。启动容器的方式大致如下:

1
2
3
4
5
$ docker run --name mydb -d \
    -p 3306:3306 \
    -v /Users/voidint/dockerV/mysql/data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=xxxxx \
    mysql:5.6

mysql服务正常启动之后,我想通过客户端连接此服务。于是,我顺理成章地在终端敲下了这样的命令

1
2
3
$ mysql -u root -p
Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

非常意外,居然报错了。我记得以前都是这样敲的呀?怎么换成跑在docker里就行不通了?不科学!

1
2
3
$ mysql -h localhost -uroot -p
Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

加上-h选项还是不行,气急败坏。气归气,问题还是要解决的,那就查查资料。然后,看到了这篇,在粗粗浏览过之后,发现有人建议用-h 127.0.0.1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$ mysql -h 127.0.0.1 -u root -p 
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3823
Server version: 5.6.35 MySQL Community Server (GPL)

Copyright (c) 2000, 2015, 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>

试过之后,发现效果立竿见影。这简直颠覆了我的既有观念!

  • 难道localhost和127.0.0.1不是同一个东西?OMG!
  • 那个socket文件/tmp/mysql.sock又是怎么一回事,指定了127.0.0.1怎么就正常了?

在查阅了一些资料之后,终于对于这几个问题有了稍深入的理解:

localhost和127.0.0.1的区别

  • localhost和127.0.0.1,前者是域名,后者是IP地址中特殊的一类回还地址。
  • 许多时候localhost和127.0.0.1给人感觉是等价的,是由于在多数系统的/etc/hosts文件中,两者存在映射关系。
  • 本机上的服务,如果通过localhost访问,可以不经过网卡,并且不受防火墙的限制。如果不经过网卡,那客户端和服务端要如何通信?答案就是socket。比如上面例子中的/tmp/mysql.sock。也因为不需要经过网卡,不需要TCP/IP协议的层层封包和层层解包过程,性能上会更出色一些。
  • 本机上的服务,如果通过127.0.0.1访问,需要经过网卡,也可能受到防火墙限制。

参考资料