Skip to content

Instantly share code, notes, and snippets.

@singe
Last active June 20, 2024 07:37
Show Gist options
  • Save singe/3c6bde78191f1a9bd414a4d729e98f1c to your computer and use it in GitHub Desktop.
Save singe/3c6bde78191f1a9bd414a4d729e98f1c to your computer and use it in GitHub Desktop.
Restricting Networking in Docker for Mac & Windows

Shared Unix Sockets on macOS/Windows machines to isolated Docker containers

In a Linux world, a Unix Domain Socket can just be shared with a standard Docker bind mount. However, in macOS and Windows' Docker Desktop, this can't be done due to Windows not supporting UDS and macOS' BSD base implementing sockets differently to Linux and lastly because you can't just copy a socket between computers and expect the same things to be bound to it. There's a long thread started from a 2016 Docker issue if you'd like the context docker/for-mac#483

This repository shows an easy way to share a socket to an otherwise isolated container by making use of socat and Docker volumes. Sharing a socket is a more secure way of giving access to a single service than requiring networking and full access to the host.

IMG_3119

It works because the volume is created on the interstitial host vm, which is the same "computer" the containers are run within.

There are two examples, one using docker compose and the other using individual docker commands.

This example has socat connecting a network service to the socket, but can be changed for your needs.

If you wanted to share a socket to the socket, you would need to wrap the socket with something IP enabled, like running an additional socat on the underlying macOS/Windows host to create a TCP-LISTEN'er that the socat container can then connect to.

services:
socat:
image: alpine/socat
# Connects to a service running on port 1337 on the host machine and creates a unix socket listener
command: UNIX-LISTEN:/sockets/shared.sock,unlink-early,unlink-close,fork TCP-CONNECT:host.docker.internal:1337,reuseaddr
# unlink-* deletes the socket file before start up and when the connection is closed
restart: unless-stopped
volumes:
- sockets:/sockets
# It needs access to the host, hence the default network
networks:
- default
isolated:
image: alpine
volumes:
- sockets:/sockets
# Isolate the host's networking
network_mode: "none"
# Create a standard docker volume, this will reside on the host VM rather than the underlying macOS or Windows
volumes:
sockets:
#!/bin/sh
# Create the volume
docker volume create sockets
# Start the socat TCP -> Unix Socket
# This example connects to a service running on port 1337 on the host macOS/Windows machine
docker run --rm --volume sockets:/sockets alpine/socat \
UNIX-LISTEN:/sockets/shared.sock,unlink-early,unlink-close,fork \
TCP-CONNECT:host.docker.internal:1337,reuseaddr
# Run a container with an isolated network but access to the socket
docker run --rm -it --volume sockets:/sockets --network none alpine:latest
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment