pythondockerweasyprint

Docker file with Ubuntu, Python and Weasyprint - Problem with venv


I am trying to get a docker image with Ubuntu, Python and Weasyprint to work. I think the error for me is that requirements.txt is installed in a Python venv. When I try to run main.py it gives me a error ModuleNotFoundError: No module named 'sqlalchemy', so it did install requirements.txt, but only in the virtual environment, and this is not the environment that is beeing run.

Dockerfile

# Specify Python
FROM ubuntu:latest

# Upgrade Ubuntu
RUN echo Dockerfile :: Update Ubuntu
RUN apt-get update && apt-get install -y
RUN apt-get install build-essential -y

# Install Python
RUN echo Dockerfile :: Install Python
RUN apt install python3 -y
RUN python3 --version

# Install Weasyprint
RUN echo Dockerfile :: Install components
RUN apt-get install -y python3-lxml libcairo2 libgdk-pixbuf2.0-0 libffi-dev shared-mime-info
RUN apt-get install -y libpango-1.0-0
RUN apt install -y python3-dev libpq-dev

# Install PIP
RUN echo Dockerfile :: Install PIP
RUN apt-get install python3-pip -y
RUN pip --version

# Install venv
RUN echo Dockerfile :: Install Venv
RUN apt-get install python3-venv -y

# Set enviroment variables
RUN echo Dockerfile :: Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# Open port
RUN echo Dockerfile :: Open port
EXPOSE 8080

# Add Python script
RUN echo Dockerfile :: Add Python script
RUN mkdir /app
WORKDIR /app
COPY . .

# Install dependencies
RUN echo Dockerfile :: Install dependencies

RUN python3 -m venv .venv
RUN . .venv/bin/activate
RUN .venv/bin/pip install -r requirements.txt

# Set Pythons path
RUN echo Dockerfile :: Set Pythons path
ENV PYTHONPATH /app

# Run script
RUN echo Dockerfile :: Run script
CMD [ "python3", "./main.py" ]

Build output:

docker build .
2024/05/02 08:54:37 http2: server: error reading preface from client //./pipe/docker_engine: file has already been closed
[+] Building 0.0s (0/0)  docker:default
[+] Building 51.2s (33/33) FINISHED                                                                                                                                  docker:default
 => [internal] load build definition from Dockerfile                                                                                                                           0.0s
 => => transferring dockerfile: 1.42kB                                                                                                                                         0.0s 
 => [internal] load metadata for docker.io/library/ubuntu:latest                                                                                                               0.5s 
 => [internal] load .dockerignore                                                                                                                                              0.0s
 => => transferring context: 2B                                                                                                                                                0.0s 
 => [ 1/28] FROM docker.io/library/ubuntu:latest@sha256:3f85b7caad41a95462cf5b787d8a04604c8262cdcdf9a472b8c52ef83375fe15                                                       0.0s 
 => [internal] load build context                                                                                                                                              0.8s 
 => => transferring context: 973.99kB                                                                                                                                          0.8s 
 => CACHED [ 2/28] RUN echo Dockerfile :: Update Ubuntu                                                                                                                        0.0s
 => CACHED [ 3/28] RUN apt-get update && apt-get install -y                                                                                                                    0.0s
 => CACHED [ 4/28] RUN apt-get install build-essential -y                                                                                                                      0.0s 
 => CACHED [ 5/28] RUN echo Dockerfile :: Install Python                                                                                                                       0.0s 
 => CACHED [ 6/28] RUN apt install python3 -y                                                                                                                                  0.0s 
 => CACHED [ 7/28] RUN python3 --version                                                                                                                                       0.0s 
 => CACHED [ 8/28] RUN echo Dockerfile :: Install components                                                                                                                   0.0s 
 => CACHED [ 9/28] RUN apt-get install -y python3-lxml libcairo2 libgdk-pixbuf2.0-0 libffi-dev shared-mime-info                                                                0.0s 
 => CACHED [10/28] RUN apt-get install -y libpango-1.0-0                                                                                                                       0.0s 
 => CACHED [11/28] RUN apt install -y python3-dev libpq-dev                                                                                                                    0.0s 
 => CACHED [12/28] RUN echo Dockerfile :: Install PIP                                                                                                                          0.0s 
 => CACHED [13/28] RUN apt-get install python3-pip -y                                                                                                                          0.0s 
 => CACHED [14/28] RUN pip --version                                                                                                                                           0.0s 
 => CACHED [15/28] RUN echo Dockerfile :: Install Venv                                                                                                                         0.0s 
 => CACHED [16/28] RUN apt-get install python3-venv -y                                                                                                                         0.0s 
 => CACHED [17/28] RUN echo Dockerfile :: Set environment variables                                                                                                            0.0s 
 => CACHED [18/28] RUN echo Dockerfile :: Open port                                                                                                                            0.0s 
 => CACHED [19/28] RUN echo Dockerfile :: Add Python script                                                                                                                    0.0s 
 => CACHED [20/28] RUN mkdir /app                                                                                                                                              0.0s 
 => CACHED [21/28] WORKDIR /app                                                                                                                                                0.0s 
 => [22/28] COPY . .                                                                                                                                                           3.9s 
 => [23/28] RUN echo Dockerfile :: Install dependencies                                                                                                                        0.4s 
 => [24/28] RUN python3 -m venv .venv                                                                                                                                          4.0s 
 => [25/28] RUN . .venv/bin/activate                                                                                                                                           0.4s 
 => [26/28] RUN .venv/bin/pip install -r requirements.txt                                                                                                                     38.9s 
 => [27/28] RUN echo Dockerfile :: Set Pythons path                                                                                                                            0.4s 
 => [28/28] RUN echo Dockerfile :: Run script                                                                                                                                  0.5s 
 => exporting to image                                                                                                                                                         1.2s 
 => => exporting layers                                                                                                                                                        1.2s 
 => => writing image sha256:e936b6ebf44f23a8a04ec47c9ce69c33f7872249b6ee795a606d64a30e30b6a8                                                                                   0.0s 

What's Next?
  View a summary of image vulnerabilities and recommendations → docker scout quickview

Run output:

docker run e9 
Traceback (most recent call last):
  File "/app/./main.py", line 10, in <module>
    from src.dao.db_adapter import DBAdapter
  File "/app/src/dao/db_adapter.py", line 19, in <module>
    import sqlalchemy
ModuleNotFoundError: No module named 'sqlalchemy'

How can I fix so that either requirements are installed system wide or python uses the venv?


Solution

  • Running RUN . .venv/bin/activate won't do anything meaningful. Every RUN command uses its own shell, then exits, so all the environment variables set by activate will not persist. The ultimate issue is that your CMD ["python" ...] doesn't run in your virtualenv

    There's a couple ways to deal with this:

    1. You can use equivalent ENV commands to properly set the virtual env for subsequent RUN (or CMD/ENTRYPOINT) instructions:
    # ...
    RUN python -m venv .venv
    ENV PATH="/app/.venv/bin:$PATH"
    RUN pip install -r requirements.txt
    # ...
    
    1. You can first activate your virtualenv for every command where you want it to be active and chain with &&
    RUN python -m venv .venv
    RUN source .venv/bin/activate && pip install -r requirements.txt
    # ...
    CMD ["bash", "-c", "source .venv/bin/activate && python ./main.py"]
    

    Additional reference: https://pythonspeed.com/articles/activate-virtualenv-dockerfile/