timetagger icon indicating copy to clipboard operation
timetagger copied to clipboard

docker-compose: ModuleNotFoundError: No module named 'jwt'

Open marcusfey opened this issue 1 year ago • 5 comments

Hi,

I get an error starting the app using docker compose: ModuleNotFoundError: No module named 'jwt'

My docker-compose.yml is:

version: "3"
services:
  timetagger:
    image: ghcr.io/almarklein/timetagger:v23.11.4-nonroot
    ports:
      - "6822:80"
    volumes:
      - ./_timetagger:/opt/_timetagger
    user: 1001:1001
    environment:
      - TIMETAGGER_BIND=0.0.0.0:80
      - TIMETAGGER_DATADIR=/opt/_timetagger
      - TIMETAGGER_LOG_LEVEL=info
      - TIMETAGGER_CREDENTIALS=test:$$2a$$08$$0CD1NFiIbancwWsu3se1v.RNR/b7YeZd71yg3cZ/3whGlyU6Iny5i  # test:test

Same problem with for example v23.9.2-nonroot.

What am I missing?

Thanks!

marcusfey avatar Feb 26 '24 06:02 marcusfey

That's odd. The pyjwt package should be installed here:

https://github.com/almarklein/timetagger/blob/1eb0dc25e0a1d7a3a9267be978e50c1b2667e5e0/deploy/repo.nonroot.Dockerfile#L26

The logs of the CI job that build the image are no longer available so I cannot check right now whether something went wrong. But I would expect this error to have surfaced earlier if it affects others? @danielhass any idea?

almarklein avatar Feb 26 '24 09:02 almarklein

Have you also tried the root version?

almarklein avatar Feb 26 '24 09:02 almarklein

My docker deamon runs as root. I forgot that I can run docker / docker compose without sudo due to my using being member of docker group.

Maybe I should have done the root image before...

This one works:

version: "3"
services:
  timetagger:
    image: ghcr.io/almarklein/timetagger
    ports:
      - "6822:80"
    volumes:
      - ./_timetagger:/root/_timetagger
    #user: "1001:1001"
    environment:
      - TIMETAGGER_BIND=0.0.0.0:80
      - TIMETAGGER_DATADIR=/root/_timetagger
      - TIMETAGGER_LOG_LEVEL=info
      - TIMETAGGER_CREDENTIALS=test:$$2a$$08$$0CD1NFiIbancwWsu3se1v.RNR/b7YeZd71yg3cZ/3whGlyU6Iny5i  # test:test

Actually I would like to keep the volume under my personal ownership (thus not as root).

To acchieve this I re-enable the line user: "1001:1001", the following happens:

  • a directory _timetagger gets created with owner root:root (I assumed this would be 1001:1001; but maybe I'm wrong)
  • startup fails with timetagger-root-timetagger-1 | /usr/local/bin/python: No module named timetagger

Did I screwed up something else....?

marcusfey avatar Feb 26 '24 10:02 marcusfey

It looks to me like there is a mismatch with the user groups. For some reason it does not see the timetagger that was installed into the image. It's likely that it cannot see the whole site_packages directory. IIRC this is sometimes an issue on Linux where stuff is installed with root, but used by another user (or the other way around). I'm not expert on this though ...

almarklein avatar Feb 28 '24 08:02 almarklein

Hey @marcusfey, I'm not :100: % sure but after some local testing this is what I think is happening:

if you run docker-compose up without your local data directory already existing (_timetagger), the docker daemon will create this directory for you. Doing this as the root user under which the daemon is running, hence the resulting ownership of _timetagger. This behavior seems to be expected according to the bind mount docs.

If you create the data dir _timetagger yourself beforehand this issue should be gone as the docker daemon simply mounts the existing directory. But, this will probably only work with the user being 1000 as we currently install timetagger under that users context.

See https://github.com/almarklein/timetagger/blob/main/deploy/repo.nonroot.Dockerfile#L22, where we switch to user 1000 before installing timetagger.

If I find time over the next few days I can check if we can work around this somehow. One option would be to install timetagger "globally" but still run in the context of the unprivileged user.

For now you might be able to work around this issue with the group the files are owned by? Leave the files for 1000 but add your users group with the correct permissions to access them?

danielhass avatar Mar 02 '24 13:03 danielhass

Thanks for your response! I'm sorry for getting back so late :-(

Your advise works! I'm closing this issue now. You probably track the hardcoded userid elsewhere.

Just to summarize:

version: "3"
services:
  timetagger:
    image: ghcr.io/almarklein/timetagger:v23.11.4-nonroot
    ports:
      - "8091:80"
    volumes:
      - ./_timetagger.1000:/opt/_timetagger
    environment:
      - TIMETAGGER_BIND=0.0.0.0:80
      - TIMETAGGER_DATADIR=/opt/_timetagger
      - TIMETAGGER_LOG_LEVEL=info
      - TIMETAGGER_CREDENTIALS=test:$$2a$$08$$0CD1NFiIbancwWsu3se1v.RNR/b7YeZd71yg3cZ/3whGlyU6Iny5i  # test:test

And:

marcus@epsilon:~/docker/timetagger$ ll -n _timetagger.1000/
total 8
-rw-r--r-- 1 1000 1001   43 Mar  4 11:50 jwt.key
drwxr-xr-x 2 1000 1001 4096 Aug 24 17:11 users
marcus@epsilon:~/docker/timetagger$ ll -n
total 8
-rw-r--r-- 1 1001 1001  892 Aug 24 17:11 docker-compose.yml
drwxr-xr-x 3 1000 1001 4096 Mar  4 11:50 _timetagger.1000
marcus@epsilon:~/docker/timetagger$ id -u
1001

marcusfey avatar Aug 24 '24 15:08 marcusfey