Installation with pip in Docker fails to find module
Question:
I have the following in my setup.py
entry_points={
'console_scripts': [
'my-app=main:run',
],
and my file structure is
▶ tree -L 2
.
├── Dockerfile
├── README.md
├── redis.conf
├── setup.cfg
├── setup.py
├── src
│ ├── main.py
│ ├── settings.py
│ ├── bfile.py
│ └── afile.py
and in my main.py
def run():
actual_run()
Locally, in a virtualenv when performing
pip install -e . && my-app
it runs smoothly.
However in an image created with the following Dockerfile
FROM python:3.9-slim-buster
WORKDIR /app
COPY . .
RUN pip3 install .
CMD [ "my-app"]
I get
Traceback (most recent call last):
File "/usr/local/bin/my-app", line 5, in <module>
from main import run
ModuleNotFoundError: No module named 'main'
What I noticed, is that in my image, in /usr/local/lib/python3.9/site-packages/
there only the a file named my-app-0.0.1.dist-info
and not a dir with the source files.
Why is that?
Answers:
You didn’t give a minimal workable setup.py
, but next could works, FYI:
Dockerfile:
FROM python:3.9-slim-buster
WORKDIR /app
COPY . .
RUN pip3 install .
CMD [ "my-app"]
setup.py:
from setuptools import setup, find_packages
setup(
name="my-app",
version="0.0.1",
packages=['main'],
package_dir={'main':'src'},
entry_points={
'console_scripts': [
'my-app=main.main:run',
],
}
)
src/main.py:
def run():
print("hello world")
Execution:
# docker build -t abc:1 .
# docker run --rm abc:1
hello world
Explain:
In above, src
folder will map to main
module, and packages=['main']
specify the python package name which will be installed into site-packages
.
In final image, the package will be located as next:
root@7b5ce63d8226:/usr/local/lib/python3.9/site-packages/main# ls
__pycache__ main.py
So, you need to use main.main:run
to call your function.
I have the following in my setup.py
entry_points={
'console_scripts': [
'my-app=main:run',
],
and my file structure is
▶ tree -L 2
.
├── Dockerfile
├── README.md
├── redis.conf
├── setup.cfg
├── setup.py
├── src
│ ├── main.py
│ ├── settings.py
│ ├── bfile.py
│ └── afile.py
and in my main.py
def run():
actual_run()
Locally, in a virtualenv when performing
pip install -e . && my-app
it runs smoothly.
However in an image created with the following Dockerfile
FROM python:3.9-slim-buster
WORKDIR /app
COPY . .
RUN pip3 install .
CMD [ "my-app"]
I get
Traceback (most recent call last):
File "/usr/local/bin/my-app", line 5, in <module>
from main import run
ModuleNotFoundError: No module named 'main'
What I noticed, is that in my image, in /usr/local/lib/python3.9/site-packages/
there only the a file named my-app-0.0.1.dist-info
and not a dir with the source files.
Why is that?
You didn’t give a minimal workable setup.py
, but next could works, FYI:
Dockerfile:
FROM python:3.9-slim-buster
WORKDIR /app
COPY . .
RUN pip3 install .
CMD [ "my-app"]
setup.py:
from setuptools import setup, find_packages
setup(
name="my-app",
version="0.0.1",
packages=['main'],
package_dir={'main':'src'},
entry_points={
'console_scripts': [
'my-app=main.main:run',
],
}
)
src/main.py:
def run():
print("hello world")
Execution:
# docker build -t abc:1 .
# docker run --rm abc:1
hello world
Explain:
In above, src
folder will map to main
module, and packages=['main']
specify the python package name which will be installed into site-packages
.
In final image, the package will be located as next:
root@7b5ce63d8226:/usr/local/lib/python3.9/site-packages/main# ls
__pycache__ main.py
So, you need to use main.main:run
to call your function.