A Step-by-Step Guide to Running Frappe ERPNext System in Docker Containers

Introduction: In the dynamic landscape of enterprise resource planning, ERPNext stands out as a versatile and powerful solution. To streamline the deployment process and enhance flexibility, utilizing Frappe Docker is a practical approach. This guide will walk you through the step-by-step process of setting up ERPNext using Frappe Docker, including the installation of custom apps for tailored functionality.

Prerequisites: Before diving into the installation process, ensure that you have Docker and Docker Compose installed on your system. Familiarity with ERPNext and Frappe framework basics is also recommended.

Also, install Docker Compose:

A Comprehensive Guide to Installing Docker CE on Various Linux Systems

Start and enable the service:

sudo usermod -aG docker $USER
newgrp docker
sudo systemctl start docker && sudo systemctl enable docker

Step 1: Clone Frappe Docker Repository

Begin by cloning the Frappe Docker repository from GitHub. Open your terminal and execute the following command:

Now clone the frappe_docker repo for the needed YAML files.

cd ~/
git clone https://github.com/frappe/frappe_docker
cd frappe_docker

Once in the directory, create a directory for resources and configs.

mkdir ~/gitops

Ensure OpenSSL is installed:

##On Debian/Ubuntu
sudo apt install openssl

##On CentOS/Rocky/Alma Linux
sudo yum install openssl

#2. Install Traefik Ingress

Traefik ingress acts as an internal load balancer for multiple benches and sites hosted on the server. It will be used to expose port 80 or 443 and also take care of Letsencrypt automation for all sites installed on the server.

In this guide, we will expose port 80 but it is also possible to provide an FQDN for SSL encryption.

First, export the variables for the domain name and Letsencrypt notification email:

echo 'TRAEFIK_DOMAIN=traefik.example.com' > ~/gitops/traefik.env
echo 'EMAIL=admin@example.com' >> ~/gitops/traefik.env
echo 'HASHED_PASSWORD='$(openssl passwd -apr1 Passw0rd | sed 's/\$/\\\$/g') >> ~/gitops/traefik.env

This will create a file at ~/gitops/traefik.env with the above variables. You must ensure that your DNS entry points to the Server IP.

$ sudo vim /etc/hosts
192.168.205.11 traefik.example.com

Once created, you can use the file to run a Traefik container as shown.

docker compose --project-name traefik \
  --env-file ~/gitops/traefik.env \
  -f overrides/compose.traefik.yaml up -d

If you have an FQDN, and you want to run the container with SSL automation, (expose port 443)you need to include the compose.traefik-ssl.yaml as shown:

docker compose --project-name traefik \
  --env-file ~/gitops/traefik.env \
  -f overrides/compose.traefik.yaml \
  -f overrides/compose.traefik-ssl.yaml up -d

Verify if the container is running:

$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                               NAMES
f4c7000a029c   traefik:v2.6   "/entrypoint.sh --pr…"   24 seconds ago   Up 22 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   traefik-traefik-1

#3. Install MariaDB Database

In this setup, we will deploy a single MariaDB database instance that will serve as a database service for all the benches and projects installed on the server.

Create an environment file in ~/gitops

echo "DB_PASSWORD=StrongPassw0rd" > ~/gitops/mariadb.env

Change StrongPassw0rd to a preferred password for the database.

Now start the container using Docker Compose as shown:

docker compose --project-name mariadb --env-file ~/gitops/mariadb.env -f overrides/compose.mariadb-shared.yaml up -d

Once created, check if the container is running:

$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED              STATUS                            PORTS                               NAMES
18692eeb5c15   mariadb:10.6   "docker-entrypoint.s…"   7 seconds ago    Up 6 seconds (healthy)   3306/tcp                            mariadb-database
f4c7000a029c   traefik:v2.6   "/entrypoint.sh --pr…"   About a minute ago   Up About a minute                 0.0.0.0:80->80/tcp, :::80->80/tcp   traefik-traefik-1

You will all have the data persist in the directory ${HOME}/data/mariadb

#4. Create Persistent Volumes

For ERPNext to persist its data, we need to create and map the volumes correctly. For this guide, I will create a data directory at /mnt/data

Create the persistent volume:

ADVERTISING

Ezoic

sudo mkdir -p /mnt/data/sites

Set the required permissions:

sudo chmod 775 -R /mnt/data
sudo chown -R $USER:docker /mnt/data

On RHEL-based systems, set SELinux in permissive mode:

sudo setenforce 0
sudo sed -i 's/^SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config

Now create the docker volume for sites

docker volume create --driver local \
     --opt type=none \
     --opt device=/mnt/data/sites \
     --opt o=bind sites

Once created, verify with the command:

$ docker volume list
DRIVER    VOLUME NAME
local     sites 
.......

#5. Run ERPNext ERP System on Docker

The ERPNext instance creates its Redis, socketio, Gunicorn, Nginx, workers, and scheduler. It will use the internal MariaDB network to connect to the running instance and expose the service using Traefik.

We will begin by creating a bench with the name erpnext-one with two sites named one.example.com and two.example.com.

