diff --git a/api-server-multistage/.dockerignore b/api-server-multistage/.dockerignore new file mode 100644 index 0000000..467d9ab --- /dev/null +++ b/api-server-multistage/.dockerignore @@ -0,0 +1,5 @@ +**/.env/ +**/__pycache__/ +**/Makefile +**/Dockerfile +*.log diff --git a/api-server-multistage/Dockerfile b/api-server-multistage/Dockerfile new file mode 100644 index 0000000..5bc8129 --- /dev/null +++ b/api-server-multistage/Dockerfile @@ -0,0 +1,25 @@ +FROM python:3.11-slim-bookworm + +# set virtual env path +ENV \ + PATH=/venv/bin:$PATH + +# does nothing, for documentation only +EXPOSE 3000 + +# create and set main app directory +WORKDIR /app + +# copy app files to /app directory +COPY ./app . + +# install dependencies +RUN \ + python -m venv /venv && \ + pip install -r requirements.txt + +# start shell script when container starts +ENTRYPOINT ["/app/run.sh"] + +# no additional parameters to run.sh script +CMD [] diff --git a/api-server-multistage/Makefile b/api-server-multistage/Makefile new file mode 100644 index 0000000..403e94d --- /dev/null +++ b/api-server-multistage/Makefile @@ -0,0 +1,32 @@ +IMAGE_NAME=api-server +CONTAINER_NAME=api-server + +build: clean + @docker build \ + --progress=plain \ + --no-cache \ + --tag $(IMAGE_NAME) \ + . + +run: + @docker run \ + --name $(IMAGE_NAME) \ + --publish 3000:3000 \ + --env CONTAINER_NAME="Awesome API server" \ + --detach \ + $(CONTAINER_NAME) + +run-mount-log: + @docker run \ + --name $(IMAGE_NAME) \ + --publish 3000:3000 \ + --volume /var/log/api-server:/app/log \ + --env CONTAINER_NAME="Awesome API server" \ + --detach \ + $(CONTAINER_NAME) + + +clean: + - @docker stop $(CONTAINER_NAME) + - @docker rm $(CONTAINER_NAME) + - @docker rmi $(IMAGE_NAME) diff --git a/api-server-multistage/app/Makefile b/api-server-multistage/app/Makefile new file mode 100644 index 0000000..aa88106 --- /dev/null +++ b/api-server-multistage/app/Makefile @@ -0,0 +1,2 @@ +run: + @./run.sh diff --git a/api-server-multistage/app/main.py b/api-server-multistage/app/main.py new file mode 100644 index 0000000..74c82be --- /dev/null +++ b/api-server-multistage/app/main.py @@ -0,0 +1,29 @@ +from fastapi import FastAPI +import logging +import os + +app = FastAPI() + + +LOG_FILE = "./log/api-server.log" +CONTAINER_NAME = os.environ.get("CONTAINER_NAME", "Unknown") + + +@app.get("/") +async def root(): + logging.info(f"Container {CONTAINER_NAME} received request") + return { + "message": f"Hello World from {CONTAINER_NAME}", + } + + +def main(): + logging.basicConfig( + filename=LOG_FILE, + format="%(asctime)s %(levelname)s %(message)s", + level=logging.INFO, + ) + logging.info(f"Starting server {CONTAINER_NAME}") + + +main() diff --git a/api-server-multistage/app/requirements.txt b/api-server-multistage/app/requirements.txt new file mode 100644 index 0000000..97dc7cd --- /dev/null +++ b/api-server-multistage/app/requirements.txt @@ -0,0 +1,2 @@ +fastapi +uvicorn diff --git a/api-server-multistage/app/run.sh b/api-server-multistage/app/run.sh new file mode 100755 index 0000000..121e648 --- /dev/null +++ b/api-server-multistage/app/run.sh @@ -0,0 +1,9 @@ +#!/usr/bin/sh + +# start command with exec to replace execution shell and properly receive signals from docker +# without exec, container can't be gracefully terminated with ctrl+c or docker stop +exec uvicorn \ + main:app \ + --host 0.0.0.0 \ + --port 3000 \ + --lifespan off diff --git a/api-server/Dockerfile b/api-server/Dockerfile index d8ff8c2..5bc8129 100644 --- a/api-server/Dockerfile +++ b/api-server/Dockerfile @@ -1,14 +1,19 @@ FROM python:3.11-slim-bookworm +# set virtual env path ENV \ PATH=/venv/bin:$PATH +# does nothing, for documentation only EXPOSE 3000 +# create and set main app directory WORKDIR /app +# copy app files to /app directory COPY ./app . +# install dependencies RUN \ python -m venv /venv && \ pip install -r requirements.txt