How do I install the human resources module in a Docker setup?

I set up ERPNext on a virtual machine using the single server example:
(https://github.com/frappe/frappe_docker/blob/main/docs/single-server-example.md)

Now I’d like to install the HRMS app, but I’m really struggling with this.

First, I build a custom package as explained in the docker repo
https://github.com/zebra-pig/zebrapig-erp/pkgs/container/erp%2Fcustom

My apps JSON was:

[
    {
        "url": "https://github.com/frappe/hrms",
        "branch": "version-14"
    }
]

Then, I added the following lines to my erpnext-one.yaml aka compose.yaml:

x-customizable-image: &customizable_image
  image: https://ghcr.io/zebrapig/erp/custom:1.0.0

Afterwards, i ran the compose command:
docker compose --project-name erpnext-one -f ~/gitops/erpnext-one.yaml up -d

My ERPNext instance works fine, but I don’t find the HR module anywhere. What did I miss?

your apps.json needs erpnext on version-14 branch as well. In the array add erpnext object first then hrms object

Thank you for the hint @revant_one. I updated the apps.json accordingly…

[
    {
        "url": "https://github.com/frappe/erpnext",
        "branch": "version-14"
    },
    {
        "url": "https://github.com/frappe/hrms",
        "branch": "version-14"
    }
]

…and changed compose.yaml to use the new package version:

x-customizable-image: &customizable_image
  image: https://ghcr.io/zebra-pig/erp/custom:1.0.1

But the HR module still is not installed. I’m not sure if x-customizable-image does have any effect in my compose.yaml. Is there a way to check this?

after building image you’ve to install app on a site.

if you don’t have site created then first create a site.

When I run bench --site [sitename] install-app hrms in the backend container, I get the following message: Could not find app "hrms". Also there is no hrms directory in my apps folder. Could it be that my compose.yaml’s x-customizable-image tag does not have an effect on the containers somehow?

you’ll need to figure that out. check image of running containers.

You can use GitHub - castlecraft/custom_containers to build the image which works flawless

Or you can use the below which is pre configured with hrms and lms

For testing and to check if your yaml works fine, use the pre built image from here. This is my production working image. Will ensure where have you gone wrong. Once you get the site working then you can focus on building your custom image on your own and replace, pull->down->up so that the container uses yours.

ghcr.io/lmnaslimited/lensdocker/lenshxm:v14.12.0

Should you not run bench get-app hrms first, or did your custom package include it?
Works for me. But first supervisor is needed in the backend container.
Here is some help for that: WARN: restart failed: Couldn't find supervisorctl in PATH and Easy install fails with "frappe: ERROR (no such group)" message · Issue #6 · frappe/easy_install · GitHub
Installed supervisor, adjusted the supervisor config to include both fixes, restarted the service. Note that to install it, you need to be root and run apt-get update first.
After that bench get-app hrms runs successfully.

But when I include --resolve-deps this happens:

bench get-app hrms --resolve-deps
ERROR: 'App' object has no attribute 'org'
Traceback (most recent call last):
  File "/usr/local/bin/bench", line 8, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.10/site-packages/bench/cli.py", line 127, in cli
    bench_command()
  File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1130, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.10/site-packages/click/core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.10/site-packages/click/core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/bench/commands/make.py", line 159, in get_app
    get_app(
  File "/usr/local/lib/python3.10/site-packages/bench/app.py", line 372, in get_app
    resolution = make_resolution_plan(app, bench)
  File "/usr/local/lib/python3.10/site-packages/bench/app.py", line 297, in make_resolution_plan
    is_valid_frappe_branch(dep_app.url, dep_app.branch)
  File "/usr/local/lib/python3.10/site-packages/bench/app.py", line 152, in url
    return self.get_http_url()
  File "/usr/local/lib/python3.10/site-packages/bench/app.py", line 155, in get_http_url
    return f"https://{self.remote_server}/{self.org}/{self.repo}.git"
AttributeError: 'App' object has no attribute 'org'

So, leaving deps out for now.

By this point I think HRMS is ready in Frappe but not in ERPNext yet.
Next: bench --site sitename install-app hrms

The install completes successfully, but ERPNext page is: Internal Server Error
That’s where I am stuck now.

$ bench --site frontend install-app hrms
App erpnext already installed
App hrms already installed
$ bench list-apps
frappe  14.29.0 UNVERSIONED
erpnext 14.19.0 UNVERSIONED

No hrms app shown.

Errors in backend container:

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/frappe/frappe-bench/env/lib/python3.10/site-packages/gunicorn/workers/gthread.py", line 271, in handle
    keepalive = self.handle_request(req, conn)
  File "/home/frappe/frappe-bench/env/lib/python3.10/site-packages/gunicorn/workers/gthread.py", line 323, in handle_request
    respiter = self.wsgi(environ, resp.start_response)
  File "/home/frappe/frappe-bench/env/lib/python3.10/site-packages/werkzeug/local.py", line 237, in application
    return ClosingIterator(app(environ, start_response), self.cleanup)
  File "/home/frappe/frappe-bench/env/lib/python3.10/site-packages/werkzeug/wrappers/request.py", line 194, in application
    resp = f(*args[:-2] + (request,))
  File "/home/frappe/frappe-bench/apps/frappe/frappe/app.py", line 84, in application
    response = handle_exception(e)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/app.py", line 324, in handle_exception
    response = get_response("message", http_status_code=http_status_code)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/serve.py", line 27, in get_response
    response = ErrorPage(exception=e).render()
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/error_page.py", line 7, in __init__
    super().__init__(path=path, http_status_code=http_status_code)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py", line 45, in __init__
    self.set_template_path()
  File "/home/frappe/frappe-bench/apps/frappe/frappe/website/page_renderers/template_page.py", line 54, in set_template_path
    app_path = frappe.get_app_path(app)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 1356, in get_app_path
    return get_pymodule_path(app_name, *joins)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 1373, in get_pymodule_path
    return os.path.join(os.path.dirname(get_module(scrub(modulename)).__file__ or ""), *joins)
  File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 1327, in get_module
    return importlib.import_module(modulename)
  File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1004, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'hrms'

Read this: Frequently Asked Questions · frappe/frappe_docker Wiki · GitHub

In case of production setup you need to build your custom image for installing apps. This repository only publishes frappe/erpnext image with no additional app. You CANNOT bench get-app in running containers.

Ah my bad. I am easily lost in this project, I have to read more. Will look into that soon. Thanks!

Hi im relatively new to this but Im a bit stuck. Im in the stage that i build my own custom Docker Image(whitout Apps just to troubleshoot step by step). I also can deploy with the code of pwd.yml, but im not sure how to edit/create/provide the app.json? Were ist the folder? or do i have to edit the containerfile and provide the infos there? can you provide a samle Containerfile with real or fake entrys so im able to recreate it?

Thank you very mutch!

There is no directory or place for apps.json. It needs to be passed as base64 encoded string of json, through container build-arg. You can generate it as a part of your CI run job. You can keep a file in a build repo where the runner job is triggered. You can commit changes to apps.json in this “builder” repo.

The environment variable if found is saved into a file in the build layer of the image.

This file is then used to add apps to bench during bench init

Thank you!

It might sound stupid but how do i do it on prem? I dont have an Ci CD pipline…

My Steps so far:

login to my maschine
login as root
go to /opt/erpnext/
git clone frappe_docker
cp /images/custom/Containerfile Dockerfile
cp pwd.yml compose.yaml
nano compose.yaml
edite the Images to build: ./Dockerfile
save nano
docker compose up

in this Prozess via the compose yaml Docker build me my img and docker compose uses it.

Were in this prozess and how do i crate the json string an were do i have to place it?

this is the inculde but were do Docker look for the APPS_JSON_BASE64 variable? and how do I create the json string on prem?

apps.json includes

ARG APPS_JSON_BASE64
RUN if [ -n “${APPS_JSON_BASE64}” ]; then
mkdir /opt/frappe && echo “${APPS_JSON_BASE64}” | base64 -d > /opt/frappe/apps.json;
fi

Hey @mirrose . Check frappe_docker/docs/custom-apps.md at main · frappe/frappe_docker · GitHub

Execute the first export command to load the text into the APPS_JSON variable. Then echo $APPS_JSON into a file, apps.json:

echo $APPS_JSON > apps.json

After that, you can carefully edit the file to your needs.

Hi @trustedcomputer I’m sorry i still dont get it.

how do i run this comand?

export APPS_JSON=‘[
{
“url”: “example url”,
“branch”: “develop”
},
{
“url”: “example url”,
“branch”: “version-14”
},
{
“url”: “example url”,
“branch”: “main”
}
]’

I tried it via the RUN-arg but docker reported an error because of a { and i cant run it from cli or can i?

=> [internal] load .dockerignore 0.0s
=> => transferring context: 83B 0.0s
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 4.98kB 0.0s
Dockerfile:98

96 | # apps.json includes
97 | RUN export APPS_JSON='[
98 | >>> {
99 | “url”: “exapmle url”,
100 | “branch”: “develop”

ERROR: failed to solve: dockerfile parse error on line 98: unknown instruction: {

Thanks for our’e help and patience :slight_smile:

@mirrose You run these commands in your shell (i.e. bash prompt).

Based on frappe_docker/custom-apps.md at main · frappe/frappe_docker · GitHub I’ll write commands below. Copy-paste them in your terminal window and press enter.

git clone https://github.com/frappe/frappe_docker && cd frappe_docker
export APPS_JSON='[
  {
    "url": "https://github.com/frappe/erpnext",
    "branch": "v14.21.0"
  },
  {
    "url": "https://github.com/frappe/hrms",
    "branch": "v14.2.2"
  }
]'
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=v14.32.1 \
  --build-arg=PYTHON_VERSION=3.10.5 \
  --build-arg=NODE_VERSION=16.18.0 \
  --build-arg=APPS_JSON_BASE64=$APPS_JSON_BASE64 \
  --tag=custom/hrms:1.0.0 \
  --file=images/custom/Containerfile .

Above command will build image named custom/hrms:1.0.0 with frappe v14.32.1, erpnext v14.21.0, hrms v14.2.2, python 3.10.5, nodejs 16.18.0

You can make changes to the command.

3 Likes

Thank you so mutch fort you’re explanations and patience !

It worked! And with this blueprint i have successfully installed a lot of Apps

hello sir, this method not work for me , I can you help me please?

Hi is there a possibility to inclue a custom pip libray?

I want to install the App FinTS and need to install the Python lib fints, how can i do this?

Thanks a lot!