trafficjam
trafficjam copied to clipboard
Docker socket proxy support
Would it be possible to implement support for Docker Socket Proxy?
This probably isn't possible if the host networking mode is required.
It should already be supported, actually. You just need to set the DOCKER_HOST
env var, and the docker command in the container will automatically connect to whatever you set it to (i.e. the docker-socket-proxy tcp socket). It won't work in swarm, but it would be relatively easy to add.
I'm curious why you want to use dsp. Running trafficjam in a container is just a convenience. You could just as easily run the script as root on the host itself. Since the container isn't connected to the outside world, the risk of giving it access to the docker socket is essentially zero.
I'm curious why you want to use dsp. Running trafficjam in a container is just a convenience. You could just as easily run the script as root on the host itself. Since the container isn't connected to the outside world, the risk of giving it access to the docker socket is essentially zero.
Honestly just my OCD, all my services that require access to the docker socket use the dsp. I also don't see any security concerns.
I hadn't had the time to test DOCKER_HOST
yet.
Honestly just my OCD
I totally get it. I'm the same! I'm gonna close this but feel free to comment if you have trouble with the env var
Hey @kaysond, thanks for sharing this cool, simple tool.
I have managed to run it behind the Docker socket proxy with only 2 permissions (CONTAINERS
& NETWORKS
). Unfortunately, it can only run if the proxy is also in network_mode: host
. (or so, I thought..)
Here is the docker-compose.yml you want to give a try:
version: "3.9"
networks:
traefik_net:
external: true
backend_traefik:
external: false
services:
traefik:
container_name: traefik
image: traefik:latest
restart: always
networks:
- backend_traefik
proxy-docker:
image: tecnativa/docker-socket-proxy:0.1.1
container_name: traefik_docker_socket_proxy
restart: always
networks:
- backend_traefik
privileged: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- LOG_LEVEL=warning
# Traefik ONLY!
- CONTAINERS=1
trafficjam-proxy-docker:
image: tecnativa/docker-socket-proxy:0.1.1
container_name: traefik_trafficjam_socket_proxy
restart: always
network_mode: host
privileged: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- LOG_LEVEL=warning
- CONTAINERS=1
- NETWORKS=1
trafficjam:
image: kaysond/trafficjam:v2.1.1
container_name: traefik_trafficjam
restart: always
cap_add:
- NET_ADMIN
network_mode: host
environment:
- DOCKER_HOST=tcp://0.0.0.0:2375
- TZ
- NETWORK=traefik_net
- WHITELIST_FILTER=ancestor=traefik:2.10
- DEBUG=1
This setup, however, opens the docker tcp port on the host:
ss -tulpn | grep LISTEN
tcp LISTEN 0 3000 0.0.0.0:2375 0.0.0.0:* users:(("haproxy",pid=28169,fd=6))
Run the docker-socket-proxy on a dedicated network
Then, the issue is that I can't use the docker DNS for the tcp URL, e.g. DOCKER_HOST=tcp://traefik_trafficjam_socket_proxy:2375
traefik_trafficjam | [2023-06-07 18:47:00] ERROR: Unexpected error while determining network driver:
traefik_trafficjam | error during connect: Get "http://trafficjam-proxy-docker:2375/v1.24/networks/traefik_net": dial tcp: lookup trafficjam-proxy-docker on 1.1.1.1:53: no such host
If I hard code the DOCKER_HOST to the trafficjam-proxy-docker
located on it's dedicated subnetwork (DOCKER_HOST=tcp://172.22.0.2:2375
), it works.
TLDR
How can I set automatically the env DOCKER_HOST
to use the IP of a certain container?
On the host, I can infer it via:
docker container inspect -f '{{ .NetworkSettings.Networks.traefik_backend_trafficjam.IPAddress }}' traefik_trafficjam_socket_proxy
172.22.0.2
How can I set automatically the env DOCKER_HOST to use the IP of a certain container?
I don't think you can, unfortunately.
Then, the issue is that I can't use the docker DNS for the tcp URL, e.g. DOCKER_HOST=tcp://traefik_trafficjam_socket_proxy:2375
This doesn't work because when you use network_mode: host
, it uses the host DNS server by default. You might be able to play with some of the container dns options and get it to use the docker dns server instead: https://docs.docker.com/network/#dns-services
This setup, however, opens the docker tcp port on the host:
I don't really see this as a big problem, though you should probably configure it to bind to localhost (127.0.0.1) only, instead of 0.0.0.0. The proxy is set to read only anyways, so even if an attacker could access the port, they couldn't do anything permanent with it. They could get some information about your docker networks and containers, but realistically, if someone can access it, you're probably in bad shape anyways.
This does bring up a good point, though, that it's not trivial to get dsp working when you have to be on the host network namespace. I'll have to give it some more thought. There might be some tricks you can play with iptables and veth interfaces (which could be automated via the container).
In the meantime, though, you could set the dsp container to have a static ip: https://www.howtogeek.com/devops/how-to-assign-a-static-ip-to-a-docker-container/
Thanks @kaysond for the idea! I will share here the complete working docker-compose.yml for others not to waste time figuring it out:
version: "3.9"
networks:
traefik_net:
external: true
backend_traefik:
external: false
backend_trafficjam:
external: false
ipam:
driver: default
config:
- subnet: 172.16.238.0/30
services:
traefik:
container_name: traefik
image: traefik:2.10
restart: always
# ... rest of your config
networks:
- backend_traefik
# Docker Socket Proxy - Security Enchanced Proxy for Docker Socket
proxy-docker:
image: custom-image/docker-socket-proxy:0.1.1
container_name: traefik_docker_socket_proxy
restart: always
networks:
- backend_traefik
privileged: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
# debug,info,notice,warning,err,crit,alert,emerg
- LOG_LEVEL=warning
# Traefik ONLY!
- CONTAINERS=1
trafficjam-proxy-docker:
image: custom-image/docker-socket-proxy:0.1.1
container_name: traefik_trafficjam_socket_proxy
# restart: always
privileged: true
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
# debug,info,notice,warning,err,crit,alert,emerg
- LOG_LEVEL=warning
- CONTAINERS=1
- NETWORKS=1
networks:
backend_trafficjam:
ipv4_address: 172.16.238.2
depends_on:
- traefik
trafficjam:
image: kaysond/trafficjam:v2.1.1
container_name: traefik_trafficjam
# restart: always
cap_add:
- NET_ADMIN
network_mode: host
environment:
- DOCKER_HOST=tcp://172.16.238.2:2375
- TZ
- NETWORK=traefik_net
- WHITELIST_FILTER=ancestor=traefik:2.10
- DEBUG=1
depends_on:
- trafficjam-proxy-docker
Pay special attention to the depends_on:
part of the config.
FYI: the custom-image/docker-socket-proxy
was created to fix the "Provider connection error unexpected EOF"
as discussed in issue 21:
ARG TAG=0.1.1
FROM ghcr.io/tecnativa/docker-socket-proxy:$TAG
RUN apk add --no-cache curl
HEALTHCHECK --interval=9m --timeout=5s --retries=3 \
CMD curl -f http://localhost:2375/_ping || exit 1
Feel free to link to this comment inside the README.md file (so people don't expect you to provide support for this type of configuration)
PS: I also get this warning (see issue 79 and 74) and everything seems to work as expected:
traefik_docker_socket_proxy | [WARNING] 166/085731 (1) : Can't open server state file '/var/lib/haproxy/server-state': No such file or directory
For future users, I've switched to CetusGuard for better API rules support and these are the rules that work for me:
trafficjam-proxy-docker:
image: docker.io/hectorm/cetusguard:v1.0.11
container_name: traefik_trafficjam_socket_proxy
restart: always
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
CETUSGUARD_BACKEND_ADDR: "unix:///var/run/docker.sock"
CETUSGUARD_FRONTEND_ADDR: "tcp://:2375"
CETUSGUARD_RULES: |
! List containers
GET %API_PREFIX_CONTAINERS%/json
! Inspect a container
GET %API_PREFIX_CONTAINERS%/%CONTAINER_ID%/json
! Inspect a network
GET %API_PREFIX_NETWORKS%/%NETWORK_NAME%
# Warning = 4 and Debug = 7
CETUSGUARD_LOG_LEVEL: "4"
networks:
backend_trafficjam:
ipv4_address: 172.16.238.2
depends_on:
- traefik
The rest of the yml is the same.