docker-compose: ModuleNotFoundError: No module named 'jwt'
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!
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?
Have you also tried the root version?
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
_timetaggergets created with ownerroot: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....?
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 ...
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?
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