1

I have a Docker container that exposes a port to an application (e.g. Redis, which exposes port 6379). Instead of exposing 6379 on my host (and hence 1. taking up one of my precious few 65535 port numbers and 2. exposing the Redis cache to all users on my host), I would like to instead connect to Redis via a Unix socket in my local directory (e.g. by using $ redis-cli -s ~/redis.sock).

However, Docker only appears to provide port-to-port forwarding (via the ports option in docker compose, or the -p switch in docker run) or socket-to-socket forwarding (via exposing the directory the socket is contained in). Is there another way (within any GCI-compliant container system) to do the direct socket-to-port translation I'm looking for, or is this a limitation inherent to the GCI standard?

I am aware that Redis itself can listen on a Unix socket, though I'm interested in this for applications that don't have that feature available.

1 Answers1

2

There's no native support for this in docker, but you could use a tool like socat running in a container to proxy between a unix socket and a network socket (and use a bind mount to expose the unix socket in your host filesystem).

Using redis as an example, we could do something like this:

services:
  redis:
    image: docker.io/redis
    healthcheck:
      test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
      interval: 10s

redis-socket-proxy: image: docker.io/alpine/socat volumes: - ./sockets:/sockets command: - unix-listen:/sockets/redis.socket,fork,mode=0777 - tcp-connect:redis:6379 depends_on: redis: condition: service_healthy

Now you have a unix socket ./sockets/redis.socket that will connect you to the redis service.


That said, you don't have only 65535 network sockets available; you have many times more than that because you can bind sockets to specific ip addresses. Here are two redis servers, both bound to port 6379 on the host by using two different localhost addresses:

services:
  redis1:
    image: docker.io/redis
    ports:
      - 127.0.0.1:6379:6379

redis2: image: docker.io/redis ports: - 127.0.0.2:6379:6379

In many cases, you don't even need to bind ports on the host; if you've got a service like redis or a database or something that is being used as a backend for another containerized application, there's no need to publish the backend service ports; you only need to expose the frontend service.

And of course you can always connect to a service direction using the container ip address regardless of whether or not you have published the port.

For services that don't natively support binding to a unix socket, you may have a hard time finding client libraries or other tools that know how to connect to the service over the unix socket.

larsks
  • 47,453