Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b006711
images from poc and bbqs work from slack
tekrajchhetri Feb 5, 2026
b30502f
design document for pi-grants-skills kg
tekrajchhetri Feb 5, 2026
d433500
time added
tekrajchhetri Feb 5, 2026
33ab5d2
removed "RDF-based Knowledge Graph"
tekrajchhetri Feb 17, 2026
1b362ed
admin mermaid diagram added
tekrajchhetri Feb 17, 2026
e0f05e4
Data Flow diagram added
tekrajchhetri Feb 17, 2026
a5fef76
potential API endpoints added
tekrajchhetri Feb 17, 2026
0d62a0a
added requirements and cleaned.
tekrajchhetri Feb 17, 2026
6b29e06
UI info added
tekrajchhetri Feb 17, 2026
111a874
Update UI implementation guidelines for Next.js
tekrajchhetri Feb 17, 2026
d636226
removed line
tekrajchhetri Feb 17, 2026
0e1565c
Merge branch 'design_docs' of github.com:sensein/BrainKB into design_…
tekrajchhetri Feb 17, 2026
64ee4d2
Create PI-Grant-Skills-Research-microservice.md
tekrajchhetri Feb 19, 2026
ed4decc
Create PI-Grant-Skills-Research-model.md
tekrajchhetri Feb 19, 2026
31c45b3
removed Implementation (API Endpoints)
tekrajchhetri Feb 19, 2026
1d7b621
moved Sequence diagram and paper references added
tekrajchhetri Feb 19, 2026
b48c17c
Update requirements.txt
tekrajchhetri Apr 29, 2026
0389999
Update env.template
tekrajchhetri Apr 29, 2026
6a2fb56
updated database to include OAuthIdentity information
tekrajchhetri Apr 29, 2026
4c4f235
oauth + rbc information added
tekrajchhetri Apr 29, 2026
b7a0a6f
env variable info updated
tekrajchhetri Apr 29, 2026
180e1f6
globus + oauth handle for token generation
tekrajchhetri Apr 29, 2026
a32fc41
updated user management to store profile information + globus integra…
tekrajchhetri Apr 30, 2026
d2316ed
added usermanagement
tekrajchhetri Apr 30, 2026
3694364
check diff env variables
tekrajchhetri Apr 30, 2026
b930756
Create README.unified-docker.md
tekrajchhetri Apr 30, 2026
17456bf
Merge branch 'main' into user-rbac
tekrajchhetri May 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 157 additions & 6 deletions Dockerfile.unified
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Unified Dockerfile for BrainKB Services
# Deploys: APItokenmanager, query_service, ml_service, and oxigraph
# Deploys: APItokenmanager, query_service, ml_service, usermanagement_service, and oxigraph

# Note: Oxigraph binary extraction skipped - oxigraph image is distroless
# Oxigraph will be run as a separate service in docker-compose or use the fallback script

# Main build stage
FROM python:3.10-slim
# Python 3.11+ required: synthscholar (ml_service) depends on it.
FROM python:3.11-slim

# Set metadata
LABEL project="BrainyPedia" \
Expand Down Expand Up @@ -46,12 +47,88 @@ COPY ml_service/ /app/ml_service/
WORKDIR /app/ml_service
RUN pip install --use-deprecated=legacy-resolver "structsense==0.0.4" || \
pip install --use-deprecated=legacy-resolver --no-deps "structsense==0.0.4" && \
pip install -r requirements.txt
pip install --use-deprecated=legacy-resolver -r requirements.txt

# Copy usermanagement_service
COPY usermanagement_service/ /app/usermanagement_service/
WORKDIR /app/usermanagement_service
RUN pip install -r requirements.txt


# Create supervisor configuration
RUN mkdir -p /etc/supervisor/conf.d
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
RUN cat > /etc/supervisor/conf.d/supervisord.conf << 'EOF'
[unix_http_server]
file=/var/run/supervisor.sock
chmod=0700

[supervisord]
nodaemon=true
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[program:api_tokenmanager]
command=gunicorn -b 0.0.0.0:8000 APIAuthManager.wsgi:application
directory=/app/APItokenmanager
autostart=true
autorestart=true
startsecs=10
stderr_logfile=/var/log/supervisor/api_tokenmanager.err.log
stdout_logfile=/var/log/supervisor/api_tokenmanager.out.log
environment=PATH="/usr/local/bin:/usr/bin:/bin"
priority=100

[program:query_service]
command=gunicorn core.main:app --bind 0.0.0.0:8010 --workers 6 --worker-class uvicorn.workers.UvicornWorker --threads 2 --timeout 300 --keep-alive 120 --max-requests 1000 --max-requests-jitter 50
directory=/app/query_service
autostart=true
autorestart=true
startsecs=30
stderr_logfile=/var/log/supervisor/query_service.err.log
stdout_logfile=/var/log/supervisor/query_service.out.log
environment=PATH="/usr/local/bin:/usr/bin:/bin",WEB_CONCURRENCY="6"
startretries=10
stopwaitsecs=10
priority=200

