Proxies from Docker
r3v3rs3 can read the labels of your running containers and build the proxies from them. A container that starts gets its proxy within about one second, and a container that stops loses it. You add no proxy by hand.
This guide builds that setup with Docker Compose and checks each step. It takes a few minutes.
What You Build
client ---> :80 r3v3rs3 ---> whoami container(s)
|
+-- reads the Docker socket for labels and events
r3v3rs3 and the containers share one Docker network. r3v3rs3 reads the label of each container and sends the traffic to the address of the container on that network.
Access to the Docker socket equals root access on the host. The
:rooption applies to the socket file only and does not make the API read-only. Put a Docker socket proxy that allowsGET /containers/jsonandGET /eventsin front of it when the host is reachable from untrusted networks.
Step 1: Write the Compose File
services:
r3v3rs3:
image: ghcr.io/kilimcininkoroglu/r3v3rs3:latest
environment:
R3V3RS3_WEBUI: 0.0.0.0:46492
volumes:
- r3v3rs3-config:/root/.config/r3v3rs3
- r3v3rs3-data:/root/.local/share/r3v3rs3
- /var/run/docker.sock:/var/run/docker.sock:ro
networks: [proxy]
ports:
- "80:80"
- "127.0.0.1:46492:46492"
stop_signal: SIGINT
whoami:
image: traefik/whoami
networks: [proxy]
labels:
r3v3rs3.enable: "true"
r3v3rs3.http.whoami.ports: http
r3v3rs3.http.whoami.vhosts: whoami.example.com
r3v3rs3.http.whoami.port: "80"
networks:
proxy:
name: proxy
volumes:
r3v3rs3-config:
r3v3rs3-data:
The labels say: this container has one HTTP proxy named whoami, it uses the r3v3rs3 port named http, it answers for the host whoami.example.com, and its upstream server listens on port 80 of the container.
name: proxy under the network keeps the network name as proxy. Without it Compose adds the project name.
Start the stack:
$ docker compose up -d
Step 2: Create the Admin Account
$ docker compose exec r3v3rs3 r3v3rs3 add-user admin
Open http://localhost:46492/ and sign in.
Step 3: Bind the Port
A discovery provider opens no port. The label ports: http names a port that must already exist.
- Click Ports in the menu, then Add.
- Write
httpin the name field. The label uses this name. - Select the interface
0.0.0.0and the port80, with the protocol HTTP. - Click Create and check the state Listening.
Step 4: Turn On the Docker Provider
- Click Settings in the menu.
- Find Docker Service Discovery and turn it on.
- Write
unix:///var/run/docker.sockin the endpoint field. - Write
proxyin the network field. This is the name of the Docker network of Step 1. - Leave Expose containers by default off, so r3v3rs3 reads only the containers with
r3v3rs3.enable=true. - Save.
The same settings in config.toml:
[discovery.docker]
enabled = true
endpoint = "unix:///var/run/docker.sock"
network = "proxy"
exposed_by_default = false
Step 5: Check the Result
The Proxies page now lists a proxy named whoami with the source docker. It has no edit button, because the container owns it. The page also shows the provider state:
$ curl -b session.txt http://127.0.0.1:46492/api/discovery
[{"provider":"docker","state":"running","proxies":1,"updated_at":1789642012}]
Send a request with the host of the label:
$ curl -H 'Host: whoami.example.com' http://127.0.0.1/
Hostname: 307d1b9d215d
IP: 192.168.164.2
...
Another host gets 502, because no route matches it.
state is error when the provider cannot read the socket. An issue names the resource and the reason, for example whoami: http.whoami: port not found: http. That message means Step 3 is missing.
Step 6: Scale the Service
$ docker compose up -d --scale whoami=3
Within a second the proxy has three servers, one per replica:
$ curl -H 'Host: whoami.example.com' http://127.0.0.1/ | grep Hostname
Repeat the request. The answers rotate over the three containers, because the replicas of one Compose service share their proxy and each replica adds its own server.
Stop a replica and the proxy drops its server. Stop every replica and the proxy disappears.
Add More Containers
Each new container needs its own labels. The proxy name after the protocol keeps two containers apart:
api:
image: my/api
networks: [proxy]
labels:
r3v3rs3.enable: "true"
r3v3rs3.http.api.ports: http
r3v3rs3.http.api.vhosts: api.example.com
r3v3rs3.http.api.port: "3000"
r3v3rs3.http.api.rate_limit.requests: "100"
r3v3rs3.http.api.rate_limit.per: minute
Every field of the admin API proxy model works as a label. Labels lists the keys, the value formats and the TCP and UDP proxies. r3v3rs3 replaces a plain text password or token with a hash before it uses the proxy, so prefer password_hash and token_hash in a label.
Certificates
An HTTP proxy from a label can get its certificate automatically. Create an ACME entry first, then name its id in the label:
r3v3rs3.http.api.acme: e7k-2np
r3v3rs3 orders a certificate for the vhosts of the proxy. ACME Certificates describes the rules.
Next Steps
- Service Discovery: every provider, every label key, and the Kubernetes, Consul and etcd sources.
- Configuration: what each proxy field does.
- High Availability: several nodes with one shared state.