Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker: MySQL container bind host mysqld socket

I am using Docker 19.03.8 and want to setup two containers:

  • The first is a MySQL container which bind mounts the mysqld socket from the host.
  • The second one is a PHP container which needs to access the database via the MySQL container.

Both containers share the same network via the networks statement. (I can not bind mount the mysqld socket directly into the PHP container, as the MySQL versions are different, therefore the MySQL container).

This is my docker-compose.yml file:

...
database:
  build: .
  volumes:
    - /var/run/mysqld/mysqld.sock:/tmp/mysql.sock
...

The Dockerfile for MySQL:

FROM mysql:8.0.20
COPY my.cnf /etc/mysql/my.cnf

And the my.cnf file contains:

...
[mysql]
socket = /tmp/mysql.sock

[mysqld]
socket = /tmp/mysql.sock
...

Unfortunately I get this error message from the MySQL container:

2020-05-20T11:30:04.708067Z 0 [ERROR] [MY-010270] [Server] Can't start server : Bind on unix socket: Address already in use
2020-05-20T11:30:04.708406Z 0 [ERROR] [MY-010258] [Server] Do you already have another mysqld server running on socket: /tmp/mysql.sock ?
2020-05-20T11:30:04.709083Z 0 [ERROR] [MY-010119] [Server] Aborting

The MySQL container starts with no errors, if I leave out socket = /tmp/mysql.sock from the [mysqld] section in my.cnf. But if I then try to connect to the database from the PHP container (mysql -h <what I specified in the networks statement> -u <user> -p <password>) I just get an empty database. So I assume it uses the default socket (/var/run/mysqld/mysqld.sock).

I don't understand why this is not working, I would be really grateful if anyone could give me a hint.

like image 976
Dominik K Avatar asked Oct 15 '22 03:10

Dominik K


1 Answers

You should use a TCP connection for this. Configure the PHP container to connect to the Compose service name (database) and default MySQL port (3306) for the database container. Do not try to use a Unix socket here.

This setup should work with the out-of-the-box mysql:8 and Docker Compose configurations. You do not need a custom my.cnf or Compose networks:, container_name:, links:, or other options.


The important detail in the setup you show is that the MySQL daemon must create the socket file itself. If you really want to do this using a Unix socket, you need to bind-mount the directory containing the socket file; you can't bind-mount the socket itself. (You could also in principle use a named volume here.)

# Not the preferred path: mount a directory instead of a file
volumes:
  - ./shared_tmp:/tmp

With the setup you show, you'll hit the following sequence of events:

  1. Docker tries to set up the database container.
  2. Docker sees /var/run/mysqld/mysqld.sock doesn't exist on the host, so it creates an empty directory there and mounts it into the container.
  3. When the MySQL daemon starts up, it tries to create a socket at /tmp/mysql.sock, but there is already a (empty) directory there.

In general it's better to avoid trying to communicate between containers via the filesystem. In addition to complications like these, there are frequently user-permission issues, and this setup limits your ability to run on multi-host setups like Docker Swarm and Kubernetes.

like image 192
David Maze Avatar answered Nov 10 '22 01:11

David Maze