1- # TestTeller Agent - Dual-Feedback RAG Architecture
2- # Multi-stage Docker build for next-generation AI-powered test automation platform
3- # Build stage
4- FROM ubuntu:22.04 AS builder
1+ # TestTeller Agent - Optimized Docker Build
2+ # Multi-stage build optimized for minimal size
3+ FROM python:3.11-slim AS builder
54
6- # Set environment variables
5+ # Build-time environment variables
76ENV PYTHONDONTWRITEBYTECODE=1 \
87 PYTHONUNBUFFERED=1 \
9- PYTHONPATH=/app \
108 PIP_NO_CACHE_DIR=1 \
11- DEBIAN_FRONTEND=noninteractive
9+ PIP_DISABLE_PIP_VERSION_CHECK=1
1210
13- # Set the working directory
1411WORKDIR /app
1512
16- # Install Python and build dependencies
17- RUN apt-get update && apt-get upgrade -y && \
18- apt-get install -y --no-install-recommends \
19- python3.11 \
20- python3.11-venv \
21- python3.11-dev \
22- python3-pip \
13+ # Install only essential build dependencies
14+ RUN apt-get update && apt-get install -y --no-install-recommends \
2315 gcc \
16+ g++ \
2417 libpoppler-cpp-dev \
2518 pkg-config \
26- sqlite3 \
27- && apt-get clean \
28- && rm -rf /var/lib/apt/lists/* \
29- && sqlite3 --version
30-
31- # Create and activate virtual environment
32- RUN python3.11 -m venv /opt/venv
33- ENV PATH="/opt/venv/bin:$PATH"
34-
35- # Copy only requirements first for better caching
36- COPY requirements.txt .
37- COPY setup.py .
38- COPY README.md .
39- COPY MANIFEST.in .
40- COPY pyproject.toml .
41- COPY testteller/ testteller/
19+ && rm -rf /var/lib/apt/lists/*
20+
21+ # Copy requirements and install Python dependencies
22+ COPY requirements.txt pyproject.toml README.md MANIFEST.in ./
23+ RUN pip install --no-cache-dir --user -r requirements.txt
4224
43- # Install dependencies and package in development mode
44- RUN pip install --no-cache-dir -r requirements.txt && \
45- pip install -e .
25+ # Copy source and install package
26+ COPY testteller/ testteller/
27+ RUN pip install --no-cache-dir --user -e .
4628
47- # Final stage
48- FROM ubuntu:22.04
29+ # Final stage - minimal runtime image
30+ FROM python:3.11-slim
4931
50- # Set environment variables
32+ # Runtime environment variables
5133ENV PYTHONDONTWRITEBYTECODE=1 \
5234 PYTHONUNBUFFERED=1 \
5335 PYTHONPATH=/app \
54- PATH="/opt/venv/bin:$PATH" \
55- DEBIAN_FRONTEND=noninteractive
36+ PATH="/home/testteller/.local/bin:$PATH"
5637
5738WORKDIR /app
5839
59- # Install runtime dependencies
60- RUN apt-get update && apt-get upgrade -y && \
61- apt-get install -y --no-install-recommends \
62- python3.11 \
63- libpoppler-cpp-dev \
40+ # Install only essential runtime dependencies
41+ RUN apt-get update && apt-get install -y --no-install-recommends \
42+ libpoppler-cpp0v5 \
6443 tesseract-ocr \
65- git \
66- wget \
67- curl \
6844 sqlite3 \
69- && apt-get clean \
45+ curl \
46+ git \
7047 && rm -rf /var/lib/apt/lists/* \
71- && sqlite3 --version
72-
73- # Copy virtual environment from builder
74- COPY --from=builder /opt/venv /opt/venv
75-
76- # Create necessary directories with proper permissions
77- RUN mkdir -p /app/chroma_data \
78- /app/temp_cloned_repos \
79- /app/testteller_generated_tests \
80- /app/testteller_automated_tests \
81- && chmod -R 777 /app/chroma_data \
82- && chmod -R 777 /app/temp_cloned_repos \
83- && chmod -R 777 /app/testteller_generated_tests \
84- && chmod -R 777 /app/testteller_automated_tests
85-
86- # Create entrypoint script with multi-LLM support and improved error handling
48+ && apt-get autoremove -y \
49+ && apt-get autoclean
50+
51+ # Create non-root user
52+ RUN useradd -m -u 1000 testteller
53+
54+ # Copy Python packages from builder
55+ COPY --from=builder --chown=testteller:testteller /root/.local /home/testteller/.local
56+
57+ # Copy application files
58+ COPY --from=builder --chown=testteller:testteller /app/testteller /app/testteller
59+ COPY --from=builder --chown=testteller:testteller /app/pyproject.toml /app/
60+
61+ # Create necessary directories
62+ RUN mkdir -p /app/{chroma_data,temp_cloned_repos,testteller_generated_tests,testteller_automated_tests} \
63+ && chown -R testteller:testteller /app
64+
65+ # Create optimized entrypoint script inline
8766RUN echo '#!/bin/bash\n \
88- set -e\n \
89- \n \
90- # Function to check ChromaDB health\n \
91- check_chromadb_health() {\n \
92- for i in {1..30}; do\n \
93- if curl -s -f http://chromadb:8000/api/v1/heartbeat > /dev/null; then\n \
94- return 0\n \
95- fi\n \
96- echo "Waiting for ChromaDB to be ready... ($i/30)"\n \
97- sleep 2\n \
67+ set -e\n \
68+ \n \
69+ check_chromadb_health() {\n \
70+ for i in {1..15}; do\n \
71+ if curl -s -f http://chromadb:8000/api/v1/heartbeat > /dev/null 2>&1; then\n \
72+ return 0\n \
73+ fi\n \
74+ echo "Waiting for ChromaDB... ($i/15)"\n \
75+ sleep 2\n \
9876 done\n \
99- echo "ChromaDB is not ready after 60 seconds "\n \
77+ echo "ChromaDB unavailable after 30s "\n \
10078 return 1\n \
101- }\n \
102- \n \
103- # Function to validate environment based on LLM provider\n \
104- validate_environment() {\n \
79+ }\n \
80+ \n \
81+ validate_environment() {\n \
10582 local provider=${LLM_PROVIDER:-gemini}\n \
106- echo "Validating environment for LLM provider: $provider"\n \
107- \n \
10883 case "$provider" in\n \
109- "gemini")\n \
110- if [ -z "$GOOGLE_API_KEY" ]; then\n \
111- echo "Error: GOOGLE_API_KEY is required for Gemini provider"\n \
112- return 1\n \
113- fi\n \
114- ;;\n \
115- "openai")\n \
116- if [ -z "$OPENAI_API_KEY" ]; then\n \
117- echo "Error: OPENAI_API_KEY is required for OpenAI provider"\n \
118- return 1\n \
119- fi\n \
120- ;;\n \
121- "claude")\n \
122- if [ -z "$CLAUDE_API_KEY" ]; then\n \
123- echo "Error: CLAUDE_API_KEY is required for Claude provider"\n \
124- return 1\n \
125- fi\n \
126- if [ -z "$OPENAI_API_KEY" ]; then\n \
127- echo "Error: OPENAI_API_KEY is also required for Claude provider (for embeddings)"\n \
128- return 1\n \
129- fi\n \
130- ;;\n \
131- "llama")\n \
132- echo "Note: Llama provider uses local Ollama - no API key required"\n \
133- echo "Make sure OLLAMA_BASE_URL is properly configured: ${OLLAMA_BASE_URL:-http://localhost:11434}"\n \
134- ;;\n \
135- *)\n \
136- echo "Error: Unsupported LLM provider: $provider"\n \
137- echo "Supported providers: gemini, openai, claude, llama"\n \
138- return 1\n \
139- ;;\n \
84+ "gemini") [ -n "$GOOGLE_API_KEY" ] || { echo "Error: GOOGLE_API_KEY required"; return 1; };;\n \
85+ "openai") [ -n "$OPENAI_API_KEY" ] || { echo "Error: OPENAI_API_KEY required"; return 1; };;\n \
86+ "claude") \n \
87+ [ -n "$CLAUDE_API_KEY" ] || { echo "Error: CLAUDE_API_KEY required"; return 1; }\n \
88+ [ -n "$OPENAI_API_KEY" ] || { echo "Error: OPENAI_API_KEY also required"; return 1; };;\n \
89+ "llama") echo "Using Ollama at ${OLLAMA_BASE_URL:-http://host.docker.internal:11434}";;\n \
90+ *) echo "Error: Unsupported provider: $provider"; return 1;;\n \
14091 esac\n \
141- echo "Environment validation passed for $provider provider"\n \
142- }\n \
143- \n \
144- # Function to display configuration info\n \
145- display_config_info() {\n \
146- echo "=== TestTeller Configuration ==="\n \
147- echo "LLM Provider: ${LLM_PROVIDER:-gemini}"\n \
148- echo "ChromaDB Host: ${CHROMA_DB_HOST:-chromadb}"\n \
149- echo "Default Collection: ${DEFAULT_COLLECTION_NAME:-test_documents}"\n \
150- echo "Log Level: ${LOG_LEVEL:-INFO}"\n \
151- echo "================================"\n \
152- }\n \
153- \n \
154- if [ "$1" = "serve" ]; then\n \
155- display_config_info\n \
156- echo "🤖 TestTeller Agent - Dual-Feedback RAG Architecture"\n \
157- echo "Next-generation self-improving test automation platform"\n \
158- echo ""\n \
159- echo "Container is running. Use one of the following commands:"\n \
160- echo " docker-compose exec app testteller --help"\n \
161- echo " docker-compose exec app testteller configure"\n \
162- echo ""\n \
163- echo "📚 RAG-Enhanced Workflows:"\n \
164- echo " # Ingest with enhanced parsing"\n \
165- echo " docker-compose exec app testteller ingest-docs doc.pdf -c collection -e"\n \
166- echo " # Generate with self-learning feedback"\n \
167- echo " docker-compose exec app testteller generate \" API tests\" -c collection"\n \
168- echo " # Automate with context discovery"\n \
169- echo " docker-compose exec app testteller automate tests.md -c collection -l python -F pytest"\n \
170- echo ""\n \
171- echo "🔧 Multi-LLM Support:"\n \
172- echo " Set LLM_PROVIDER: gemini (default), openai, claude, llama"\n \
173- echo " Configure API keys based on your chosen provider"\n \
174- echo ""\n \
175- echo "🔄 Feedback Loop: ${ENABLE_TEST_CASE_FEEDBACK:-true} | Quality Threshold: ${MIN_QUALITY_SCORE_FOR_STORAGE:-0.7}"\n \
176- # Keep container running\n \
92+ }\n \
93+ \n \
94+ if [ "$1" = "serve" ]; then\n \
95+ echo "🤖 TestTeller Agent - Optimized Container"\n \
96+ echo "Provider: ${LLM_PROVIDER:-gemini} | ChromaDB: ${CHROMA_DB_HOST:-chromadb}"\n \
17797 tail -f /dev/null\n \
178- else\n \
179- # Validate environment\n \
98+ else\n \
18099 validate_environment\n \
181- # Check ChromaDB health before running commands\n \
182100 check_chromadb_health\n \
183- # Unset GITHUB_TOKEN if empty to avoid validation errors\n \
184- if [ -z "$GITHUB_TOKEN" ]; then\n \
185- unset GITHUB_TOKEN\n \
186- fi\n \
187- # Run the command\n \
101+ [ -z "$GITHUB_TOKEN" ] && unset GITHUB_TOKEN\n \
188102 python -m testteller.main "$@"\n \
189- fi' > /app/entrypoint.sh && \
190- chmod +x /app/entrypoint.sh
191-
192- # Copy the application code
193- COPY . .
103+ fi' > /app/entrypoint.sh && chmod +x /app/entrypoint.sh
194104
195- # Create a non-root user and switch to it
196- RUN useradd -m -u 1000 testteller && \
197- chown -R testteller:testteller /app
198105USER testteller
199106
200- # Add healthcheck
201- HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
107+ # Minimal healthcheck
108+ HEALTHCHECK --interval=60s --timeout=10s --start-period=30s --retries=2 \
202109 CMD curl -f http://chromadb:8000/api/v1/heartbeat || exit 1
203110
204- # Set the entrypoint
205111ENTRYPOINT ["/app/entrypoint.sh" ]
206112CMD ["serve" ]
0 commit comments