How to expose Linux socket file from Docker container (MySQL, MariaDB, etc.) to host

Disclaimer: I am not looking for a way to configure MySQL/MariaDB to use TCP connections. I am aware of that option and the question is not about that aspect.

I am having trouble binding a socket file from inside a container to the host file system. I expected a simple docker-compose entry like this to work:

    volumes:
      - /srv/docker/sockets/mariadb.container.sock:/var/run/mysqld/mysqld.sock

But that did not work. Instead, I experienced the following error messages:

its_sql_dev    | 190305 10:31:23 [ERROR] Can't start server : Bind on unix socket: Address already in use
its_sql_dev    | 190305 10:31:23 [ERROR] Do you already have another mysqld server running on socket: /var/run/mysqld/mysqld.sock ?

The state of the file in the host system did not seem to matter - wether it already existed, existed with a+rwx permissions, existed with the correct user or did not exist at all did not seem to have any affect on whether the container would start.

Maybe the most baffling thing was the end result in the host file system:

[user@server mariadb]# ls -alsh /srv/docker/shared/
total 16K
4.0K drwxrwxrwx 4 root    root     4.0K Mar  5 11:31 .
4.0K drwxr-xr-x 7 root    root     4.0K Mar  1 13:09 ..
4.0K drwxr-xr-x 2 root    root     4.0K Mar  5 11:31 mariadb.container.sock

It turned out the .sock file turned into an (empty) directory on the host!

I have had a little more luck with moving the socket file to its own directory amnd mounting that directory to the host, in which case it would work once, but not after a container restart.


Solution 1:

The problem is that bind mounts are for exposing something on the host to the container. So when you do this:

volumes:
  - /srv/docker/sockets/mariadb.container.sock:/var/run/mysqld/mysqld.sock

You are trying to mount /srv/docker/sockets/mariadb.container.sock -- which does not exist -- onto /var/run/mysqld/mysqld.sock inside the container. Since the source object doesn't exist, Docker will create an empty directory at that location and mount it into the container...which of course means mysqld can't create the socket when it starts up.

The correct solution is to mount a host directory onto /var/run/mysqld/, for example:

volumes:
  - /srv/docker/sockets/mariadb:/var/run/mysqld

And then on your host the socket will be available as /srv/docker/sockets/mariadb/mysqld.sock.