DEV Community

Cover image for Multi-host deployment and management using Portainer
Luke
Luke

Posted on • Edited on

Multi-host deployment and management using Portainer

TL;DR

I will simulate a multi-host environment using DinD and then use Portainer for deployment and management.

Prerequisite

  • Installed Docker (If you don't have it, follow the instructions for Windows or Linux)

  • Read previous post to know what I done

Architecture

I will migrate from a single-host to a multi-host architecture.

Architecture

Multi-host

Install Portainer

Step 1: Register 3 nodes free for portainer

  • Click on the link
  • Fill out the form
  • Get an email and save the license key

License Key

Email license key

Step 2: Create docker volume for portainer

docker volume create portainer_data
Enter fullscreen mode Exit fullscreen mode

Step 3: Create network

docker network create portainer-network
Enter fullscreen mode Exit fullscreen mode

Step 4: Run portainer with specify network

docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always --network portainer-network -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ee:lts  
Enter fullscreen mode Exit fullscreen mode

Step 5: Access portainer via localhost:9443/#!/endpoints to create account

register account

Register Account

Step 6: Register license key you get from email

register license key

Register key

home page

Home page

Push image to docker registry

Step 1: Open terminal and run (it will will be prompted to enter Docker ID (username) and password interactively)

docker login
Enter fullscreen mode Exit fullscreen mode

Step 2: Tagging image with the following format <your-username-docker>/<application-name>:<version>. Your username should be the same display on docker

docker hub

For me, username is locnguyenpv

  • FE
docker tag project-management/client-app locnguyenpv/client-app:v1
Enter fullscreen mode Exit fullscreen mode
  • BE
docker tag project-management/project-service locnguyenpv/project-service:v1
docker tag project-management/user-service locnguyenpv/user-service:v1
docker tag project-management/task-service locnguyenpv/task-service:v1
Enter fullscreen mode Exit fullscreen mode

Step 3: Push image to registry by tag

  • FE
docker push locnguyenpv/client-app:v1
Enter fullscreen mode Exit fullscreen mode
  • BE
docker push locnguyenpv/project-service:v1
docker push locnguyenpv/user-service:v1
docker push locnguyenpv/task-service:v1
Enter fullscreen mode Exit fullscreen mode

Connect to DinD

Step 1: Create 2 DinD, one for FE, one for BE

  • FE:
docker run --privileged -d --name project-management-fe --network portainer-network -p 80:80 -p 9002:9001 -p 2377:2375 docker:dind 
Enter fullscreen mode Exit fullscreen mode
  • BE:
docker run --privileged -d --name project-management-be --network portainer-network -p 2376:2375 -p 9001:9001 -p 9099:9099 docker:dind 
Enter fullscreen mode Exit fullscreen mode

Step 2: SSH into each DinD to install Portainer Agent

  • FE:
docker exec -it project-management-fe sh
docker run -d \
  -p 9001:9001 \
  --name portainer_agent \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /var/lib/docker/volumes:/var/lib/docker/volumes \
  -v /:/host \
  portainer/agent:2.27.9
Enter fullscreen mode Exit fullscreen mode
  • BE:
docker exec -it project-management-be sh
docker run -d \
  -p 9001:9001 \
  --name portainer_agent \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /var/lib/docker/volumes:/var/lib/docker/volumes \
  -v /:/host \
  portainer/agent:2.27.9
Enter fullscreen mode Exit fullscreen mode

Step 3: Connect DinD with Portainer
Environment Dashboard

select environment

connect env

connect success

Connect Success

Update docker-compose

Now that I've pushed the image to the Docker registry, I can use it instead of building from source. Replace build from source to pull image from registry

  • FE:
services:
  client-service:
    image: locnguyenpv/client-app:v1
    ports:
      - "80:80"
    restart: always
Enter fullscreen mode Exit fullscreen mode
  • BE:
services:
  mysql-service:
    image: mysql:latest
    container_name: mysql-container
    environment:
      MYSQL_PASSWORD: 123123
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql  # create space for persistence data
      - ./database:/docker-entrypoint-initdb.d # Mount init file into container 
    healthcheck:  # Check every 10s to make sure it work fine
      test: ["CMD-SHELL", "mysqladmin -u root -p$MYSQL_PASSWORD ping -h localhost || exit 1"]
      interval: 30s
      retries: 5
      timeout: 10s
      start_period: 10s
    networks:
      - internal-network

  nginx:
    image: nginx:latest
    container_name: nginx-gateway
    ports:
      - "9099:9099"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro # Mount nginx config from local to container
    depends_on:        # Start condition
      - project-service
      - user-service
      - task-service
    networks:
      - internal-network   # Virtual network
  project-service:
    image: locnguyenpv/project-service:v1
    container_name: project-service-container
    ports:
      - "8081:8081"
    environment:
      MYSQL_HOST: mysql-service
      MYSQL_PORT: 3306
      MYSQL_USER: root
      MYSQL_PASSWORD: 123123
    depends_on:
      mysql-service:
        condition: service_healthy
    networks:
      - internal-network # Virtual network
  user-service:
    image: locnguyenpv/user-service:v1
    container_name: user-service-container
    ports:
      - "8082:8082"
    environment:
      MYSQL_HOST: mysql-service
      MYSQL_PORT: 3306
      MYSQL_USER: root
      MYSQL_PASSWORD: 123123
    depends_on:
      mysql-service:
        condition: service_healthy
    networks:
      - internal-network # Virtual network
  task-service:
    image: locnguyenpv/task-service:v1
    container_name: task-service-container
    ports:
      - "8083:8083"
    environment:
      MYSQL_HOST: mysql-service
      MYSQL_PORT: 3306
      MYSQL_USER: root
      MYSQL_PASSWORD: 123123
    depends_on:
      mysql-service:
        condition: service_healthy
    networks:
      - internal-network # Virtual network

networks:
  internal-network:
      driver: bridge
      name: internal-network

volumes:
  mysql-data: 
Enter fullscreen mode Exit fullscreen mode

Deploy to DinD

Step 1: Go to home page and choose DinD

home page

Step 2: Choose stack

stack

Step 3: Add new stack

add stack

Step 4: Copy & paste docker-compose file into editor

stack editor

Step 5: Deploy

deploy stack

deploy success

Deploy success

Replace those steps for other DinD. All set!

Conclusion

I just show you the way how to simulate multi-host environment by DinD. After that, use Portainer for management and deployment.

Happy Coding

Top comments (0)