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 ls

Lets 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 ps

Now 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

 

Add new comment

The content of this field is kept private and will not be shown publicly.
  • No HTML tags allowed.
 dP     dP  .d888b.  dP     dP  .d888b.  dP   dP   dP 
88 .d8' Y8' `88 88 88 Y8' `8P 88 88 88
88aaa8P' `8bad88 88 88 d8bad8b 88 .8P .8P
88 `8b. `88 88 88 88` `88 88 d8' d8'
88 88 d. .88 Y8. .8P 8b. .88 88.d8P8.d8P
dP dP `8888P `Y88888P' Y88888P 8888' Y88'

Enter the code depicted in ASCII art style.