cp example.env ~/gitops/erpnext-one.env
sed -i 's/DB_PASSWORD=123/DB_PASSWORD=StrongPassw0rd/g' ~/gitops/erpnext-one.env
sed -i 's/DB_HOST=/DB_HOST=mariadb-database/g' ~/gitops/erpnext-one.env
sed -i 's/DB_PORT=/DB_PORT=3306/g' ~/gitops/erpnext-one.env
echo 'ROUTER=erpnext-one' >> ~/gitops/erpnext-one.env
echo "SITES=\`one.example.com\`,\`two.example.com\`" >> ~/gitops/erpnext-one.env
echo "BENCH_NETWORK=erpnext-one" >> ~/gitops/erpnext-one.env

After these commands, you will have an environment file created as ~/gitops/erpnext-one.env.

Also, create a YAML file in the ~/gitops directory.

  • For HTTP:
docker compose --project-name erpnext-one \
  --env-file ~/gitops/erpnext-one.env \
  -f compose.yaml \
  -f overrides/compose.redis.yaml \
  -f overrides/compose.multi-bench.yaml config > ~/gitops/erpnext-one.yaml
  • For HTTPS
docker compose --project-name erpnext-one \
  --env-file ~/gitops/erpnext-one.env \
  -f compose.yaml \
  -f overrides/compose.redis.yaml \
  -f overrides/compose.multi-bench.yaml \
  -f overrides/compose.multi-bench-ssl.yaml config > ~/gitops/erpnext-one.yaml

Modify your compose YAML file to accommodate the volumes created:

vim compose.yaml

At the end of the file, make the below modifications on the volumes:

# ERPNext requires local assets access (Frappe does not)
volumes:
  sites:
    external: true

You can now spin the container using the configs:

docker compose --project-name erpnext-one -f ~/gitops/erpnext-one.yaml up -d

Check if the containers created are running:

$ docker ps
CONTAINER ID   IMAGE                     COMMAND                  CREATED          STATUS                   PORTS                               NAMES
da4cfc1b874f   frappe/erpnext:v14.29.1   "nginx-entrypoint.sh"    21 seconds ago   Up 4 seconds                                                 erpnext-one-frontend-1
1a999b50b096   frappe/erpnext:v14.29.1   "node /home/frappe/f…"   21 seconds ago   Up 6 seconds                                                 erpnext-one-websocket-1
b0fae8a010ba   frappe/erpnext:v14.29.1   "/home/frappe/frappe…"   21 seconds ago   Up 6 seconds                                                 erpnext-one-backend-1
a566f522bbc2   frappe/erpnext:v14.29.1   "bench schedule"         21 seconds ago   Up 5 seconds                                                 erpnext-one-scheduler-1
a974b313570b   frappe/erpnext:v14.29.1   "bench worker --queu…"   21 seconds ago   Up 5 seconds                                                 erpnext-one-queue-short-1
4b88d00b8b2b   frappe/erpnext:v14.29.1   "bench worker --queu…"   21 seconds ago   Up 6 seconds                                                 erpnext-one-queue-default-1
380d8ae1399d   frappe/erpnext:v14.29.1   "bench worker --queu…"   21 seconds ago   Up 6 seconds                                                 erpnext-one-queue-long-1
4c14b3e32141   redis:6.2-alpine          "docker-entrypoint.s…"   21 seconds ago   Up 19 seconds            6379/tcp                            erpnext-one-redis-socketio-1
3388eba79163   redis:6.2-alpine          "docker-entrypoint.s…"   21 seconds ago   Up 19 seconds            6379/tcp                            erpnext-one-redis-cache-1
eb140fd2bcfa   redis:6.2-alpine          "docker-entrypoint.s…"   21 seconds ago   Up 19 seconds            6379/tcp                            erpnext-one-redis-queue-1
18692eeb5c15   mariadb:10.6              "docker-entrypoint.s…"   7 minutes ago    Up 7 minutes (healthy)   3306/tcp                            mariadb-database
700b6fb1b9ac   traefik:v2.6              "/entrypoint.sh --pr…"   8 minutes ago    Up 8 minutes             0.0.0.0:80->80/tcp, :::80->80/tcp   traefik-traefik-1

Now create the sites.

docker compose --project-name erpnext-one exec backend \
  bench new-site one.example.com --mariadb-root-password StrongPassw0rd --install-app erpnext --admin-password StrongPassw0rd

You can only proceed with this option if you need a single bench multi-site setup.

docker compose --project-name erpnext-one exec backend \
  bench new-site two.example.com --mariadb-root-password StrongPassw0rd --install-app erpnext --admin-password StrongPassw0rd

#6. Access the ERPNext ERP System WebUI

At this point, you can access any of your sites created on the beach with the URL. For example http://one.example.com or https://one.example.com

I assume that you have and DNS entry pointing to the Server IP. For example:

$ sudo vim /etc/hosts
192.168.205.11 one.example.com

You need to log in using the created admin password for the site as shown:

Conclusion: Setting up ERPNext using Frappe Docker streamlines the deployment process, enhances scalability, and facilitates customization. By incorporating custom apps, organizations can tailor ERP functionality to meet specific business requirements. This guide empowers users to navigate the intricacies of Frappe Docker, unlocking the full potential of ERPNext for their unique needs.

Feel free to adapt and expand upon these steps based on your specific use case, and embark on a seamless ERPNext journey with Frappe Docker.