Hello, I have ERPNext installed using the templates inside Dokploy. The instance works perfectly at first, but after about 5–15 days, all the assets (CSS and JS) suddenly stop working. This has happened three times now. After installation, everything runs fine for a while, then the assets fail to load, and I have to reinstall which is very frustrating.
Here are my observations:
The website requests these asset files:
website.bundle.NSZNBQCJ.css
login.bundle.IGORFKYS.css
frappe-web.bundle.4QVP5SVA.js
frappe-web.bundle.4QVP5SVA.js
However, the assets.json file points to completely different file names.
frappe@31efd83389d8:/$ cat /home/frappe/frappe-bench/sites/assets/assets.json
{
"billing.bundle.js": "/assets/frappe/dist/js/billing.bundle.QQE2RPCA.js",
"bootstrap-4-web.bundle.js": "/assets/frappe/dist/js/bootstrap-4-web.bundle.FOZOVELL.js",
"controls.bundle.js": "/assets/frappe/dist/js/controls.bundle.NZC3GXOU.js",
"data_import_tools.bundle.js": "/assets/frappe/dist/js/data_import_tools.bundle.IGMLQRF6.js",
"desk.bundle.js": "/assets/frappe/dist/js/desk.bundle.IMPJIRYH.js",
"dialog.bundle.js": "/assets/frappe/dist/js/dialog.bundle.YHWHYNFQ.js",
"form.bundle.js": "/assets/frappe/dist/js/form.bundle.7PHQTBOA.js",
"frappe-web.bundle.js": "/assets/frappe/dist/js/frappe-web.bundle.5RBX33XN.js",
"libs.bundle.js": "/assets/frappe/dist/js/libs.bundle.TIV7ZGVY.js",
"list.bundle.js": "/assets/frappe/dist/js/list.bundle.ET452RHV.js",
"logtypes.bundle.js": "/assets/frappe/dist/js/logtypes.bundle.EKN7LWKW.js",
"onboarding_tours.bundle.js": "/assets/frappe/dist/js/onboarding_tours.bundle.RAUR6X4Z.js",
"report.bundle.js": "/assets/frappe/dist/js/report.bundle.AMKILTJH.js",
"sentry.bundle.js": "/assets/frappe/dist/js/sentry.bundle.AX44GVWW.js",
"telemetry.bundle.js": "/assets/frappe/dist/js/telemetry.bundle.LKEZCADB.js",
"user_profile_controller.bundle.js": "/assets/frappe/dist/js/user_profile_controller.bundle.TPZWXYWN.js",
"video_player.bundle.js": "/assets/frappe/dist/js/video_player.bundle.DUYYLSFO.js",
"web_form.bundle.js": "/assets/frappe/dist/js/web_form.bundle.5DVA6C7G.js",
"form_builder.bundle.js": "/assets/frappe/dist/js/form_builder.bundle.CYK52TRC.js",
"print_format_builder.bundle.js": "/assets/frappe/dist/js/print_format_builder.bundle.3YCNST3U.js",
"workflow_builder.bundle.js": "/assets/frappe/dist/js/workflow_builder.bundle.3GDVTW3J.js",
"build_events.bundle.js": "/assets/frappe/dist/js/build_events.bundle.BCX32TWL.js",
"file_uploader.bundle.js": "/assets/frappe/dist/js/file_uploader.bundle.IO2BUJDB.js",
"kanban_board.bundle.js": "/assets/frappe/dist/js/kanban_board.bundle.FBBHCLAN.js",
"desk.bundle.css": "/assets/frappe/dist/css/desk.bundle.YEWO6UTN.css",
"email.bundle.css": "/assets/frappe/dist/css/email.bundle.NAP7GUIG.css",
"login.bundle.css": "/assets/frappe/dist/css/login.bundle.EEV2YCSU.css",
"print.bundle.css": "/assets/frappe/dist/css/print.bundle.5UWPJEM3.css",
"print_format.bundle.css": "/assets/frappe/dist/css/print_format.bundle.NVW3TB2Z.css",
"report.bundle.css": "/assets/frappe/dist/css/report.bundle.GC4I5GYW.css",
"web_form.bundle.css": "/assets/frappe/dist/css/web_form.bundle.7LGJLN7Y.css",
"website.bundle.css": "/assets/frappe/dist/css/website.bundle.QFVSUF2X.css",
"bank-reconciliation-tool.bundle.js": "/assets/erpnext/dist/js/bank-reconciliation-tool.bundle.PQSY2TRN.js",
"erpnext-web.bundle.js": "/assets/erpnext/dist/js/erpnext-web.bundle.J4A2DQB4.js",
"erpnext.bundle.js": "/assets/erpnext/dist/js/erpnext.bundle.F4VLHMIR.js",
"item-dashboard.bundle.js": "/assets/erpnext/dist/js/item-dashboard.bundle.33GEOV2J.js",
"point-of-sale.bundle.js": "/assets/erpnext/dist/js/point-of-sale.bundle.JTJY4AB2.js",
"bom_configurator.bundle.js": "/assets/erpnext/dist/js/bom_configurator.bundle.VB3HBFNX.js",
"erpnext-web.bundle.css": "/assets/erpnext/dist/css/erpnext-web.bundle.6B3MDDZU.css",
"erpnext.bundle.css": "/assets/erpnext/dist/css/erpnext.bundle.JQ7CB7T3.css",
"erpnext_email.bundle.css": "/assets/erpnext/dist/css/erpnext_email.bundle.47GDA6MO.css"
}
Also, the /assets directory actually contains the files listed in assets.json, but the website still tries to load the wrong ones.
This is the compose file from the template
x-custom-image: &custom_image
image: ${IMAGE_NAME:-docker.io/frappe/erpnext}:${VERSION:-version-15}
pull_policy: ${PULL_POLICY:-always}
deploy:
restart_policy:
condition: always
services:
backend:
<<: *custom_image
volumes:
- sites:/home/frappe/frappe-bench/sites
networks:
- bench-network
healthcheck:
test:
- CMD
- wait-for-it
- '0.0.0.0:8000'
interval: 2s
timeout: 10s
retries: 30
frontend:
<<: *custom_image
command:
- nginx-entrypoint.sh
depends_on:
backend:
condition: service_started
required: true
websocket:
condition: service_started
required: true
environment:
BACKEND: backend:8000
FRAPPE_SITE_NAME_HEADER: ${FRAPPE_SITE_NAME_HEADER:-$$host}
SOCKETIO: websocket:9000
UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
UPSTREAM_REAL_IP_RECURSIVE: "off"
volumes:
- sites:/home/frappe/frappe-bench/sites
networks:
- bench-network
healthcheck:
test:
- CMD
- wait-for-it
- '0.0.0.0:8080'
interval: 2s
timeout: 30s
retries: 30
queue-default:
<<: *custom_image
command:
- bench
- worker
- --queue
- default
volumes:
- sites:/home/frappe/frappe-bench/sites
networks:
- bench-network
healthcheck:
test:
- CMD
- wait-for-it
- 'redis-queue:6379'
interval: 2s
timeout: 10s
retries: 30
depends_on:
configurator:
condition: service_completed_successfully
required: true
queue-long:
<<: *custom_image
command:
- bench
- worker
- --queue
- long
volumes:
- sites:/home/frappe/frappe-bench/sites
networks:
- bench-network
healthcheck:
test:
- CMD
- wait-for-it
- 'redis-queue:6379'
interval: 2s
timeout: 10s
retries: 30
depends_on:
configurator:
condition: service_completed_successfully
required: true
queue-short:
<<: *custom_image
command:
- bench
- worker
- --queue
- short
volumes:
- sites:/home/frappe/frappe-bench/sites
networks:
- bench-network
healthcheck:
test:
- CMD
- wait-for-it
- 'redis-queue:6379'
interval: 2s
timeout: 10s
retries: 30
depends_on:
configurator:
condition: service_completed_successfully
required: true
scheduler:
<<: *custom_image
healthcheck:
test:
- CMD
- wait-for-it
- 'redis-queue:6379'
interval: 2s
timeout: 10s
retries: 30
command:
- bench
- schedule
depends_on:
configurator:
condition: service_completed_successfully
required: true
volumes:
- sites:/home/frappe/frappe-bench/sites
networks:
- bench-network
websocket:
<<: *custom_image
healthcheck:
test:
- CMD
- wait-for-it
- '0.0.0.0:9000'
interval: 2s
timeout: 10s
retries: 30
command:
- node
- /home/frappe/frappe-bench/apps/frappe/socketio.js
depends_on:
configurator:
condition: service_completed_successfully
required: true
volumes:
- sites:/home/frappe/frappe-bench/sites
networks:
- bench-network
configurator:
<<: *custom_image
deploy:
mode: replicated
replicas: ${CONFIGURE:-0}
restart_policy:
condition: none
entrypoint: ["bash", "-c"]
command:
- >
[[ $${REGENERATE_APPS_TXT} == "1" ]] && ls -1 apps > sites/apps.txt;
[[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && exit 0;
bench set-config -g db_host $$DB_HOST;
bench set-config -gp db_port $$DB_PORT;
bench set-config -g redis_cache "redis://$$REDIS_CACHE";
bench set-config -g redis_queue "redis://$$REDIS_QUEUE";
bench set-config -g redis_socketio "redis://$$REDIS_QUEUE";
bench set-config -gp socketio_port $$SOCKETIO_PORT;
environment:
DB_HOST: "${DB_HOST:-db}"
DB_PORT: "3306"
REDIS_CACHE: redis-cache:6379
REDIS_QUEUE: redis-queue:6379
SOCKETIO_PORT: "9000"
REGENERATE_APPS_TXT: "${REGENERATE_APPS_TXT:-0}"
volumes:
- sites:/home/frappe/frappe-bench/sites
networks:
- bench-network
create-site:
<<: *custom_image
deploy:
mode: replicated
replicas: ${CREATE_SITE:-0}
restart_policy:
condition: none
entrypoint: ["bash", "-c"]
command:
- >
wait-for-it -t 120 $$DB_HOST:$$DB_PORT;
wait-for-it -t 120 redis-cache:6379;
wait-for-it -t 120 redis-queue:6379;
export start=`date +%s`;
until [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && \
[[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_cache // empty"` ]] && \
[[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_queue // empty"` ]];
do
echo "Waiting for sites/common_site_config.json to be created";
sleep 5;
if (( `date +%s`-start > 120 )); then
echo "could not find sites/common_site_config.json with required keys";
exit 1
fi
done;
echo "sites/common_site_config.json found";
[[ -d "sites/${SITE_NAME}" ]] && echo "${SITE_NAME} already exists" && exit 0;
bench new-site --mariadb-user-host-login-scope='%' --admin-password=$${ADMIN_PASSWORD} --db-root-username=root --db-root-password=$${DB_ROOT_PASSWORD} $${INSTALL_APP_ARGS} $${SITE_NAME};
volumes:
- sites:/home/frappe/frappe-bench/sites
environment:
SITE_NAME: ${SITE_NAME}
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
DB_HOST: ${DB_HOST:-db}
DB_PORT: "${DB_PORT:-3306}"
DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
INSTALL_APP_ARGS: ${INSTALL_APP_ARGS}
networks:
- bench-network
migration:
<<: *custom_image
deploy:
mode: replicated
replicas: ${MIGRATE:-0}
restart_policy:
condition: none
entrypoint: ["bash", "-c"]
command:
- >
curl -f http://${SITE_NAME}:8080/api/method/ping || echo "Site busy" && exit 0;
bench --site all set-config -p maintenance_mode 1;
bench --site all set-config -p pause_scheduler 1;
bench --site all migrate;
bench --site all set-config -p maintenance_mode 0;
bench --site all set-config -p pause_scheduler 0;
volumes:
- sites:/home/frappe/frappe-bench/sites
networks:
- bench-network
db:
image: mariadb:10.6
deploy:
mode: replicated
replicas: ${ENABLE_DB:-0}
restart_policy:
condition: always
healthcheck:
test: mysqladmin ping -h localhost --password=${DB_ROOT_PASSWORD}
interval: 1s
retries: 20
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --skip-character-set-client-handshake
- --skip-innodb-read-only-compressed
environment:
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
- MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
volumes:
- db-data:/var/lib/mysql
networks:
- bench-network
redis-cache:
deploy:
restart_policy:
condition: always
image: redis:6.2-alpine
networks:
- bench-network
healthcheck:
test:
- CMD
- redis-cli
- ping
interval: 5s
timeout: 5s
retries: 3
redis-queue:
deploy:
restart_policy:
condition: always
image: redis:6.2-alpine
volumes:
- redis-queue-data:/data
networks:
- bench-network
healthcheck:
test:
- CMD
- redis-cli
- ping
interval: 5s
timeout: 5s
retries: 3
redis-socketio:
deploy:
restart_policy:
condition: always
image: redis:6.2-alpine
volumes:
- redis-socketio-data:/data
networks:
- bench-network
healthcheck:
test:
- CMD
- redis-cli
- ping
interval: 5s
timeout: 5s
retries: 3
volumes:
db-data:
redis-queue-data:
redis-socketio-data:
sites:
driver_opts:
type: "${SITE_VOLUME_TYPE}"
o: "${SITE_VOLUME_OPTS}"
device: "${SITE_VOLUME_DEV}"
networks:
bench-network:
Things I’ve already tried:
bench buildbench restartbench clear-cachebench clear-website-cache- Verified file permissions belong to the
frappeuser - Cleared and disabled Redis cache
- Removed Redis cache volume
- Restarted the machine
None of these helped.
I’ve checked every related discussion on the forums, but I still can’t find the root cause. I need to understand why this keeps happening and how to apply a permanent fix. Thanks.