Skip to content
Wolfgang Ellsässer edited this page Sep 28, 2025 · 6 revisions

socket-proxy

Socket-proxy allows partial access to a Unix socket via TCP. A good use case is giving a docker container some permissions to the docker socket without mounting the docker socket directly in the container.

Samples

Dozzle

Dozzle is an easy-to-use docker log viewer.

Here is an example of running Dozzle without being root and without mounting the docker socket in the container. Note that some IP addresses are declared statically, so the socket proxy can be configured to only allow that specific IP address. This is not necessary, but it adds an extra layer of security.

docker-compose.yml

services:
  dockerproxy:
    image: wollomatic/socket-proxy:1
    command:
      - '-loglevel=info'
      - '-allowfrom=dozzle' # allow only the dozzle container
      - '-listenip=0.0.0.0'
      - '-allowGET=/v1\..{2}/(containers/.*|events|info)'
      - '-allowHEAD=/_ping'
      - '-watchdoginterval=3600'
      - '-stoponwatchdog'
      - '-shutdowngracetime=10'
    restart: unless-stopped
    read_only: true
    mem_limit: 64M
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges
    user: 65534:998
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - docker-proxynet
      
  dozzle:
    image: amir20/dozzle:v8.5.3
    user: 65534:65534
    read_only: true
    mem_limit: 256M
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges
    depends_on:
      - dockerproxy
#    ports: # please mind that this would expose dozzle to the whole network!
#      - 9999:8080
    environment:
      DOZZLE_REMOTE_HOST: tcp://dockerproxy:2375
    networks:
      - docker-proxynet
      - dozzle

networks:
  docker-proxynet:
    internal: true
    attachable: false
  dozzle:
    driver: bridge
    attachable: false

Using socket instead of TCP (example with Traefik)

This is just an example to use a unix socket, no complete Traefik configuration. Traefik´s docker provider has to be configured to use the specified socket file:

config/traefik.yaml (snippet)

providers:
  docker:
    exposedByDefault: false
    endpoint: 'unix:///socket/traefik.sock'
    network: traefik-servicenet

docker-compose.yaml

services:

  socketproxy:
    image: ghcr.io/wollomatic/socket-proxy:1.9.0
    read_only: true
    restart: unless-stopped
    user: 65530:999
    mem_limit: 128M
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges
    command:
      - -loglevel=debug
      - -shutdowngracetime=5
      - -allowGET=/v1\..{1,2}/(version|containers/.*|events.*)
      - -watchdoginterval=60
      - -stoponwatchdog
      - -proxysocketendpoint=/socket/traefik.sock
      - -proxysocketendpointfilemode=0600
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - socket:/socket/
    network_mode: none

  traefik:
    image: traefik:v3.5.3
    restart: unless-stopped
    depends_on:
      - socketproxy
    read_only: true
    mem_limit: 2G
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    volumes:
      - ./config/traefik.yaml:/etc/traefik/traefik.yaml:ro
      - ./config/dynamic/:/etc/traefik/dynamic/:ro
      - socket:/socket/:ro
    user: "65530:65530"
    networks:
      - traefik-servicenet
    ports:
      - "80:80/tcp"
      - "443:443/tcp"

networks:
  traefik-servicenet:
    external: true
    name: traefik-servicenet

volumes:
  socket:
    driver: local
    driver_opts:
      type: tmpfs
      device: tmpfs
      o: size=1k,uid=65530,gid=0,mode=0700,noexec
Clone this wiki locally