I’m new to Traefik and I want to expose two containers to two different ports via Traefik.
- The first container is a ckan service which run on port 5000
- The second container is a jupyter notebook running on port 8000
I mapped the first container to web and secureweb entrypoints via traefik (using port 80 and 443) and it’s working fine.
However, the second container is not exposed even though I mapped it to port 9090 as I did with the previous container. So when I try to open the domain with port 8443 i get (404 page not found).
What I want to achieve is to access both containers’ services via HTTPS:
Here is my docker-compose file:
version: "3"
volumes:
ckan_config:
ckan_home:
ckan_storage:
pg_data:
solr_data:
jn_config:
services:
ckan:
container_name: ckan
image: ckan
build:
context: ./
args:
- CKAN_SITE_URL=${CKAN_SITE_URL}
- CKAN_JUPYTERNOTEBOOK_URL=${CKAN_JUPYTERNOTEBOOK_URL}
- CKAN_CONFIG_L=${CKAN_CONFIG}
- CKAN_HOME_L=${CKAN_HOME}
- CKAN_STORAGE_PATH_L=${CKAN_STORAGE_PATH}
- CKAN_VER=${CKAN_VERSION}
links:
- jupyternotebook
depends_on:
- jupyternotebook
ports:
- "5000:5000"
env_file:
- .env
volumes:
- ckan_config:${CKAN_CONFIG}
- ckan_home:${CKAN_HOME}
- ckan_storage:${CKAN_STORAGE_PATH}
networks:
- ldmnetwork
labels:
- "traefik.enable=true"
- "traefik.http.routers.ckan.rule=Host(`example.com`)"
- "traefik.http.routers.ckan.entrypoints=websecure"
- "traefik.http.routers.ckan.tls.certresolver=myresolver"
- "traefik.http.services.ckan.loadbalancer.server.port=5000"
jupyternotebook:
build:
context: ./jupyternotebook/
args:
- CKAN_JUPYTERNOTEBOOK_URL=${CKAN_JUPYTERNOTEBOOK_URL}
- CKAN_SITE_URL=${CKAN_SITE_URL}
- CKAN_STORAGE_PATH=${CKAN_STORAGE_PATH}
image: jupyter/datascience-notebook
container_name: jupyternotebook
ports:
- "8000:8000"
env_file:
- .env
volumes:
- ckan_storage:${CKAN_STORAGE_PATH}:ro
- jn_config:/home/jovyan/.jupyter
networks:
- ldmnetwork
labels:
- "traefik.enable=true"
- "traefik.http.routers.jupyternotebook.rule=Host(`example.com`)"
- "traefik.http.routers.jupyternotebook.entrypoints=other"
- "traefik.http.routers.jupyternotebook.tls.certresolver=myresolver"
- "traefik.http.services.jupyternotebook.loadbalancer.server.port=8000"
traefik:
# The official v2 Traefik docker image
image: "traefik:latest"
container_name: "traefik"
# Enables the web UI and tells Traefik to listen to docker
command:
- "--api=true"
- "--api.dashboard=true"
- "--log.level=DEBUG"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=ldmnetwork"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.other.address=:9090"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.other.http.redirections.entryPoint.scheme=https"
- "--certificatesresolvers.myresolver.acme.httpchallenge=true"
- "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.myresolver.acme.email=XXXX"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
- "9090:9090"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
labels:
- "traefik.enable=true"
- "traefik.http.routers.api.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.api.service=api@internal"
- "traefik.http.routers.api.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=XXXXX"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.http.routers.api.entrypoints=websecure"
- "traefik.http.routers.api.tls.certresolver=myresolver"
networks:
- "ldmnetwork"
networks:
ldmnetwork:
2
Answers
I found out what's the problem. The traefik configurations were correct. However, after having a look at the logs of traefik, the jupyter notebook container was filtered out because it has an unhealthy status. I put a valid Health Check command in the docker file of the container and now everything is working fine.
So to summarize the problem is that traefik filter out unhealthy docker containers and don't pass traffic unless the status of the docker container is healthy.
Here’s a simple example that does what you want:
With this configuration in place, we can watch the logs from
docker-compose
and see that a request like this:Is serviced by
app1
:And that a request like this:
Is serviced by
app2
:And I think that is what you were asking for.