2
0
mirror of https://github.com/frappe/frappe_docker.git synced 2024-11-10 07:11:00 +00:00
frappe_docker/docs/docker-swarm.md
Revant Nandgaonkar 38be99fc5e docs: organize docs
break down readme into multiple files
organize in docs directory
[skip travis]
2020-06-13 15:33:06 +05:30

12 KiB

Prerequisites

IMPORTANT: All commands are executed on live server with public IP and DNS Configured.

Setup docker swarm

Set hostname

export USE_HOSTNAME=dog.example.com

echo $USE_HOSTNAME > /etc/hostname
hostname -F /etc/hostname

Update packages using tools provided by installed linux distribution.

Example on Ubuntu. Use distro specific commands.

apt-get update -y && apt-get upgrade

Install Docker using official convenience script

# Download Docker
curl -fsSL get.docker.com -o get-docker.sh
# Install Docker using the stable channel (instead of the default "edge")
CHANNEL=stable sh get-docker.sh
# Remove Docker install script
rm get-docker.sh

Setup Swarm Mode

docker swarm init --advertise-addr 111.111.111.111

Note: Select the public IP of the server instead of 111.111.111.111

Add worker nodes. Execute following command from worker node.

docker swarm join --token SWMTKN-1-5tl7ya98erd9qtasdfml4lqbosbhfqv3asdf4p13-dzw6ugasdfk0arn0 111.111.111.111:2377

Note: Replace appropriate token and Public IP of manager in the command.

Install Traefik on manager node

Set environment variables

  • EMAIL=user@domain.com: Letsencrypt Email
  • DOMAIN: Domain for traefik dashboard, e.g. traefik.example.com
  • HASHED_PASSWORD=$(openssl passwd -apr1 $PASSWORD) where PASSWORD is secret string

deploy the following yaml.

docker stack deploy -c traefik.yaml traefik
version: "3.3"

services:
  traefik:
    image: traefik:v2.2
    ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host
    command:
      - --api
      - --log.level=INFO
      - --accesslog=true
      - --metrics.prometheus=true
      - --providers.docker=true
      - --providers.docker.endpoint=unix:///var/run/docker.sock
      - --providers.docker.swarmMode=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=traefik-public
      - --entrypoints.http.address=:80
      - --entrypoints.https.address=:443
      - --certificatesResolvers.certbot=true
      - --certificatesResolvers.certbot.acme.httpChallenge=true
      - --certificatesResolvers.certbot.acme.httpChallenge.entrypoint=http
      - --certificatesResolvers.certbot.acme.email=${EMAIL?Variable EMAIL not set}
      - --certificatesResolvers.certbot.acme.storage=/certs/acme-v2.json
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /data/traefik/certs:/certs
    networks:
      - traefik-public
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
      labels:
        # v2.2
        - "traefik.docker.network=traefik-public"
        - "traefik.enable=true"
        - "traefik.http.services.traefik.loadbalancer.server.port=8080"
        # Http
        - "traefik.http.routers.traefik.rule=Host(`${DOMAIN?Variable DOMAIN not set}`)"
        - "traefik.http.routers.traefik.entrypoints=http,https"
        # Enable Let's encrypt auto certificat creation
        - "traefik.http.routers.traefik.tls.certresolver=certbot"
        # Enable authentification
        - "traefik.http.routers.traefik.middlewares=traefik-auth"
        - "traefik.http.middlewares.traefik-auth.basicauth.users=admin:${HASHED_PASSWORD?Variable HASHED_PASSWORD not set}"
        # Redirect All hosts to HTTPS
        - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
        - "traefik.http.routers.http-catchall.entrypoints=http"
        - "traefik.http.routers.http-catchall.middlewares=redirect-to-https@docker"
        - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
        - "traefik.http.routers.traefik.service=api@internal"
        - "traefik.http.routers.traefik.tls"

networks:
  traefik-public:
    name: traefik-public
    attachable: true
    driver: overlay

Install Portainer

Set environment variable DOMAIN as domain where portainer is located e.g. DOMAIN=portainer.example.com

deploy the following yaml.

docker stack deploy -c portainer.yaml portainer
version: "3.3"

