Issue with Custom Docker Build for ERPNext with Additional Apps

Hello everyone,

I am trying to build a custom Docker image for ERPNext along with the HRMS app on version 15. Here is the command sequence I’m using:

$ git clone https://github.com/frappe/frappe_docker && cd frappe_docker
$ export APPS_JSON='[
  {
    "url": "https://github.com/frappe/erpnext",
    "branch": "version-15"
  },
  {
    "url": "https://github.com/frappe/hrms",
    "branch": "version-15"
  }
]'
$ export APPS_JSON_BASE64=$(echo ${APPS_JSON} | base64 -w 0)
$ docker build \
  --build-arg=FRAPPE_PATH=https://github.com/frappe/frappe \
  --build-arg=FRAPPE_BRANCH=version-15 \
  --build-arg=PYTHON_VERSION=3.11 \
  --build-arg=NODE_VERSION=18 \
  --build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
  --tag=custom/hrms:1.0.0 \
  --file=images/custom/Containerfile .

However, I’m encountering a build error during the Docker image creation. It seems to be related to the bench init command in the Dockerfile, specifically when attempting to use the base64 encoded APPS_JSON. Here is the error message:

79.61 $ yarn install --check-files --verbose
80.62 Traceback (most recent call last):
80.62   File "/usr/local/lib/python3.11/site-packages/bench/commands/make.py", line 75, in init
80.62     init(
80.62   File "/usr/local/lib/python3.11/site-packages/bench/utils/render.py", line 105, in wrapper_fn
80.62     return fn(*args, **kwargs)
80.62            ^^^^^^^^^^^^^^^^^^^
80.62   File "/usr/local/lib/python3.11/site-packages/bench/utils/system.py", line 87, in init
80.62     get_app(
80.62   File "/usr/local/lib/python3.11/site-packages/bench/app.py", line 777, in get_app
80.62     app.install(verbose=verbose, skip_assets=skip_assets, restart_bench=restart_bench)
80.62   File "/usr/local/lib/python3.11/site-packages/bench/utils/render.py", line 126, in wrapper_fn
80.62     return fn(*args, **kwargs)
80.62            ^^^^^^^^^^^^^^^^^^^
80.62   File "/usr/local/lib/python3.11/site-packages/bench/app.py", line 254, in install
80.62     install_app(
80.62   File "/usr/local/lib/python3.11/site-packages/bench/app.py", line 920, in install_app
80.62     bench.run(yarn_install, cwd=app_path)
80.62   File "/usr/local/lib/python3.11/site-packages/bench/bench.py", line 48, in run
80.62     return exec_cmd(cmd, cwd=cwd or self.cwd, _raise=_raise)
80.62            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
80.62   File "/usr/local/lib/python3.11/site-packages/bench/utils/__init__.py", line 174, in exec_cmd
80.62     return_code = subprocess.call(spl_cmd, cwd=cwd, universal_newlines=True, env=env)
80.62                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
80.62   File "/usr/local/lib/python3.11/subprocess.py", line 389, in call
80.62     with Popen(*popenargs, **kwargs) as p:
80.62          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
80.62   File "/usr/local/lib/python3.11/subprocess.py", line 1026, in __init__
80.62     self._execute_child(args, executable, preexec_fn, close_fds,
80.62   File "/usr/local/lib/python3.11/subprocess.py", line 1955, in _execute_child
80.62     raise child_exception_type(errno_num, err_msg, err_filename)
80.62 FileNotFoundError: [Errno 2] No such file or directory: 'yarn'
80.62
80.62 ERROR: There was a problem while creating /home/frappe/frappe-bench
80.62 Do you want to rollback these changes? [y/N]: Aborted!
------
Containerfile:117
--------------------
 116 |     ARG FRAPPE_PATH=https://github.com/frappe/frappe
 117 | >>> RUN export APP_INSTALL_ARGS="" && \
 118 | >>>   if [ -n "${APPS_JSON_BASE64}" ]; then \
 119 | >>>     export APP_INSTALL_ARGS="--apps_path=/opt/frappe/apps.json"; \
 120 | >>>   fi && \
 121 | >>>   bench init ${APP_INSTALL_ARGS}\
 122 | >>>     --frappe-branch=${FRAPPE_BRANCH} \
 123 | >>>     --frappe-path=${FRAPPE_PATH} \
 124 | >>>     --no-procfile \
 125 | >>>     --no-backups \
 126 | >>>     --skip-redis-config-generation \
 127 | >>>     --verbose \
 128 | >>>     /home/frappe/frappe-bench && \
 129 | >>>   cd /home/frappe/frappe-bench && \
 130 | >>>   echo "{}" > sites/common_site_config.json && \
 131 | >>>   find apps -mindepth 1 -path "*/.git" | xargs rm -fr
 132 |
--------------------
ERROR: failed to solve: process "/bin/sh -c export APP_INSTALL_ARGS=\"\" &&   if [ -n \"${APPS_JSON_BASE64}\" ]; then     export APP_INSTALL_ARGS=\"--apps_path=/opt/frappe/apps.json\";   fi &&   bench init ${APP_INSTALL_ARGS}    --frappe-branch=${FRAPPE_BRANCH}     --frappe-path=${FRAPPE_PATH}     --no-procfile     --no-backups     --skip-redis-config-generation     --verbose     /home/frappe/frappe-bench &&   cd /home/frappe/frappe-bench &&   echo \"{}\" > sites/common_site_config.json &&   find apps -mindepth 1 -path \"*/.git\" | xargs rm -fr" did not complete successfully: exit code: 1

(Hopefully this is allowed) Here is a link to a pastebin for the full console output of running this command on my Ubuntu 24.04 server: pastebin

Has anyone here experienced similar issues or can offer some guidance on how to correctly pass multiple apps via the APPS_JSON in a Docker build for ERPNext? Any help or pointers would be much appreciated!

Thank you in advance!

Solution found. I was using a malformed docker build command.