Multistage build

This commit is contained in:
Eden Kirin
2024-01-11 13:20:06 +01:00
parent d96368feb6
commit 176d22bbe4
9 changed files with 396 additions and 60 deletions

View File

@ -0,0 +1,5 @@
**/.env/
**/__pycache__/
**/Makefile
**/Dockerfile
*.log

View File

@ -0,0 +1,31 @@
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
# install sys libs and create virtual env
RUN \
apt update && \
apt install -y gcc libpq-dev python3-dev && \
python -m venv /venv
# copy app files to /app directory
COPY ./app .
# install dependencies && cleanup
RUN \
pip install -r requirements.txt && \
apt purge --auto-remove -y
# start shell script when container starts
ENTRYPOINT ["/app/run.sh"]
# no additional parameters to run.sh script
CMD []

View File

@ -0,0 +1,51 @@
FROM python:3.11-slim-bookworm AS install-dependencies
# create and set main app directory
WORKDIR /app
# set virtual env path
ENV \
PATH=/venv/bin:$PATH
# install sys libs and create virtual env
RUN \
apt update && \
apt install -y gcc libpq-dev python3-dev && \
python -m venv /venv
# copy app files to /app directory
COPY ./app/requirements.txt .
# install dependencies && cleanup
RUN \
pip install -r requirements.txt
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 --from=install-dependencies /venv /venv
# copy app files to /app directory
COPY ./app .
RUN ls -alF /
RUN ls -alF /venv
RUN ls -alF /venv/bin
RUN ls -alF /app
# start shell script when container starts
ENTRYPOINT ["/app/run.sh"]
# no additional parameters to run.sh script
CMD []

28
multistage-build/Makefile Normal file
View File

@ -0,0 +1,28 @@
IMAGE_NAME=api-server-ms
CONTAINER_NAME=api-server-ms
build: clean
@docker build \
--progress=plain \
--tag $(IMAGE_NAME) \
.
build-multistage: clean
@docker build \
--progress=plain \
--tag $(IMAGE_NAME) \
--file Dockerfile.multistage \
.
run:
@docker run \
--name $(IMAGE_NAME) \
--publish 3000:3000 \
--env CONTAINER_NAME="Awesome API server" \
--detach \
$(CONTAINER_NAME)
clean:
- @docker stop $(CONTAINER_NAME)
- @docker rm $(CONTAINER_NAME)
- @docker rmi $(IMAGE_NAME)

View File

@ -0,0 +1,2 @@
run:
@./run.sh

View File

@ -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()

View File

@ -0,0 +1,3 @@
fastapi
uvicorn
psycopg2

9
multistage-build/app/run.sh Executable file
View File

@ -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