services:
  agent:
    image: portainer/agent:1.5.1
    environment:
      AGENT_CLUSTER_ADDR: tasks.agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes
    networks:
      - agent-network
    deploy:
      mode: global
      placement:
        constraints:
          - node.platform.os == linux

  portainer:
    image: portainer/portainer:1.23.2
    command: -H tcp://tasks.agent:9001 --tlsskipverify
    volumes:
      - portainer-data:/data
    networks:
      - agent-network
      - traefik-public
    deploy:
      placement:
        constraints:
          - node.role == manager
          - node.labels.portainer.portainer-data == true
      labels:
        - "traefik.docker.network=traefik-public"
        - "traefik.enable=true"
        - "traefik.http.services.portainer.loadbalancer.server.port=9000"
        # Http
        - "traefik.http.routers.portainer.rule=Host(`${DOMAIN?Variable DOMAIN not set}`)"
        - "traefik.http.routers.portainer.entrypoints=http,https"
        # Enable Let's encrypt auto certificate creation
        - "traefik.http.routers.portainer.tls.certresolver=certbot"
networks:
  agent-network:
    attachable: true
  traefik-public:
    external: true

volumes:
  portainer-data:

Use Portainer for rest of the guide

Create Config

Configs > Add Config > frappe-mariadb-config

