4343# Size Impact: ~150MB (Python slim + runtime deps)
4444# ==============================================================================
4545
46- FROM python:3.13.5 -slim@sha256:4c2cf9917bd1cbacc5e9b07320025bdb7cdf2df7b0ceaccb55e9dd7e30987419 AS base
46+ FROM python:3.13.7 -slim@sha256:27f90d79cc85e9b7b2560063ef44fa0e9eaae7a7c3f5a9f74563065c5477cc24 AS base
4747
4848# OCI Labels for container metadata and registry compliance
4949# These labels provide important metadata for container registries and tools
@@ -81,13 +81,12 @@ RUN echo 'path-exclude /usr/share/doc/*' > /etc/dpkg/dpkg.cfg.d/01_nodoc && \
8181RUN apt-get update && \
8282 apt-get upgrade -y && \
8383 apt-get install -y --no-install-recommends --no-install-suggests \
84- ffmpeg=7:5.1.6-0+deb12u1 \
85- git=1:2.39.5-0+deb12u2 \
86- libcairo2=1.16.0-7 \
87- libgdk-pixbuf2.0-0=2.40.2-2 \
88- libpango1.0-0=1.50.12+ds-1 \
89- libpangocairo-1.0-0=1.50.12+ds-1 \
90- shared-mime-info=2.2-1 \
84+ git=1:2.47.2-0.2 \
85+ libcairo2=1.18.4-1+b1 \
86+ libgdk-pixbuf-2.0-0=2.42.12+dfsg-4 \
87+ libpango-1.0-0=1.56.3-1 \
88+ libpangocairo-1.0-0=1.56.3-1 \
89+ shared-mime-info=2.4-5+b2 \
9190 # Cleanup package manager caches to reduce layer size
9291 && apt-get clean \
9392 && rm -rf /var/lib/apt/lists/*
@@ -108,7 +107,7 @@ ENV PYTHONUNBUFFERED=1 \
108107# ==============================================================================
109108# BUILD STAGE - Development Tools and Dependency Installation
110109# ==============================================================================
111- # Purpose: Installs build tools, Uv , and application dependencies
110+ # Purpose: Installs build tools, Poetry , and application dependencies
112111# Contains: Compilers, headers, build tools, complete Python environment
113112# Size Impact: ~1.3GB (includes all build dependencies and Python packages)
114113# ==============================================================================
@@ -122,21 +121,37 @@ RUN apt-get update && \
122121 apt-get upgrade -y && \
123122 apt-get install -y --no-install-recommends \
124123 # GCC compiler and build essentials for native extensions
125- build-essential=12.9 \
124+ build-essential=12.12 \
126125 # Additional utilities required by some Python packages
127- findutils=4.9 .0-4 \
126+ findutils=4.10 .0-3 \
128127 # Development headers for graphics libraries
129- libcairo2-dev=1.16.0-7 \
128+ libcairo2-dev=1.18.4-1+b1 \
130129 # Foreign Function Interface library for Python extensions
131- libffi-dev =3.4.4-1 \
130+ libffi8 =3.4.8-2 \
132131 # Cleanup to reduce intermediate layer size
133132 && apt-get clean \
134133 && rm -rf /var/lib/apt/lists/*
135134
136- ENV UV_VERSION=0.8.0
135+ # Poetry configuration for dependency management
136+ # These settings optimize Poetry for containerized builds
137137
138- # Install Uv using pip
139- RUN pip install uv==$UV_VERSION
138+ # POETRY_NO_INTERACTION=1 : Disables interactive prompts for CI/CD
139+ # POETRY_VIRTUALENVS_CREATE=1 : Ensures virtual environment creation
140+ # POETRY_VIRTUALENVS_IN_PROJECT=1: Creates .venv in project directory
141+ # POETRY_CACHE_DIR=/tmp/poetry_cache: Uses temporary directory for cache
142+ # POETRY_INSTALLER_PARALLEL=true : Enables parallel package installation
143+
144+ ENV POETRY_VERSION=2.1.1 \
145+ POETRY_NO_INTERACTION=1 \
146+ POETRY_VIRTUALENVS_CREATE=1 \
147+ POETRY_VIRTUALENVS_IN_PROJECT=1 \
148+ POETRY_CACHE_DIR=/tmp/poetry_cache \
149+ POETRY_INSTALLER_PARALLEL=true
150+
151+ # Install Poetry using pip with BuildKit cache mount for efficiency
152+ # Cache mount prevents re-downloading Poetry on subsequent builds
153+ RUN --mount=type=cache,target=/root/.cache \
154+ pip install poetry==$POETRY_VERSION
140155
141156# Set working directory for all subsequent operations
142157WORKDIR /app
@@ -148,13 +163,15 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
148163# Copy dependency files first for optimal Docker layer caching
149164# Changes to these files will invalidate subsequent layers
150165# OPTIMIZATION: This pattern maximizes cache hits during development
151- COPY pyproject.toml uv .lock ./
166+ COPY pyproject.toml poetry .lock ./
152167
153- # Install dependencies
154- RUN --mount=type=cache,target=/root/.cache/uv \
155- --mount=type=bind,source=uv.lock,target=uv.lock \
156- --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
157- uv sync --locked --no-install-project
168+ # Install Python dependencies using Poetry
169+ # PERFORMANCE: Cache mount speeds up subsequent builds
170+ # SECURITY: --only main excludes development dependencies from production
171+ # NOTE: Install dependencies only first, package itself will be installed later with git context
172+ RUN --mount=type=cache,target=$POETRY_CACHE_DIR \
173+ --mount=type=cache,target=/root/.cache/pip \
174+ poetry install --only main --no-root --no-directory
158175
159176# Copy application files in order of change frequency (Docker layer optimization)
160177# STRATEGY: Files that change less frequently are copied first to maximize cache reuse
@@ -163,16 +180,13 @@ RUN --mount=type=cache,target=/root/.cache/uv \
163180# These are typically static configuration that changes infrequently
164181COPY config/ ./config/
165182
166- # 2. Database migration files (change infrequently)
167- # Alembic migrations are relatively stable
168- COPY src/tux/database/migrations/ ./src/tux/database/migrations /
183+ # 2. Database schema files (change infrequently)
184+ # Prisma schema and migrations are relatively stable
185+ COPY prisma/ ./prisma /
169186
170187# 3. Main application code (changes more frequently)
171188# The core bot code is most likely to change during development
172- # Copy the entire src tree so Poetry can find packages from "src"
173- COPY src/ ./src/
174- # Keep runtime path stable at /app/tux for later stages and health checks
175- RUN cp -a src/tux ./tux
189+ COPY tux/ ./tux/
176190
177191# 4. Root level files needed for installation
178192# These include metadata and licensing information
@@ -201,9 +215,12 @@ RUN set -eux; \
201215 fi; \
202216 echo "Building version: $(cat /app/VERSION)"
203217
204- # Sync the project
205- RUN --mount=type=cache,target=/root/.cache/uv \
206- uv sync --locked
218+ # Install the application and generate Prisma client
219+ # COMPLEXITY: This step requires multiple operations that must be done together
220+ RUN --mount=type=cache,target=$POETRY_CACHE_DIR \
221+ --mount=type=cache,target=/root/.cache \
222+ # Install the application package itself
223+ poetry install --only main
207224
208225# ==============================================================================
209226# DEVELOPMENT STAGE - Development Environment
@@ -232,7 +249,7 @@ RUN set -eux; \
232249 chsh -s /usr/bin/zsh && \
233250 apt-get clean && \
234251 rm -rf /var/lib/apt/lists/*; \
235- fi
252+ fi; \
236253# Fix ownership of all application files for non-root user
237254# SECURITY: Ensures the application runs with proper permissions
238255COPY --from=build --chown=nonroot:nonroot /app /app
@@ -241,21 +258,22 @@ RUN set -eux; \
241258 # Create application cache and temporary directories
242259 # These directories are used by the bot for caching and temporary files
243260 mkdir -p /app/.cache/tldr /app/temp; \
244- # Create user cache directories (fixes permission issues for npm and other tools )
261+ # Create user cache directories (fixes permission issues for Prisma/ npm)
245262 mkdir -p /home/nonroot/.cache /home/nonroot/.npm; \
246- # Ensure correct ownership for nonroot user to write into these directories
247- chown -R nonroot:nonroot /app/.cache /app/temp /home/nonroot/.cache /home/nonroot/.npm
248263# Switch to non-root user for all subsequent operations
249264# SECURITY: Follows principle of least privilege
250265USER nonroot
251266
252- # Install development dependencies
267+ # Install development dependencies and setup Prisma
253268# DEVELOPMENT: These tools are needed for linting, testing, and development workflow
254- RUN uv sync --dev
269+ RUN poetry install --only dev --no-root --no-directory && \
270+ poetry run prisma py fetch && \
271+ poetry run prisma generate
255272
256273# Development container startup command
257- # WORKFLOW: Starts the bot in development mode with automatic database migrations
258- CMD ["uv" , "run" , "tux" , "--dev" , "start" ]
274+ # WORKFLOW: Regenerates Prisma client and starts the bot in development mode
275+ # This ensures the database client is always up-to-date with schema changes
276+ CMD ["sh" , "-c" , "poetry run prisma generate && exec poetry run tux --dev start" ]
259277
260278# ==============================================================================
261279# PRODUCTION STAGE - Minimal Runtime Environment
@@ -266,7 +284,7 @@ CMD ["uv", "run", "tux", "--dev", "start"]
266284# Size Impact: ~440MB (73% reduction from development image)
267285# ==============================================================================
268286
269- FROM python:3.13.5 -slim@sha256:4c2cf9917bd1cbacc5e9b07320025bdb7cdf2df7b0ceaccb55e9dd7e30987419 AS production
287+ FROM python:3.13.7 -slim@sha256:27f90d79cc85e9b7b2560063ef44fa0e9eaae7a7c3f5a9f74563065c5477cc24 AS production
270288
271289# Duplicate OCI labels for production image metadata
272290# COMPLIANCE: Ensures production images have proper metadata for registries
@@ -293,17 +311,18 @@ RUN echo 'path-exclude /usr/share/doc/*' > /etc/dpkg/dpkg.cfg.d/01_nodoc && \
293311 echo 'path-exclude /usr/share/man/*' >> /etc/dpkg/dpkg.cfg.d/01_nodoc && \
294312 echo 'path-exclude /usr/share/groff/*' >> /etc/dpkg/dpkg.cfg.d/01_nodoc && \
295313 echo 'path-exclude /usr/share/info/*' >> /etc/dpkg/dpkg.cfg.d/01_nodoc && \
296- echo 'path-exclude /usr/share/lintian/*' >> /etc/dpkg/dpkg.cfg.d/01_nodoc
314+ echo 'path-exclude /usr/share/lintian/*' >> /etc/dpkg/dpkg.cfg.d/01_nodoc && \
315+ echo 'path-exclude /usr/share/linda/*' >> /etc/dpkg/dpkg.cfg.d/01_nodoc
297316
298317# Install ONLY runtime dependencies (minimal subset of base stage)
299318# SECURITY: Update all packages first, then install minimal runtime dependencies
300319# SIZE: Significantly smaller than build stage dependencies
301320RUN apt-get update && \
302321 apt-get upgrade -y && \
303322 apt-get install -y --no-install-recommends --no-install-suggests \
304- libcairo2=1.16.0-7 \
305- libffi8=3.4.4-1 \
306- coreutils=9.1-1 \
323+ libcairo2=1.18.4-1+b1 \
324+ libffi8=3.4.8-2 \
325+ coreutils=9.7-3 \
307326 # Aggressive cleanup to minimize image size
308327 && apt-get clean \
309328 && rm -rf /var/lib/apt/lists/* \
@@ -336,7 +355,7 @@ ENV VIRTUAL_ENV=/app/.venv \
336355# EFFICIENCY: Only copies what's needed for runtime
337356COPY --from=build --chown=nonroot:nonroot /app/.venv /app/.venv
338357COPY --from=build --chown=nonroot:nonroot /app/tux /app/tux
339-
358+ COPY --from=build --chown=nonroot:nonroot /app/prisma /app/prisma
340359COPY --from=build --chown=nonroot:nonroot /app/config /app/config
341360COPY --from=build --chown=nonroot:nonroot /app/pyproject.toml /app/pyproject.toml
342361COPY --from=build --chown=nonroot:nonroot /app/VERSION /app/VERSION
@@ -353,32 +372,35 @@ RUN set -eux; \
353372 rm -rf /home/nonroot/.npm/_cacache_; \
354373 chown nonroot:nonroot /app/.cache /app/temp /home/nonroot/.cache /home/nonroot/.npm
355374
356- # Switch to non-root user for final optimizations
375+ # Switch to non-root user and finalize Prisma binaries
357376USER nonroot
377+ RUN /app/.venv/bin/python -m prisma py fetch \
378+ && /app/.venv/bin/python -m prisma generate
358379
359380USER root
360- # Aggressive cleanup and optimization
381+ # Aggressive cleanup and optimization after Prisma setup
361382# PERFORMANCE: Single RUN reduces layer count and enables atomic cleanup
362- # SIZE: Removes unnecessary files to minimize final image size
383+ # SIZE: Removes unnecessary files to minimize final image size but preserves Prisma binaries
363384RUN set -eux; \
364385 # VIRTUAL ENVIRONMENT CLEANUP
365386 # The following operations remove unnecessary files from the Python environment
366387 # This can reduce the size by 30-50MB without affecting functionality
367388 # Remove Python bytecode files (will be regenerated as needed)
368389 find /app/.venv -name "*.pyc" -delete; \
369390 find /app/.venv -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true; \
370- # Remove test directories from installed packages
391+ # Remove test directories from installed packages (but preserve prisma binaries)
371392 # These directories contain test files that are not needed in production
372- for test_dir in tests testing "* test*" ; do \
373- find /app/.venv -name "$test_dir" -type d -exec rm -rf {} + 2>/dev/null || true; \
393+ for test_dir in tests testing "test*" ; do \
394+ find /app/.venv -name "$test_dir" -type d -not -path "*/prisma*" - exec rm -rf {} + 2>/dev/null || true; \
374395 done; \
375- # Remove documentation files from installed packages
396+ # Remove documentation files from installed packages (but preserve prisma docs)
376397 # These files take up significant space and are not needed in production
377398 for doc_pattern in "*.md" "*.txt" "*.rst" "LICENSE*" "NOTICE*" "COPYING*" "CHANGELOG*" "README*" "HISTORY*" "AUTHORS*" "CONTRIBUTORS*" ; do \
378- find /app/.venv -name "$doc_pattern" -delete 2>/dev/null || true; \
399+ find /app/.venv -name "$doc_pattern" -not -path "*/prisma*" - delete 2>/dev/null || true; \
379400 done; \
380401 # Remove large development packages that are not needed in production
381402 # These packages (pip, setuptools, wheel) are only needed for installing packages
403+ # NOTE: Preserving packages that Prisma might need
382404 for pkg in setuptools wheel pkg_resources; do \
383405 rm -rf /app/.venv/lib/python3.13/site-packages/${pkg}* 2>/dev/null || true; \
384406 rm -rf /app/.venv/bin/${pkg}* 2>/dev/null || true; \
@@ -387,7 +409,7 @@ RUN set -eux; \
387409 # Compile Python bytecode for performance optimization
388410 # PERFORMANCE: Pre-compiled bytecode improves startup time
389411 # Note: Some compilation errors are expected and ignored
390- /app/.venv/bin/python -m compileall -b -q /app/src/ tux /app/.venv/lib/python3.13/site-packages 2>/dev/null || true
412+ /app/.venv/bin/python -m compileall -b -q /app/tux /app/.venv/lib/python3.13/site-packages 2>/dev/null || true
391413
392414# Switch back to non-root user for runtime
393415USER nonroot
@@ -396,7 +418,7 @@ USER nonroot
396418# MONITORING: Allows Docker/Kubernetes to monitor application health
397419# RELIABILITY: Enables automatic restart of unhealthy containers
398420HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
399- CMD python -c "import tux.cli.core; import tux.shared.config .env; print('Health check passed')" || exit 1
421+ CMD python -c "import tux.cli.core; import tux.utils .env; print('Health check passed')" || exit 1
400422
401423# --interval=30s : Check health every 30 seconds
402424# --timeout=10s : Allow 10 seconds for health check to complete
0 commit comments