Hi everyone,
I’m experiencing an intermittent issue when deploying a Docker image built using the official frappe_docker
setup with custom apps building, even when installing only one app like erpnext
. I share the most relevants parts.
Dev environment
macOS (Apple M4-pro, Docker Desktop ~3 months old)
custom_apps.json
[
{
"url": "https://github.com/frappe/erpnext.git",
"branch": "version-15"
}
]
build_image.sh
#!/bin/bash
#Ruta a file
RUTA_FILE="../frappe_docker/"
# Verifica si se proporcionó un argumento
if [ -z "$1" ]; then
echo "Use: $0 <image_name>"
exit 1
fi
# Asigna el tag proporcionado como parámetro
IMAGE_TAG=$1
# Verifica si la variable APPS_JSON_BASE64 está definida
if [ -z "$APPS_JSON_BASE64" ]; then
echo "Error: La variable de entorno APPS_JSON_BASE64 no está definida."
echo "Ejecuta primero el script para configurarla."
exit 1
fi
# Construcción de la imagen Docker
docker buildx build --no-cache --platform=linux/amd64 \
--build-arg FRAPPE_BRANCH=version-15 \
--build-arg APPS_JSON_BASE64=$APPS_JSON_BASE64 \
--tag=$IMAGE_TAG \
--file="${RUTA_FILE}images/layered/Containerfile" .
# Verifica si la construcción fue exitosa
if [ $? -eq 0 ]; then
echo "✅ Imagen construida con éxito: $IMAGE_TAG"
else
echo "❌ Error en la construcción de la imagen."
exit 1
fi
Production environment
Linux ubuntu-8gb-nbg1-1 6.8.0-55-generic #57-Ubuntu SMP PREEMPT_DYNAMIC Wed Feb 12 23:42:21 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Everything seems to work fine. After that, I push the image in the repo, and deploy in production.
# Reference: https://github.com/frappe/frappe_docker/blob/main/docs/environment-variables.md
ERPNEXT_VERSION=v15.63.0
DB_PASSWORD=pwd
# Only if you use external database
DB_HOST=mariadb-database
DB_PORT=3306
# Only if you use external Redis
REDIS_CACHE=
REDIS_QUEUE=
# Only with HTTPS override
LETSENCRYPT_EMAIL=admin@mycompany.net
# These environment variables are not required.
# Default value is `$$host` which resolves site by host. For example, if your host is `example.com`,
# site's name should be `example.com`, or if host is `127.0.0.1` (local debugging), it should be `127.0.0.1`.
# This variable allows to override described behavior. Let's say you create site named `mysite`
# and do want to access it by `127.0.0.1` host. Than you would set this variable to `mysite`.
FRAPPE_SITE_NAME_HEADER=test04.mycompany.net
# Default value is `8080`.
HTTP_PUBLISH_PORT=
# Default value is `127.0.0.1`. Set IP address as our trusted upstream address.
UPSTREAM_REAL_IP_ADDRESS=
# Default value is `X-Forwarded-For`. Set request header field whose value will be used to replace the client address
UPSTREAM_REAL_IP_HEADER=
# Allowed values are on|off. Default value is `off`. If recursive search is disabled,
# the original client address that matches one of the trusted addresses
# is replaced by the last address sent in the request header field defined by the real_ip_header directive.
# If recursive search is enabled, the original client address that matches one of the trusted addresses is replaced by the last non-trusted address sent in the request header field.
UPSTREAM_REAL_IP_RECURSIVE=
# All Values Allowed by nginx proxy_read_timeout are allowed, default value is 120s
# Useful if you have longrunning print formats or slow loading sites
PROXY_READ_TIMEOUT=
# All Values allowed by nginx client_max_body_size are allowed, default value is 50m
# Necessary if the upload limit in the frappe application is increased
CLIENT_MAX_BODY_SIZE=
# List of sites for letsencrypt certificates quoted with backtick (`) and separated by comma (,)
# More https://doc.traefik.io/traefik/routing/routers/#rule
# About acme https://doc.traefik.io/traefik/https/acme/#domain-definition
SITES=`test04.mycompany.net`
ROUTER=test04
BENCH_NETWORK=test04
CUSTOM_IMAGE='app_imagen_name'
CUSTOM_TAG='v0.0.1'
I then use:
docker compose --project-name "$PROJECT_NAME" \
--env-file "$ENV_FILE" \
-f ../frappe_docker/compose.yaml \
-f ../frappe_docker/overrides/compose.redis.yaml \
-f ../frappe_docker/overrides/compose.multi-bench.yaml \
-f ../frappe_docker/overrides/compose.multi-bench-ssl.yaml \
config > "$OUTPUT_YAML"
To generate the yaml in production, deploy with:
docker compose --project-name "$PROJECT_NAME" -f "$YAML_FILE" up -d
and init site with something like:
INSTALL_APPS_ARGS=()
for APP in "${APPS[@]}"; do
INSTALL_APPS_ARGS+=(--install-app "$APP")
done
# Ejecuta el comando de creación del sitio con todas las apps
docker compose --project-name "$PROJECT_NAME" exec backend \
bench new-site --mariadb-user-host-login-scope=% \
--db-root-password "$DB_ROOT_PASSWORD" \
"${INSTALL_APPS_ARGS[@]}" \
--admin-password "$ADMIN_PASSWORD" \
"$SITE_NAME"
Key behaviors:
- The first load of the site fails to load some assets (CSS/JS).
- A second reload sometimes loads assets correctly, but other times reverts to missing files again.
- Hashes in the asset filenames change unexpectedly between reloads.
- Happens even with only
erpnext
in the custom build. - No issue when using the default frappe/erpnext image, only when using a custom image via
APPS_JSON_BASE64
. - There are other benches/sites beeing served in the same production host.
- When I was using the previous docker for frappe library, and I deployed a new bench, the old ones got broken. Now, under this new version, the rest of the benches keep on working properly.
If you read all of this — thank you so much! Let me know if you need any more info or want me to test something. I’ll continue debugging until I find the root cause.
Thanks again