Skip to content

Instantly share code, notes, and snippets.

@danielnaranjo
Forked from Ocramius/Caddyfile
Created June 2, 2020 01:29
Show Gist options
  • Save danielnaranjo/4fab6a0ba1222a3918cb152ee0bc1142 to your computer and use it in GitHub Desktop.
Save danielnaranjo/4fab6a0ba1222a3918cb152ee0bc1142 to your computer and use it in GitHub Desktop.
Example docker + docker-compose + caddy + traefik setup that routes to multiple apps from one exposed HTTP port

Example docker-compose setup that routes to separate hosts while exposing one port

This example runs 4 different docker containers:

  • a traefik reverse proxy
  • 3 caddy instances (simple/modern web server with minimal config)

The 3 applications are completely isolated from the outside network, and are neither accessible nor can access the WAN.

The HTTP routing (and eventual SSL termination) is up to traefik or your reverse proxy of choice.

Running it

Careful: this CLI script will use sudo rights, please audit it before running it!

./run.sh
FROM abiosoft/caddy:0.11.0
ADD ./Caddyfile /etc/Caddyfile
ADD ./app1.html /serve/index.html
<title>app1</title>
FROM abiosoft/caddy:0.11.0
ADD ./Caddyfile /etc/Caddyfile
ADD ./app2.html /serve/index.html
<title>app2</title>
FROM abiosoft/caddy:0.11.0
ADD ./Caddyfile /etc/Caddyfile
ADD ./app3.html /serve/index.html
<title>app3</title>
:80 {
root /serve
}
version: '3.5'
services:
traefik:
image: traefik:1.7
command: --web --docker --docker.domain=app.test --logLevel=DEBUG
depends_on:
# our setup relies on the 3 apps running. Trying to spin up traefik will bring up those too
- "app1"
- "app2"
- "app3"
ports:
# access this with the correct Host header to access the respective container
- "80:80"
# management UI
- "8080:8080"
volumes:
# traefik does its magic by reading information about running containers from the docker socket
- /var/run/docker.sock:/var/run/docker.sock
- /dev/null:/traefik.toml
networks:
outside-world:
internal-network:
# app1, app2 and app3 are Caddy instances listening to port 80 and serving an index.html.
app1:
build:
context: .
dockerfile: app1-Dockerfile
networks:
internal-network:
# the aliases are not required, but are useful if the applications want to internally
# reference each other by host name
aliases:
- "app1.test"
labels:
- "traefik.port=80"
- "traefik.frontend.rule=Host:app1.test"
app2:
build:
context: .
dockerfile: app2-Dockerfile
networks:
internal-network:
aliases:
- "app2.test"
labels:
- "traefik.port=80"
- "traefik.frontend.rule=Host:app2.test"
app3:
build:
context: .
dockerfile: app3-Dockerfile
networks:
internal-network:
aliases:
- "app3.test"
labels:
- "traefik.port=80"
- "traefik.frontend.rule=Host:app3.test"
networks:
# everything that is *only* on "internal network" cannot talk to WAN
internal-network:
internal: true
# add this network to a container to make it talk to the rest of the world
outside-world:
#!/usr/bin/env bash
set -exuo pipefail
IFS=$'\n\t'
docker-compose up -d
curl -H Host:app1.test http://127.0.0.1
curl -H Host:app2.test http://127.0.0.1
curl -H Host:app3.test http://127.0.0.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment