When deploying traefik in docker swarm, it is a challenge of running Traefik on worker nodes rather than manager nodes due to the limitation that Traefik needs access to the Swarm mode API, which is only available on manager nodes. There is a work around using socat to create a bidirectional byte stream between a TCP socket and the Docker Unix socket.
So my questions are
- Is is mandatory to start traefik container in manager node with respect to docker swarm?
- What are the industry standard when running traefik in docker swarm?
- Is there any other way that we can spin up traefik in non manager node?
For Traefik Configuration Discovery you need access to the Docker Socket on at least one Swarm manager.
For improved security some run a docker-socket-proxy. If you constrain that to the Swarm managers, Traefik can run anywhere.
Be aware that introducing additional components like that also increases the risk of security issues, IMHO especially when they are maintained by a single person.
We created our own tiny docker-socket-proxy solution to avoid that. Simple NodeJS or Python script or a simple nginx config to only allow GET on necessary URLs will do.
There is also a recent docker socket proxy project that enables multi-tenancy in a Docker Swarm (link).
Hi, can you please provide docker-socket-proxy solution. How to create that script and how to leverage that.
There are Docker images available. Usual suspects are socket-proxy and docker-socket-proxy. For the latter, make sure you don't use the image without a tag, as latest
is really old (link).
Or you can create your own docker-socket-proxy. This inline version is rather a dirty hack:
services:
dockersock:
image: nginx:alpine-slim
hostname: '{{.Node.Hostname}}'
#user: "0"
#user: dockersocket:docker
security_opt:
- no-new-privileges:true
cap_add:
- CHOWN
- SETGID
- SETUID
- NET_BIND_SERVICE
cap_drop:
- ALL
networks:
- dockersock
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
mode: global
placement:
constraints:
- node.role==manager
entrypoint: ["/bin/sh", "-c"]
command:
- |
ln -sf /dev/stdout /var/log/nginx/access.log
ln -sf /dev/stderr /var/log/nginx/error.log
#su - nginx
cat <<'EOF' > /etc/nginx/nginx.conf
user root;
events { worker_connections 1024; }
http {
server {
listen 2375;
location ~ ^/(v1\.24/events|v1\.24/containers|v1\.24/services|v1\.24/version|v1\.24/networks|v1\.24/tasks) {
if ($$request_method != GET) { return 405; }
proxy_pass http://unix:/var/run/docker.sock;
proxy_set_header Host $$host;
proxy_set_header X-Real-IP $$remote_addr;
proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $$scheme;
}
location / { return 405; }
}
}
EOF
echo ID
id
echo Starting nginx
nginx -g "daemon off;"
expose:
- 2375