At the beginning of times, when the mountains were not so tall I was using simple nginx image, which was exposed to 80 port (8080 or any other) and website was accessible in browser by http://127.0.0.1[:8080] url. Later I found the article where traefik was described and started to use in every docker-compose.yml file. it was used only for one virtual network but with user-friendly urls! http://mywebsite.in-docker.localhost/.
Suddenly the task has come to make two (or more) websites running on local env and to make them see each other by clean urls, made a request, receive responses, check each other health etc. Idea of cloning containers in docker-compose was moved in trash immediatly. Because it's not funny to have nginx-1 + php-1, nginx-2 + php-2 containeers in one docker-compose file. But what if the amount of websites will be changd in future? Not funny to have php-1, php-2,php-3, php-4 there…
The solution of this problem is running the one common network and common Traefik for all websites.
Create file docker-compose.traefik.yml
version: "3"
services:
  traefik:
    image: traefik
    container_name: "my-traefik"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - ./traefik.toml:/etc/traefik/traefik.toml:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
networks:
  default:
    external:
      name: common-traefik
80 port for all websites, 8080 port for Traefik's dashboard.
Important!! file /images-traefik/traefik.toml has the command to enable the dashboard and the network name with dockers to monitor
[api] dashboard = true insecure = true [providers.docker] watch = true network = "common-traefik"
Next we create docker-compose for our websites clones. docker-compose.drupal8.yml
version: '3'
services:
  php-fpm:
    image: php:7.4-fpm-alpine
    container_name: "${PROJECT_NAME}-php-fpm"
    volumes:
      - ../${PROJECT_NAME}:/drupal
    links:
      - mariadb
    labels:
      - "traefik.enable=false"
    networks:
      - default
      - project-network
  web:
    image: nginx:alpine
    container_name: "${PROJECT_NAME}-web"
    expose:
      - '80'
    volumes:
      - ../${PROJECT_NAME}:/drupal
    environment:
      - SERVER_NAME=${PROJECT_NAME}.my-docker.localhost
    links:
      - php-fpm
    labels:
      - traefik.http.routers.${PROJECT_NAME}.rule=Host(`${PROJECT_NAME}.my-docker.localhost`)
    depends_on:
      - php-fpm
    networks:
      - default
      - project-network
  mariadb:
    image: mariadb:10.3
    container_name: "${PROJECT_NAME}-sql"
    environment:
      MYSQL_ROOT_PASSWORD: 'password'
      MYSQL_DATABASE: 'drupal8'
      MYSQL_USER: 'drupal8'
      MYSQL_PASSWORD: 'drupal8'
    command: ['--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci', '--default-authentication-plugin=mysql_native_password']
    labels:
      - "traefik.enable=false"
    cap_add:
      - SYS_NICE
    volumes:
      - db:/var/lib/mysql
    networks:
      - project-network
volumes:
  db:
networks:
  default:
    external:
      name: common-traefik
  project-network:
    name: ${PROJECT_NAME}-network
    internal: true
It's simplfied a lot, you should have more complicated structure. You should pay attention to networks section at the bottom of the file. Our external network is common-traefik.
I think you've noticed variable ${PROJECT_NAME} – it should have own value for each website.
How to use env files for different instances I will show up in another article.
Check the labels in the configs – they provide the rules for websites in Traefik. And make websites visible by labels values.
- traefik.http.routers.${PROJECT_NAME}.rule=Host(`${PROJECT_NAME}.my-docker.localhost`)Before running this all stuff we should create a network for it
$ docker network create \ --driver=bridge \ --attachable \ --internal=false \ common-traefik
Проверяем что сеть создана комнадой. В списке должна быть сеть common-traefik
$ docker network lsLets run our docker with traefik
$ docker-compose --project-name my-traefik --file ./docker-compose.traefik.yml up -d –build
and after everything downloaded and running up successfully we can check it to be sure.
$ docker psNow spin-up our websites:
$ export PROJECT_NAME=website1;docker-compose --project-name ${PROJECT_NAME}--file ./docker-compose.drupal8.yml up -d –build
$ export PROJECT_NAME=website2;docker-compose --project-name ${PROJECT_NAME}--file ./docker-compose.drupal8.yml up -d –build
Great! What's next?
We can check if Traefik's dashboard is working
http://127.0.0.1:8080/dashboard
Check the Routes page and find out there our two instances
http://127.0.0.1:8080/dashboard#/http/routers
paste the urls in browser and smile if it's really works.
http://website1.my-docker.localhost/
http://website2.my-docker.localhost/
Turn that stuff down:
$ export PROJECT_NAME=website1;docker-compose --project-name ${PROJECT_NAME} --file ./docker-compose.drupal8.yml down $ export PROJECT_NAME=website2;docker-compose --project-name ${PROJECT_NAME} --file ./docker-compose.drupal8.yml down $ docker-compose --project-name my-traefik --file ./docker-compose.traefik.yml down
Okay, I agree that copy-paste this stuff in shell is not what you want on your daily job. In some of the next articles I will show you how to use Makefile files.
So, with the help of Traefik and Docker we had a success to run two (or more) websites on local machine, which use the same external virtual network. And both websites are runnong on 80 port with user friendly urls launched from one docker-compose file. Of course this example is just for local environment. Before using it on production you should take care of security!
check the source code here: https://github.com/onesixromcom/docker_traefik_multiple