# Docker compose guide
## Table of content
- [Docker compose guide](#docker-compose-guide)
- [Table of content](#table-of-content)
- [Suggestions](#suggestions)
- [Additional setup](#additional-setup)
- [Labels](#labels)
- [Syntax](#syntax)
- [Fields](#fields)
- [Key-value mapping example](#key-value-mapping-example)
- [List example](#list-example)
- [Troubleshooting](#troubleshooting)
- [Docker compose examples](#docker-compose-examples)
- [Services URLs for above examples](#services-urls-for-above-examples)
## Suggestions
In order for labels to work correctly in `compose.yml`:
1. `key: value` mapping is suggested for label, instead of `- key=value`
2. you need to add `|` in the end for multiline strings.
Example
```yaml
services:
app:
...
container_name: app
labels:
proxy.app.middlewares.modify_request.set_headers: |
X-Custom-Header1: value1, value2
X-Custom-Header2: value3
proxy.app.middlewares.modify_request.hide_headers: |
X-Custom-Header4
X-Custom-Header5
X-Custom-Header6
```
## Additional setup
1. Enable HTTPs _(optional)_
Mount a folder to store obtained certs or to load existing cert
```yaml
services:
go-proxy:
...
volumes:
- ./certs:/app/certs
```
To use **autocert**, complete that section in `config.yml`, e.g.
```yaml
autocert:
email: john.doe@x.y.z # ACME Email
domains: # a list of domains for cert registration
- y.z
- *.y.z
provider: cloudflare
options:
auth_token: c1234565789-abcdefghijklmnopqrst # your zone API token
```
To use **existing certificate**, set path for cert and key in `config.yml`, e.g.
```yaml
autocert:
provider: local
cert_path: /app/certs/cert.crt
key_path: /app/certs/priv.key
```
2. Modify `compose.yml` to fit your needs
3. Run `docker compose up -d` to start the container
4. Navigate to Web panel `http://gp.yourdomain.com` or use **Visual Studio Code (provides schema check)** to edit proxy config
[🔼Back to top](#table-of-content)
## Labels
**Parts surrounded by `[]` are optional**
### Syntax
| Label | Description | Example | Default | Accepted values |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | ------------------------------------------------------------------------- |
| `proxy.aliases` | comma separated aliases for subdomain and label matching | `gitlab,gitlab-reg,gitlab-ssh` | `container_name` | any |
| `proxy.exclude` | to be excluded from `go-proxy` | | false | boolean |
| `proxy.idle_timeout` | time for idle (no traffic) before put it into sleep **(http/s only)**
_**NOTE: idlewatcher will only be enabled containers that has non-empty `idle_timeout`**_ | `1h` | empty or `0` **(disabled)** | `number[unit]...`, e.g. `1m30s` |
| `proxy.wake_timeout` | time to wait for target site to be ready | | `30s` | `number[unit]...` |
| `proxy.stop_method` | method to stop after `idle_timeout` | | `stop` | `stop`, `pause`, `kill` |
| `proxy.stop_timeout` | time to wait for stop command | | `10s` | `number[unit]...` |
| `proxy.stop_signal` | signal sent to container for `stop` and `kill` methods | | docker's default | `SIGINT`, `SIGTERM`, `SIGHUP`, `SIGQUIT` and those without **SIG** prefix |
| `proxy..` | set field for specific alias | `proxy.gitlab-ssh.scheme` | N/A | N/A |
| `proxy.#.` | set field for specific alias at index (starting from **1**) | `proxy.#3.port` | N/A | N/A |
| `proxy.*.` | set field for all aliases | `proxy.*.set_headers` | N/A | N/A |
| `proxy.?.middlewares.[.]` | enable and set field for specific middleware | **?** here means `` / `$` / `*` - `proxy.#1.middlewares.modify_request.set_headers`
- `proxy.*.middlewares.modify_response.hide_headers`
- `proxy.app1.middlewares.redirect_http`
| N/A | Middleware specific
See [middlewares.md](middlewares.md) for more |
### Fields
| Field | Description | Default | Allowed Values / Syntax |
| --------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scheme` | proxy protocol | - `http` for numeric port
- `tcp` for `x:y` port
| `http`, `https`, `tcp`, `udp` |
| `host` | proxy host | - Docker: docker client IP / hostname
- File: `localhost`
| IP address, hostname |
| `port` | proxy port **(http/s)** | first port returned from docker | number in range of `1 - 65535` |
| `port` | proxy port **(tcp/udp)** | `0:first_port` | `x:y`
- **x**: port for `go-proxy` to listen on.
**x** can be 0, which means listen on a random port - **y**: port or [_service name_](../src/common/constants.go#L55) of target container
|
| `no_tls_verify` | whether skip tls verify **(https only)** | `false` | boolean |
| `path_patterns` | proxy path patterns **(http/s only)**
only requests that matched a pattern will be proxied | `/` **(proxy all requests)** | list[1](#list-example) of ([path patterns](https://pkg.go.dev/net/http#hdr-Patterns-ServeMux)) |
[🔼Back to top](#table-of-content)
#### Key-value mapping example
Docker Compose
```yaml
services:
nginx:
...
labels:
proxy.nginx.middlewares.modify_request.set_headers: | # remember to add the '|'
X-Custom-Header1: value1, value2
X-Custom-Header2: value3, value4
```
File Provider
```yaml
service_a:
host: service_a.internal
middlewares:
modify_request:
set_headers:
X-Custom-Header1: value1, value2
X-Custom-Header2: value3
```
[🔼Back to top](#table-of-content)
#### List example
Docker Compose
```yaml
services:
nginx:
...
labels:
proxy.nginx.path_patterns: | # remember to add the '|'
GET /
POST /auth
proxy.nginx.middlewares.modify_request.hide_headers: | # remember to add the '|'
X-Custom-Header1
X-Custom-Header2
```
Include file
```yaml
service_a:
host: service_a.internal
path_patterns:
GET /
POST /auth
middlewares:
modify_request:
hide_headers:
- X-Custom-Header1
- X-Custom-Header2
```
[🔼Back to top](#table-of-content)
## Troubleshooting
- Container not showing up in proxies list
Please check that either `ports` or label `proxy..port` is declared, e.g.
```yaml
services:
nginx-1: # Option 1
...
ports:
- 80
nginx-2: # Option 2
...
container_name: nginx-2
network_mode: host
labels:
proxy.nginx-2.port: 80
```
- Firewall issues
If you are using `ufw` with vpn that drop all inbound traffic except vpn, run below:
`sudo ufw allow from 172.16.0.0/16 to 100.64.0.0/10`
Explaination:
Docker network is usually `172.16.0.0/16`
Tailscale is used as an example, `100.64.0.0/10` will be the CIDR
You can also list CIDRs of all docker bridge networks by:
`docker network inspect $(docker network ls | awk '$3 == "bridge" { print $1}') | jq -r '.[] | .Name + " " + .IPAM.Config[0].Subnet' -`
[🔼Back to top](#table-of-content)
## Docker compose examples
More examples in [here](examples/)
```yaml
volumes:
adg-work:
adg-conf:
mc-data:
palworld:
nginx:
services:
adg:
image: adguard/adguardhome
restart: unless-stopped
labels:
- proxy.aliases=adg,adg-dns,adg-setup
- proxy.#1.port=80
- proxy.#2.scheme=udp
- proxy.#2.port=20000:dns
- proxy.#3.port=3000
volumes:
- adg-work:/opt/adguardhome/work
- adg-conf:/opt/adguardhome/conf
ports:
- 80
- 3000
- 53/udp
mc:
image: itzg/minecraft-server
tty: true
stdin_open: true
container_name: mc
restart: unless-stopped
ports:
- 25565
labels:
- proxy.mc.port=20001:25565
environment:
- EULA=TRUE
volumes:
- mc-data:/data
palworld:
image: thijsvanloef/palworld-server-docker:latest
restart: unless-stopped
container_name: pal
stop_grace_period: 30s
ports:
- 8211/udp
- 27015/udp
labels:
- proxy.aliases=pal1,pal2
- proxy.*.scheme=udp
- proxy.#1.port=20002:8211
- proxy.#2.port=20003:27015
environment: ...
volumes:
- palworld:/palworld
nginx:
image: nginx
container_name: nginx
volumes:
- nginx:/usr/share/nginx/html
ports:
- 80
labels:
proxy.idle_timeout: 1m
go-proxy:
image: ghcr.io/yusing/go-proxy:latest
container_name: go-proxy
restart: always
network_mode: host
volumes:
- ./config:/app/config
- /var/run/docker.sock:/var/run/docker.sock
go-proxy-frontend:
image: ghcr.io/yusing/go-proxy-frontend:latest
container_name: go-proxy-frontend
restart: unless-stopped
network_mode: host
labels:
- proxy.aliases=gp
- proxy.gp.port=3000
depends_on:
- go-proxy
```
[🔼Back to top](#table-of-content)
### Services URLs for above examples
- `gp.yourdomain.com`: go-proxy web panel
- `adg-setup.yourdomain.com`: adguard setup (first time setup)
- `adg.yourdomain.com`: adguard dashboard
- `nginx.yourdomain.com`: nginx
- `yourdomain.com:2000`: adguard dns (udp)
- `yourdomain.com:20001`: minecraft server
- `yourdomain.com:20002`: palworld server
[🔼Back to top](#table-of-content)