Skip to content

Commit

Permalink
feat(docker): reduce image size (#363)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonperron authored Jan 12, 2025
1 parent 07ac4e3 commit 659f787
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 15 deletions.
17 changes: 17 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Ignore git related files
.github/
.gitignore

# Ignore folders not necessary for the docker image
docs/
tests/

# Ignore venv if any
venv/

# Ignore files not necessary for the docker image
CONTRIBUTING.md
*.png
*.json
LICENSE
Makefile
42 changes: 29 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,35 +1,51 @@
ARG PY_VERSION=3.12

#---------------------------------------------------------------------------------------
# Stage 1 → Builder image
#---------------------------------------------------------------------------------------
FROM python:$PY_VERSION-slim AS build-env

ARG VERSION

WORKDIR /app

# Install python deps
RUN python -m pip install --upgrade poetry wheel twine
RUN apt-get update && apt-get install -y --no-install-recommends build-essential \
&& rm -rf /var/lib/apt/lists/*
RUN python -m pip install --no-cache-dir --upgrade poetry wheel twine

# Install project deps
COPY pyproject.toml .
RUN poetry install --with dev
COPY pyproject.toml poetry.lock ./
RUN poetry install --with dev --no-root

# Copy code *after* installing deps to avoid unnecessarily invalidating cache
COPY . .

# Build the project
RUN poetry build
RUN PROJECT_VERSION=$(poetry version -s) && cp /app/dist/boaviztapi-$PROJECT_VERSION.tar.gz ./boaviztapi-$VERSION.tar.gz
RUN pip install boaviztapi-$VERSION.tar.gz && cp $(which uvicorn) /app
RUN PROJECT_VERSION=$(poetry version -s) && \
cp /app/dist/boaviztapi-$PROJECT_VERSION.tar.gz ./boaviztapi-$VERSION.tar.gz

#---------------------------------------------------------------------------------------
# Stage 2 → Runtime image
#---------------------------------------------------------------------------------------
FROM python:$PY_VERSION-slim AS run-env
# Python 3 surrogate unicode handling
# @see https://click.palletsprojects.com/en/7.x/python3/
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8

COPY --from=build-env /app /app
COPY --from=build-env /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
ENV PYTHONPATH=/usr/local/lib/python3.12/site-packages
ENV LC_ALL=C.UTF-8 \
LANG=C.UTF-8

ARG VERSION
WORKDIR /app

# Copy executable and dependencies
COPY --from=build-env /app/boaviztapi-$VERSION.tar.gz /app/
RUN pip install --no-cache-dir /app/boaviztapi-$VERSION.tar.gz

# Required in main.py
COPY --from=build-env /app/pyproject.toml /usr/local/lib/python3.12/site-packages/boaviztapi/

# Copy uvicorn executable
RUN pip install --no-cache-dir uvicorn

EXPOSE 5000
CMD ["./uvicorn", "boaviztapi.main:app", "--host", "0.0.0.0", "--port", "5000"]
CMD ["uvicorn", "boaviztapi.main:app", "--host", "0.0.0.0", "--port", "5000"]
18 changes: 16 additions & 2 deletions boaviztapi/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,27 @@

from fastapi.responses import HTMLResponse

def get_version_from_pyproject():
# List of potential locations for the pyproject.toml file
potential_paths = [
os.path.join(os.path.dirname(__file__), '../pyproject.toml'),
os.path.join(os.path.dirname(__file__), 'pyproject.toml'),
]

for path in potential_paths:
if os.path.exists(path):
with open(path, 'r') as f:
return toml.loads(f.read())['tool']['poetry']['version']

# Raise an error if the file is not found in any of the locations
raise FileNotFoundError("pyproject.toml not found in expected locations")

# Serverless frameworks adds a 'stage' prefix to the route used to serve applications
# We have to manage it to expose openapi doc on aws and generate proper links.
stage = os.environ.get('STAGE', None)
openapi_prefix = f"/{stage}" if stage else "/"
app = FastAPI(root_path=openapi_prefix) # Here is the magic
version = toml.loads(open(os.path.join(os.path.dirname(__file__), '../pyproject.toml'), 'r').read())['tool']['poetry'][
'version']
version = get_version_from_pyproject()
_logger = logging.getLogger(__name__)

origins = json.loads(os.getenv("ALLOWED_ORIGINS", '["*"]'))
Expand Down

0 comments on commit 659f787

Please sign in to comment.