Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
chatbot-canifa-feedback
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
chatbot-canifa-feedback
Commits
7fd76787
Commit
7fd76787
authored
Mar 17, 2026
by
Vũ Hoàng Anh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf: multi-stage Docker builds, .dockerignore, singleton StarRocks connection
parent
7b429387
Pipeline
#3378
failed with stage
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
122 additions
and
28 deletions
+122
-28
.dockerignore
backend/.dockerignore
+43
-5
Dockerfile.dev
backend/Dockerfile.dev
+31
-13
Dockerfile.prod
backend/Dockerfile.prod
+43
-5
product_route.py
backend/api/product_route.py
+5
-5
No files found.
backend/.dockerignore
View file @
7fd76787
# ═══ Git & IDE ═══
.git
.gitignore
.vscode
.idea
*.swp
*.swo
# ═══ Python cache ═══
__pycache__
__pycache__
*.pyc
*.pyc
.env
*.pyo
*.egg-info
.pytest_cache
.mypy_cache
.ruff_cache
# ═══ Virtual environments ═══
.venv
.venv
venv
venv
.git
env
.gitignore
# ═══ Docker ═══
Dockerfile*
docker-compose*
.dockerignore
.dockerignore
logs
data
# ═══ Dev & test files ═══
tests/
*.test.py
setup_readonly_user.py
# ═══ Docs & artifacts ═══
*.md
LICENSE
# ═══ OS files ═══
.DS_Store
Thumbs.db
# ═══ Logs ═══
*.log
logs/
# ═══ Local env backup ═══
.env.local
.env.backup
.env.example
backend/Dockerfile.dev
View file @
7fd76787
# ============================================================
# ============================================================
# DOCKERFILE.DEV
- Local Development (Hot Reload + Cache
)
# DOCKERFILE.DEV
— Multi-stage Dev Build (Hot Reload
)
# ============================================================
# ============================================================
# Sử dụng Python 3.11 Slim để tối ưu dung lượng
# Stage 1: Builder — install dependencies
# Stage 2: Runtime — dev server with reload
# ============================================================
# ──── Stage 1: Builder ────
FROM python:3.11-slim AS builder
WORKDIR /build
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt \
&& pip install --no-cache-dir --user watchdog[watchmedo]
# ──── Stage 2: Runtime ────
FROM python:3.11-slim
FROM python:3.11-slim
# Thiết lập thư mục làm việc
WORKDIR /app
WORKDIR /app
# Thiết lập biến môi trường
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 curl \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get purge -y --auto-remove
ENV PYTHONUNBUFFERED=1
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV ENV=development
ENV ENV=development
# Copy requirements.txt trước để tận dụng Docker cache
# Copy installed packages from builder
COPY requirements.txt .
COPY --from=builder /root/.local /root/.local
ENV PATH=/root/.local/bin:$PATH
# Cài đặt thư viện Python (Docker layer cache)
RUN pip install -r requirements.txt && pip install watchdog[watchmedo]
#
Copy toàn bộ source code vào image
#
Source code mounted via volume in docker-compose (not COPY)
COPY . .
COPY . .
# Expose port 5000
EXPOSE 5000
EXPOSE 5000
# Health check (optional)
HEALTHCHECK --interval=10s --timeout=5s --start-period=5s --retries=2 \
HEALTHCHECK --interval=10s --timeout=5s --start-period=5s --retries=2 \
CMD
python -c "import requests; requests.get('http://localhost:5000/docs')"
|| exit 1
CMD
curl -f http://localhost:5000/docs
|| exit 1
CMD ["gunicorn", "--workers", "1", "--worker-class", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:5000", "--timeout", "120", "--reload", "server:app"]
CMD ["gunicorn", "--workers", "1", "--worker-class", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:5000", "--timeout", "120", "--reload", "server:app"]
backend/Dockerfile.prod
View file @
7fd76787
# ============================================================
# DOCKERFILE.PROD — Multi-stage Production Build
# ============================================================
# Stage 1: Build — install dependencies in isolated layer
# Stage 2: Runtime — minimal image with only what's needed
# ============================================================
FROM python:3.11-slim
# ──── Stage 1: Builder ────
FROM python:3.11-slim AS builder
WORKDIR /build
# Install only build-time system deps (if any wheels need compiling)
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
# Install to user site-packages (no root pollution)
RUN pip install --no-cache-dir --user -r requirements.txt
# ──── Stage 2: Runtime ────
FROM python:3.11-slim
WORKDIR /app
WORKDIR /app
# Minimal runtime deps only
RUN apt-get update && apt-get install -y --no-install-recommends \
libpq5 curl \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get purge -y --auto-remove
ENV PYTHONUNBUFFERED=1
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV ENV=
development
ENV ENV=
production
COPY requirements.txt .
# Copy only installed packages from builder (no pip cache, no gcc)
RUN pip install -r requirements.txt
COPY --from=builder /root/.local /root/.local
ENV PATH=/root/.local/bin:$PATH
# Copy application source
COPY . .
COPY . .
EXPOSE 5000
EXPOSE 5000
...
@@ -19,4 +48,13 @@ EXPOSE 5000
...
@@ -19,4 +48,13 @@ EXPOSE 5000
ENV WORKERS=1
ENV WORKERS=1
ENV TIMEOUT=60
ENV TIMEOUT=60
CMD gunicorn server:app --workers $WORKERS --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:5000 --timeout $TIMEOUT
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:5000/docs || exit 1
CMD gunicorn server:app \
--workers $WORKERS \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:5000 \
--timeout $TIMEOUT \
--access-logfile - \
--error-logfile -
backend/api/product_route.py
View file @
7fd76787
...
@@ -9,7 +9,7 @@ from typing import Optional
...
@@ -9,7 +9,7 @@ from typing import Optional
from
fastapi
import
APIRouter
,
Query
from
fastapi
import
APIRouter
,
Query
from
fastapi.responses
import
JSONResponse
from
fastapi.responses
import
JSONResponse
from
common.starrocks_connection
import
StarRocksC
onnection
from
common.starrocks_connection
import
get_db_c
onnection
from
agent.tools.product_mapping
import
resolve_color
,
resolve_product_name
,
SYNONYM_TO_DB
from
agent.tools.product_mapping
import
resolve_color
,
resolve_product_name
,
SYNONYM_TO_DB
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -21,7 +21,7 @@ TABLE_NAME = "shared_source.magento_product_dimension_with_text_embedding"
...
@@ -21,7 +21,7 @@ TABLE_NAME = "shared_source.magento_product_dimension_with_text_embedding"
@
router
.
get
(
"/api/products/overview"
,
summary
=
"Product catalog KPI overview"
)
@
router
.
get
(
"/api/products/overview"
,
summary
=
"Product catalog KPI overview"
)
async
def
products_overview
():
async
def
products_overview
():
"""Return aggregate KPIs for the product catalog."""
"""Return aggregate KPIs for the product catalog."""
db
=
StarRocksC
onnection
()
db
=
get_db_c
onnection
()
try
:
try
:
rows
=
await
db
.
execute_query_async
(
f
"""
rows
=
await
db
.
execute_query_async
(
f
"""
SELECT
SELECT
...
@@ -104,7 +104,7 @@ async def products_list(
...
@@ -104,7 +104,7 @@ async def products_list(
offset
:
int
=
Query
(
0
,
ge
=
0
),
offset
:
int
=
Query
(
0
,
ge
=
0
),
):
):
"""Return paginated product listing grouped by internal_ref_code."""
"""Return paginated product listing grouped by internal_ref_code."""
db
=
StarRocksC
onnection
()
db
=
get_db_c
onnection
()
# Build WHERE clauses
# Build WHERE clauses
clauses
=
[]
clauses
=
[]
...
@@ -234,7 +234,7 @@ async def products_colors(
...
@@ -234,7 +234,7 @@ async def products_colors(
code
:
str
=
Query
(
...
,
description
=
"internal_ref_code"
),
code
:
str
=
Query
(
...
,
description
=
"internal_ref_code"
),
):
):
"""Return all color variants for a given internal_ref_code."""
"""Return all color variants for a given internal_ref_code."""
db
=
StarRocksC
onnection
()
db
=
get_db_c
onnection
()
try
:
try
:
variants
=
await
db
.
execute_query_async
(
variants
=
await
db
.
execute_query_async
(
f
"""
f
"""
...
@@ -266,7 +266,7 @@ async def products_colors(
...
@@ -266,7 +266,7 @@ async def products_colors(
@
router
.
get
(
"/api/products/filters"
,
summary
=
"Available filter options"
)
@
router
.
get
(
"/api/products/filters"
,
summary
=
"Available filter options"
)
async
def
products_filters
():
async
def
products_filters
():
"""Return all available filter values for color, product_line, age, season."""
"""Return all available filter values for color, product_line, age, season."""
db
=
StarRocksC
onnection
()
db
=
get_db_c
onnection
()
try
:
try
:
colors
=
await
db
.
execute_query_async
(
f
"""
colors
=
await
db
.
execute_query_async
(
f
"""
SELECT master_color, COUNT(DISTINCT internal_ref_code) AS cnt
SELECT master_color, COUNT(DISTINCT internal_ref_code) AS cnt
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment