I am new to docker and was trying to dockerize my fastapi application. I built a Dockerfile shown below
# syntax=docker/dockerfile:1
FROM python:3.8-slim-buster
WORKDIR /app
COPY requirements.txt requirements.txt
RUN apt-get update
RUN apt-get -y install libpq-dev gcc
RUN apt-get -y install libnss3-tools
RUN apt-get -y install curl
RUN curl -LJO https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64
RUN mv mkcert-v1.4.4-linux-amd64 mkcert
RUN chmod x mkcert
RUN ./mkcert -install
RUN ./mkcert -cert-file cert.pem -key-file key.pem 0.0.0.0 localhost 127.0.0.1 ::1
RUN pip3 install -r requirements.txt
COPY . .
CMD ["python3.8", "-m", "uvicorn", "main:app", "--host=0.0.0.0", "--ssl-keyfile=./key.pem", "--ssl-certfile=./cert.pem"]
and ran the containers and they all worked. But when I try to combine the containers with docker compose its tells me can't find uvicorn module even when it's in the requirements.txt file . Here is a snippet of my docker compose file containing the server service.
services:
server:
container_name: server
image: python:3.8-slim-buster
command: ["python3.8", "-m", "uvicorn", "main:app", "--host=0.0.0.0", "--ssl-keyfile=./key.pem", "--ssl-certfile=./cert.pem"]
ports:
- 8000:8000
working_dir: /app
I have tried using changing the command part of the server service in docker compose to
command: bash "python3.8 -m uvicorn main:app --host=0.0.0.0 --ssl-keyfile=./key.pem --ssl-certfile=./cert.pem"
didn't work. changed it to
command: sh -c "python3.8 -m uvicorn main:app --host=0.0.0.0 --ssl-keyfile=./key.pem --ssl-certfile=./cert.pem"
didn't work.
I removed the command totally it still didn't work, keeps showing
server | /usr/local/bin/python3.8: No module named uvicorn
server exited with code 1
CodePudding user response:
The image you use in the docker compose is not the one previously built in the Dockerfile but a basic Python image.
You could build the image from your Dockerfile
docker build . -t fastapi
then modify your docker-compose.yml
file with something like this
services:
api:
image: fastapi
ports:
- "8000:8000"
then run docker compose
docker-compose -f docker-compose.yml up
CodePudding user response:
Yes, that's correct. Running the pip install command in a separate container as a long-running service is not ideal as the packages will not be available in the other containers. It's better to include the pip install command in the Dockerfile for your application and build an image that includes all the required packages. This way, you can use the same image for both development and production environments and ensure consistency.
Here's an updated Dockerfile:
FROM python:3.8-slim-buster
WORKDIR /app
COPY requirements.txt requirements.txt
RUN apt-get update \
&& apt-get -y install libpq-dev gcc \
&& apt-get -y install libnss3-tools \
&& apt-get -y install curl \
&& curl -LJO https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64 \
&& mv mkcert-v1.4.4-linux-amd64 mkcert \
&& chmod x mkcert \
&& ./mkcert -install \
&& ./mkcert -cert-file cert.pem -key-file key.pem 0.0.0.0 localhost 127.0.0.1 ::1
RUN pip3 install -r requirements.txt
COPY . .
CMD ["python3.8", "-m", "uvicorn", "main:app", "--host=0.0.0.0", "--ssl-keyfile=./key.pem", "--ssl-certfile=./cert.pem"]
And here's the updated Docker Compose file:
version: '3'
services:
server:
build: .
command: sh -c "python3.8 -m uvicorn main:app --host=0.0.0.0 --ssl-keyfile=./key.pem --ssl-certfile=./cert.pem"