Github Repo for this application
Nginx¶
This dead simple application shows you to how to create a simple Docker Image with running FastAPI app with Nginx and presenting the basics of creating and running Docker Images. Each step is deeply described below.
You should definitely have any clue about what’s going on here, there is a great video which helped me out: Docker For Beginners Video on YouTube.
Application structure¶
├── app
| |── app
| | ├── __init__.py
| | ├── main.py # FastAPI app here
| |
| ├── config
| ├── config.json # Nginx config file
|
├── .dockerignore # similar to .gitignore
| # but for Docker
├── .gitignore
|
├── Dockerfile # commands to build
| # a Docker Image
├── README.md
|
├── requirements.txt # pip freeze from
| # pip install fastapi
Files description¶
requirements.txt, .gitignore, .dockerignore
Some common stuff. In
.dockerignoreI’ve addedREADME.md- we don’t need it in our Container.
app/app/main.py
from fastapi import FastAPI my_fastapi_app = FastAPI() @my_fastapi_app.get("/") async def root(): return {"Nginx": "I'm alive"}
app/config/config.json
{ "listeners": { "*:80": { "pass": "applications/fastapi" } }, "applications": { "fastapi": { "type": "python 3.9", "path": "/build/app/", "module": "app.main", "callable": "my_fastapi_app" } } }This is a configuration file for our Nginx server. Some basic listener
*:80. If we change applications to apps and fastapi to python_app we would have"pass": "apps/python_app".“type”
python 3.9is obvious because we’re using Docker Image with python version 3.9. Note that we want later inDockerfileto copy our repo to/buildfolder inside of the Container so “path”/build/app/will be a root folder for our FastAPI application. Then “module” is just a python file with application which ismain.pyso “module” isapp.mainand since we named the instance ofFastAPIclass inmain.pyas amy_fastapi_app, “callable” ismy_fastapi_app.If we had a different folder structure, e.g. one more
appfolder and then themain.pyfile, then the “module” would be"app.app.main".Note
Configuration docs for python apps can be found here: https://unit.nginx.org/configuration/#configuration-python
Dockerfile
FROM nginx/unit:1.23.0-python3.9 # Our Debian with Python and Nginx for python apps. # See https://hub.docker.com/r/nginx/unit/ COPY ./app/config/config.json /docker-entrypoint.d/config.json # Ok, this is something we get thanks to the Nginx Unit Image. # We don't need to call stuff like # curl -X PUT --data-binary @config.json --unix-socket \ # /path/to/control.unit.sock http://localhost/config/ # to set our configuration # Becouse as stated in docs https://unit.nginx.org/installation/#docker-images, # configuration snippets are # uploaded as to the config section of Unit’s configuration # That means we only have to copy our config.json file to the folder # /docker-entrypoint.d/ RUN mkdir build # We create folder named build for our app. COPY . ./build # We copy our app folder to the /build RUN apt update && apt install -y python3-pip \ && pip3 install -r /build/requirements.txt \ && apt remove -y python3-pip \ && apt autoremove --purge -y \ && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/*.list # OK, that looks strange but here's a explanation from Nginx docs # https://unit.nginx.org/howto/docker/: # """ PIP isn't installed by default, so we install it first. # Next, we install the requirements, remove PIP, and perform image cleanup. """ # Note we use /build/requirements.txt since this is our file EXPOSE 80 # Instruction informs Docker that the container listens on port 80
Local deployment¶
In your favourite folder:
1 2 3 4 5 6 7 8 9 10 11 | git clone https://github.com/rafsaf/docker-fastapi-projects-nginx.git
cd docker-fastapi-projects-nginx
docker build . -t nginx
# creates image in current folder with tag nginx
docker run --rm -it -p 80:80/tcp nginx:latest
# runs nginx image
|
Now the app is up and running locally. In your favourite browser type in:
localhost
You should see:
1 | {"Nginx": "I'm alive"}
|
Awesome!