[program:ml_service]
command=gunicorn core.main:app --bind 0.0.0.0:8007 --workers 6 --worker-class uvicorn.workers.UvicornWorker --threads 2 --max-requests 1000 --max-requests-jitter 50 --timeout 220 --keep-alive 220 --log-level debug
directory=/app/ml_service
autostart=true
autorestart=true
startsecs=15
stderr_logfile=/var/log/supervisor/ml_service.err.log
stdout_logfile=/var/log/supervisor/ml_service.out.log
environment=PATH="/usr/local/bin:/usr/bin:/bin",WEB_CONCURRENCY="6"

[program:usermanagement_service]
command=gunicorn core.main:app --bind 0.0.0.0:8004 --workers 4 --worker-class uvicorn.workers.UvicornWorker --threads 4 --max-requests 1000 --max-requests-jitter 50 --timeout 220 --keep-alive 220 --log-level debug
directory=/app/usermanagement_service
autostart=true
autorestart=true
startsecs=15
stderr_logfile=/var/log/supervisor/usermanagement_service.err.log
stdout_logfile=/var/log/supervisor/usermanagement_service.out.log
environment=PATH="/usr/local/bin:/usr/bin:/bin"
priority=300

[program:oxigraph]
command=/app/oxigraph/oxigraph_server --bind 0.0.0.0:7878 --storage /data
directory=/app/oxigraph
autostart=false
autorestart=false
stderr_logfile=/var/log/supervisor/oxigraph.err.log
stdout_logfile=/var/log/supervisor/oxigraph.out.log
environment=PATH="/usr/local/bin:/usr/bin:/bin",TMPDIR="/tmp"
startsecs=0
startretries=0
EOF

# Create directories for logs and data
# Ensure supervisor socket directory exists and is writable
Expand All @@ -68,11 +145,85 @@ RUN echo '#!/bin/bash' > /app/oxigraph/oxigraph_server && \
chmod +x /app/oxigraph/oxigraph_server

# Create startup script
COPY start.sh /app/start.sh
RUN cat > /app/start.sh << 'EOF'
#!/bin/bash
set -e

# Note: Oxigraph runs as a separate service in docker-compose

# Ensure supervisor socket directory exists and is writable
mkdir -p /var/run
chmod 755 /var/run

# Wait for PostgreSQL to be ready
# Use JWT_POSTGRES_DATABASE_USER if available, otherwise fall back to DB_USER
# This ensures we use the same user that PostgreSQL was initialized with
PG_USER="${JWT_POSTGRES_DATABASE_USER:-${DB_USER:-postgres}}"
PG_PASSWORD="${JWT_POSTGRES_DATABASE_PASSWORD:-${DB_PASSWORD}}"
PG_HOST="${JWT_POSTGRES_DATABASE_HOST_URL:-${DB_HOST:-postgres}}"
PG_DB="${JWT_POSTGRES_DATABASE_NAME:-${DB_NAME:-brainkb}}"

echo "Waiting for PostgreSQL to be ready..."
echo "Connecting as user: ${PG_USER} to database: ${PG_DB} on host: ${PG_HOST}"
until PGPASSWORD="$PG_PASSWORD" psql -h "$PG_HOST" -U "$PG_USER" -d "$PG_DB" -c '\q' 2>/dev/null; do
echo "PostgreSQL is unavailable - sleeping"
sleep 2
done
echo "PostgreSQL is ready!"

# Note: Oxigraph is optional - services will handle connection failures gracefully
# No need to wait for it here - services will retry when needed

# Run Django migrations for APItokenmanager if needed
cd /app/APItokenmanager
if [ -f .env ] || [ -n "$DB_NAME" ]; then
echo "Running Django migrations..."
python manage.py makemigrations || true
python manage.py migrate || true
python manage.py collectstatic --noinput || true

# Create superuser if credentials are provided and user doesn't exist
if [ -n "$DJANGO_SUPERUSER_USERNAME" ] && [ -n "$DJANGO_SUPERUSER_EMAIL" ] && [ -n "$DJANGO_SUPERUSER_PASSWORD" ]; then
echo "Creating Django superuser..."
export DJANGO_SUPERUSER_USERNAME DJANGO_SUPERUSER_EMAIL DJANGO_SUPERUSER_PASSWORD
python manage.py shell << 'PYTHON_SCRIPT' || true
import os
from django.contrib.auth import get_user_model
User = get_user_model()
username = os.environ.get('DJANGO_SUPERUSER_USERNAME')
email = os.environ.get('DJANGO_SUPERUSER_EMAIL')
password = os.environ.get('DJANGO_SUPERUSER_PASSWORD')
if username and email and password:
if not User.objects.filter(username=username).exists():
User.objects.create_superuser(username, email, password)
print(f'Superuser {username} created successfully')
else:
print(f'Superuser {username} already exists')
else:
print('Error: Missing superuser credentials in environment')
PYTHON_SCRIPT
else
echo "Warning: DJANGO_SUPERUSER credentials not provided. Superuser not created."
echo "You can create one manually with: python manage.py createsuperuser"
fi

echo "Django migrations completed"
fi

# Ensure supervisor socket directory exists and is writable (in case /var/run is tmpfs)
mkdir -p /var/run
chmod 755 /var/run

# Start supervisor
echo "Starting all services..."
# Use our config file that includes socket configuration
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
EOF

RUN chmod +x /app/start.sh

# Expose ports
EXPOSE 8000 8007 8010
EXPOSE 8000 8004 8007 8010

# Set working directory
WORKDIR /app
Expand Down
Loading