I have a docker compose file, I want to host my container on example.com:8080
and api.example.com:443
, I can accomplish that goal right now.
However I don't want 2 seperate service for that, I want to eliminate either my_api
or abcxyz
and have 1 service only and accomplish the same behavior, i.e. my container should be hosted at example.com:8080
and not on example.com:443
AND api.example.com:443
but not on api.example.com:8080
Is there a way to do it under 1 service.
version: "3"
services:
traefik:
image: traefik
command:
- --api.dashboard=false
- --api.insecure=false
- --providers.docker
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=web-secure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --entrypoints.web-secure.address=:443
- --entrypoints.spiderman.address=:8080
- --providers.file.directory=/configuration/
- --providers.file.watch=true
ports:
- 80:80
- 443:443
- 8080:8080
volumes:
- ./certificates.yml:/configuration/certificates.yml:ro
- /etc/letsencrypt:/letsencrypt:ro
- /var/run/docker.sock:/var/run/docker.sock
my_api:
image: traefik/whoami
deploy:
replicas: 5
labels:
- "traefik.http.routers.my_api.entrypoints=spiderman"
- "traefik.http.routers.my_api.rule=Host(`example.com`)"
- "traefik.http.routers.my_api.tls=true"
abcxyz:
image: traefik/whoami
deploy:
replicas: 5
labels:
- "traefik.http.routers.abcxyz.entrypoints=web-secure"
- "traefik.http.routers.abcxyz.rule=Host(`api.example.com`)"
- "traefik.http.routers.abcxyz.tls=true"
I could do -
labels:
- "traefik.http.routers.my_api.entrypoints=spiderman,web-secure"
- "traefik.http.routers.my_api.rule=Host(`example.com`,`api.example.com`)"
- "traefik.http.routers.my_api.tls=true"
but it would also serve at example.com:443
which I don't want because i want to host my cool wordpress site there! :)
I think you're looking for something like this:
services:
traefik:
image: traefik
command:
- --api.dashboard=false
- --api.insecure=false
- --providers.docker
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=web-secure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.web.http.redirections.entrypoint.permanent=true
- --entrypoints.web-secure.address=:443
- --entrypoints.spiderman.address=:8080
ports:
- 127.0.0.3:80:80
- 127.0.0.3:443:443
- 127.0.0.3:8080:8080
volumes:
- /run/docker.sock:/run/docker.sock
my_api:
image: traefik/whoami
hostname: my_api
labels:
- traefik.enable=true
- traefik.http.routers.example_com.entrypoints=spiderman
- traefik.http.routers.example_com.rule=Host(`example.com`)
- traefik.http.routers.example_com.service=my_api
- traefik.http.routers.example_com.tls=true
- traefik.http.routers.my_api.entrypoints=web-secure
- traefik.http.routers.my_api.rule=Host(`api.example.com`)
- traefik.http.routers.my_api.tls=true
- traefik.http.services.my_api.loadBalancer.server.port=80
Note that here I've bound everything to local address 127.0.0.3
for testing, but of course that's not necessary; I did that to avoid conflicts with existing services I have listening on ports 80, 443, and 8080.
I've defined this shell function that ensures the various hostname:port combinations resolve correctly (you could edit /etc/hosts
instead to accomplish the same thing) and shows the HTTP status code for each request:
fetch() {
curl -sf \
--resolve api.example.com:443:127.0.0.3 \
--resolve api.example.com:8080:127.0.0.3 \
--resolve example.com:443:127.0.0.3 \
--resolve example.com:8080:127.0.0.3 \
-k -w '%{stderr}%{http_code}\n' $1
}
Using that, let's test our your various requirements.
my container should be hosted at example.com:8080
$ fetch https://example.com:8080 | grep -i host
200
Hostname: my_api
Host: example.com:8080
X-Forwarded-Host: example.com:8081
and not on example.com:443
$ fetch https://example.com:443 | grep -i host
404
AND api.example.com:443
$ fetch https://api.example.com:443 | grep -i host
200
Hostname: my_api
Host: api.example.com
X-Forwarded-Host: api.example.com
but not on api.example.com:8080
$ fetch https://api.example.com:8080 | grep -i host
404
I think that covers your requirements!