[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

[mysql]
default-character-set = utf8mb4

Create Secret

Secret > Add Secret > frappe-mariadb-root-password

longsecretpassword

Note down this password. It is only available in mariadb containers at location /run/secrets/frappe-mariadb-root-password later

Deploy MariaDB Replication

Stacks > Add Stacks > frappe-mariadb

version: "3.7"

services:
  mariadb-master:
    image: 'bitnami/mariadb:10.3'
    deploy:
      restart_policy:
        condition: on-failure
    configs:
      - source: frappe-mariadb-config
        target: /opt/bitnami/mariadb/conf/bitnami/my_custom.cnf
    networks:
      - frappe-network
    secrets:
      - frappe-mariadb-root-password
    volumes:
      - 'mariadb_master_data:/bitnami/mariadb'
    environment:
      - MARIADB_REPLICATION_MODE=master
      - MARIADB_REPLICATION_USER=repl_user
      - MARIADB_REPLICATION_PASSWORD_FILE=/run/secrets/frappe-mariadb-root-password
      - MARIADB_ROOT_PASSWORD_FILE=/run/secrets/frappe-mariadb-root-password

  mariadb-slave:
    image: 'bitnami/mariadb:10.3'
    deploy:
      restart_policy:
        condition: on-failure
    configs:
      - source: frappe-mariadb-config
        target: /opt/bitnami/mariadb/conf/bitnami/my_custom.cnf
    networks:
      - frappe-network
    secrets:
      - frappe-mariadb-root-password
    volumes:
      - 'mariadb_slave_data:/bitnami/mariadb'
    environment:
      - MARIADB_REPLICATION_MODE=slave
      - MARIADB_REPLICATION_USER=repl_user
      - MARIADB_REPLICATION_PASSWORD_FILE=/run/secrets/frappe-mariadb-root-password
      - MARIADB_MASTER_HOST=mariadb-master
      - MARIADB_MASTER_PORT_NUMBER=3306
      - MARIADB_MASTER_ROOT_PASSWORD_FILE=/run/secrets/frappe-mariadb-root-password

volumes:
  mariadb_master_data:
  mariadb_slave_data:

configs:
  frappe-mariadb-config:
    external: true

secrets:
  frappe-mariadb-root-password:
    external: true

networks:
  frappe-network:
    name: frappe-network
    attachable: true

Deploy Frappe/ERPNext

Stacks > Add Stacks > frappe-bench-v12

version: "3"

services:
  redis-cache:
    image: redis:latest
    volumes:
      - redis-cache-vol:/data
    deploy:
      restart_policy:
        condition: on-failure
    networks:
      - frappe-network

  redis-queue:
    image: redis:latest
    volumes:
      - redis-queue-vol:/data
    deploy:
      restart_policy:
        condition: on-failure
    networks:
      - frappe-network

  redis-socketio:
    image: redis:latest
    volumes:
      - redis-socketio-vol:/data
    deploy:
      restart_policy:
        condition: on-failure
    networks:
      - frappe-network

  erpnext-nginx:
    image: frappe/erpnext-nginx:v12.7.1
    environment:
      - FRAPPE_PY=erpnext-python
      - FRAPPE_PY_PORT=8000
      - FRAPPE_SOCKETIO=frappe-socketio
      - SOCKETIO_PORT=9000
    volumes:
      - sites-vol:/var/www/html/sites:rw
      - assets-vol:/assets:rw
    networks:
      - frappe-network
      - traefik-public
    deploy:
      restart_policy:
        condition: on-failure
      labels:
        - "traefik.docker.network=traefik-public"
        - "traefik.enable=true"
        - "traefik.http.services.frappe-bench-v12.loadbalancer.server.port=80"
        # Http
        - "traefik.http.routers.frappe-bench-v12.rule=Host(${SITES?Variable SITES not set})"
        - "traefik.http.routers.frappe-bench-v12.entrypoints=http,https"
        # Enable Let's encrypt auto certificate creation
        - "traefik.http.routers.frappe-bench-v12.tls.certresolver=certbot"

  erpnext-python:
    image: frappe/erpnext-worker:v12.7.1
    deploy:
      restart_policy:
        condition: on-failure
    environment:
      - MARIADB_HOST=${MARIADB_HOST?Variable MARIADB_HOST not set}
      - REDIS_CACHE=redis-cache:6379
      - REDIS_QUEUE=redis-queue:6379
      - REDIS_SOCKETIO=redis-socketio:6379
      - SOCKETIO_PORT=9000
      - AUTO_MIGRATE=1
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw
      - assets-vol:/home/frappe/frappe-bench/sites/assets:rw
    networks:
      - frappe-network

  frappe-socketio:
    image: frappe/frappe-socketio:v12.5.1
    deploy:
      restart_policy:
        condition: on-failure
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw
    networks:
      - frappe-network

  frappe-worker-default:
    image: frappe/erpnext-worker:v12.7.1
    deploy:
      restart_policy:
        condition: on-failure
    command: worker
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw
    networks:
      - frappe-network

  frappe-worker-short:
    image: frappe/erpnext-worker:v12.7.1
    deploy:
      restart_policy:
        condition: on-failure
    command: worker
    environment:
      - WORKER_TYPE=short
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw
    networks:
      - frappe-network

  frappe-worker-long:
    image: frappe/erpnext-worker:v12.7.1
    deploy:
      restart_policy:
        condition: on-failure
    command: worker
    environment:
      - WORKER_TYPE=long
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw
    networks:
      - frappe-network

  frappe-schedule:
    image: frappe/erpnext-worker:v12.7.1
    deploy:
      restart_policy:
        condition: on-failure
    command: schedule
    volumes:
      - sites-vol:/home/frappe/frappe-bench/sites:rw
    networks:
      - frappe-network

volumes:
  redis-cache-vol:
  redis-queue-vol:
  redis-socketio-vol:
  assets-vol:
  sites-vol:

networks:
  traefik-public:
    external: true
  frappe-network:
    external: true

Use environment variables:

  • MARIADB_HOST=frappe-mariadb_mariadb-master
  • SITES variable is list of sites in back tick and separated by comma
SITES=`site1.example.com`,`site2.example.com`

Create new site job

  1. Containers > Add Container > add-site1-example-com
  2. Select Image frappe/erpnext-worker:v12
  3. Set command as new
  4. Select network frappe-network
  5. Select Volume frappe-bench-v12_sites_vol and mount in container /home/frappe/frappe-bench/sites
  6. Env variables:
    • MYSQL_ROOT_PASSWORD=longsecretpassword
    • SITE_NAME=site1.example.com
  7. Start container

Migrate Sites job

  1. Containers > Add Container > migrate-sites
  2. Select Image frappe/erpnext-worker:v12
  3. Set command as migrate
  4. Select network frappe-network
  5. Select Volume frappe-bench-v12_sites_vol and mount in container /home/frappe/frappe-bench/sites
  6. Env variables:
    • MAINTENANCE_MODE=1
  7. Start container