.vscode | ||
.gitignore | ||
build.sh | ||
compose.example.yml | ||
Dockerfile | ||
go.mod | ||
go.sum | ||
main.go | ||
README.md |
go-proxy
A simple auto docker reverse proxy for home use.
Written in Go with ~180 loc.
Features
- subdomain matching (domain name doesn't matter)
- path matching
- Auto hot-reload when container start / die / stop.
Why am I making this
I have tried different reverse proxy services, i.e. nginx proxy manager, traefik, nginx-proxy. I have found that traefik
is not easy to use, and I don't want to click buttons every time I spin up a new container (nginx proxy manager
). For nginx-proxy
I found it buggy and quite unusable.
How to use
-
Clone the repo
git clone https://github.com/yusing/go-proxy
-
Copy compose.example.yml to
compose.yml
-
add networks to make sure it is in the same network with other containers, or make sure
proxy.<alias>.host
is reachable -
modify the path to your SSL certs. See Getting SSL Certs
-
start
go-proxy
withdocker compose up -d
.
Configuration
With a proper container name, no label needs to be added.
However, there are some labels you can manipulate with:
proxy.aliases
: comma separated aliases for subdomain matching- defaults to
container_name
- defaults to
proxy.<alias>.scheme
: container port protocol (http
orhttps
)- defaults to
http
- defaults to
proxy.<alias>.host
: proxy host- defaults to
container_name
- defaults to
proxy.<alias>.port
: proxy port- defaults to first expose port (declared in
Dockerfile
ordocker-compose.yml
)
- defaults to first expose port (declared in
proxy.<alias>.path
: path matching- defaults to empty
version: '3'
services:
whoami:
image: traefik/whoami
container_name: whoami
# visit https://whoami.yourdomain.com to access
# enable both subdomain and path matching:
whoami:
image: traefik/whoami
container_name: whoami
labels:
- proxy.aliases=whoami,apps
- proxy.apps.path=/whoami
# 1. visit https://whoami.yourdomain.com to access
# 2. visit https://apps.yourdomain.com/whoami to access
For multiple port container (i.e. minio)
version: '3'
services:
minio:
image: quay.io/minio/minio
container_name: minio
command:
- server
- /data
- --console-address
- "9001"
env_file: minio.env
expose:
- 9000
- 9001
volumes:
- ./data/minio/data:/data
labels:
proxy.aliases: minio,minio-console
proxy.minio.port: 9000
proxy.minio-console.port: 9001
# visit https://minio.yourdomain.com to access minio
# visit https://minio-console.yourdomain.com/whoami to access minio console
Troubleshooting
Q: How to fix when it shows "no matching route for subdomain <subdomain>"?
A: Make sure the container is running, and <subdomain> matches any container name / alias
Benchmarks
Benchmarked with wrk
connecting traefik/whoami
's /bench
endpoint
Direct connection
% wrk -t20 -c100 -d10s --latency http://homelab:4999/bench
Running 10s test @ http://homelab:4999/bench
20 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.71ms 2.26ms 48.10ms 94.95%
Req/Sec 1.41k 179.01 2.11k 69.97%
Latency Distribution
50% 3.32ms
75% 3.98ms
90% 4.97ms
99% 11.36ms
282804 requests in 10.10s, 33.98MB read
Requests/sec: 27998.62
Transfer/sec: 3.36MB
With go-proxy reverse proxy
% wrk -t20 -c100 -d10s --latency https://whoami.mydomain.com/bench
Running 10s test @ https://whoami.mydomain.com/bench
20 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 4.41ms 2.56ms 77.80ms 95.38%
Req/Sec 1.18k 156.44 1.63k 86.51%
Latency Distribution
50% 3.93ms
75% 4.76ms
90% 5.92ms
99% 10.46ms
235374 requests in 10.10s, 22.90MB read
Requests/sec: 23302.42
Transfer/sec: 2.27MB
Build it yourself
-
Install go if not already
-
Get dependencies with
go get
-
build image with following commands
mkdir -p bin CGO_ENABLED=0 GOOS=<platform> go build -o bin/go-proxy docker build -t <tag> .
Getting SSL certs
I personally use nginx-proxy-manager
to get SSL certs with auto renewal by Cloudflare DNS challenge. You may symlink the certs from nginx-proxy-manager
to somewhere else, and mount them to go-proxy
's /certs