Skip to main content

Tailscale as a Docker sidecar

Add Tailscale to any Docker Compose project as a sidecar container. Your app gets a stable hostname on your tailnet with automatic HTTPS -- no port forwarding, no reverse proxy config.

docker 2025-02-08

Add Tailscale to any Docker Compose project as a sidecar container. Your app gets a stable hostname on your tailnet with automatic HTTPS – no port forwarding, no reverse proxy config.

1. Add tailscale service to compose.yml

+ services:
+   tailscale:
+     image: tailscale/tailscale:latest
+     container_name: ${TS_HOSTNAME}-tailscale
+     restart: always
+     volumes:
+       - ./tailscale:/var/lib/tailscale:rw
+       - ./serve.json:/config/serve.json:ro
+     environment:
+       - TS_AUTHKEY=${TS_AUTHKEY}
+       - TS_HOSTNAME=${TS_HOSTNAME}
+       - TS_STATE_DIR=/var/lib/tailscale
+       - TS_SERVE_CONFIG=/config/serve.json
+     cap_add:
+       - net_admin
+       - sys_module

   your-app:
     image: whatever/app
+    network_mode: service:tailscale
+    depends_on:
+      - tailscale

network_mode: service:tailscale routes your app’s traffic through the Tailscale container. Your app is now only accessible via your tailnet.

2. Create serve.json

{
	"TCP": {
		"443": {
			"HTTPS": true
		}
	},
	"Web": {
		"HOSTNAME.YOUR_TAILNET_DOMAIN.ts.net:443": {
			"Handlers": {
				"/": {
					"Proxy": "http://127.0.0.1:PORT"
				}
			}
		}
	}
}

Replace HOSTNAME, YOUR_TAILNET_DOMAIN, and PORT with your values.

3. Add to .env

Get an auth key from Tailscale admin (reusable + ephemeral recommended):

TS_AUTHKEY=tskey-auth-xxxxx
TS_HOSTNAME=your-hostname

4. Update .gitignore

tailscale/
.env

Updating all Tailscale containers

See running Tailscale containers:

docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" | grep -E "(NAMES|tailscale)"

Pull latest and recreate all of them:

docker ps --format "{{.Names}}\t{{.Labels}}" | grep tailscale | \
  sed 's/.*com.docker.compose.project.working_dir=\([^,]*\).*/\1/' | sort -u | \
  xargs -I{} sh -c 'cd "{}" && docker compose up -d --pull always'