Skip to content

Commit 34e9c9c

Browse files
committed
Docker images and compose files
1 parent 84f38d0 commit 34e9c9c

File tree

8 files changed

+418
-0
lines changed

8 files changed

+418
-0
lines changed

Makefile

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Makefile
2+
3+
# Define the directories containing the Dockerfiles
4+
DOCKER_API_DIR := docker/api
5+
DOCKER_APP_DIR := docker/app
6+
7+
# Define the image names
8+
API_IMAGE_NAME := llmstack-api
9+
APP_IMAGE_NAME := llmstack-app
10+
11+
12+
# Define the build targets
13+
.PHONY: all app client
14+
15+
all: app client
16+
17+
client:
18+
@echo "Building client..."
19+
cd llmstack/client && npm run build && cd ../../
20+
21+
api:
22+
@echo "Building client..."
23+
cd llmstack/client && npm run build && cd ../../
24+
25+
@echo "Building api image..."
26+
docker build -t $(API_IMAGE_NAME) -f $(DOCKER_API_DIR)/Dockerfile .
27+
28+
api-image:
29+
@echo "Building api image..."
30+
docker build -t $(API_IMAGE_NAME) -f $(DOCKER_API_DIR)/Dockerfile .
31+
32+
app:
33+
@echo "Building app image..."
34+
docker build -t $(APP_IMAGE_NAME) -f $(DOCKER_APP_DIR)/Dockerfile .

docker/.env.dev

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
DEBUG=True
2+
LOG_LEVEL=INFO
3+
SECRET_KEY='3!4^11rgx0-53)!n#18(1_^)&pj-3n^Afpc#mbm(+!fj4r$rp7ea!s'
4+
CIPHER_KEY_SALT=salt
5+
SINGLE_THREAD=False
6+
AUTORELOAD=True
7+
ALLOWED_HOSTS=*
8+
DATABASE_ENGINE=postgresql
9+
DATABASE_NAME=postgres
10+
DATABASE_USERNAME=postgres
11+
DATABASE_PASSWORD=
12+
DATABASE_HOST=postgres
13+
DATABASE_PORT=5432
14+
REDIS_PORT=6379
15+
REDIS_HOST=redis
16+
REDIS_DB=0
17+
STATIC_URL=static/
18+
19+
# Platform keys
20+
DEFAULT_OPENAI_API_KEY=
21+
DEFAULT_DREAMSTUDIO_API_KEY=
22+
DEFAULT_AZURE_OPENAI_API_KEY=
23+
DEFAULT_COHERE_API_KEY=
24+
DEFAULT_FOREFRONTAI_API_KEY=
25+
DEFAULT_ELEVENLABS_API_KEY=

docker/api/Dockerfile

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Stage 1: Compile and build code
2+
FROM python:3.11 AS builder
3+
4+
# Add poetry to the image
5+
RUN pip install --no-cache-dir poetry
6+
7+
# Copy pyproject.toml and poetry.lock
8+
ADD pyproject.toml /pyproject.toml
9+
ADD poetry.lock /poetry.lock
10+
11+
# Install dependencies
12+
RUN poetry config virtualenvs.create false
13+
RUN poetry install --no-root --no-dev --no-interaction --no-ansi
14+
RUN poetry install --only server --no-root --no-dev --no-interaction --no-ansi
15+
16+
# Download nltk and spacy data
17+
RUN mkdir -p /usr/local/share/nltk_data/tokenizers
18+
RUN mkdir -p /usr/local/share/nltk_data/taggers
19+
20+
ENV NLTK_DATA=/usr/local/share/nltk_data
21+
ARG UNIQUE_IDENTIFIER=promptly
22+
23+
# Install processors
24+
RUN poetry install --no-root --with processors
25+
26+
RUN python -m nltk.downloader -d /usr/local/share/nltk_data 'punkt'
27+
RUN python -m nltk.downloader -d /usr/local/share/nltk_data 'averaged_perceptron_tagger'
28+
RUN python -m spacy download en_core_web_sm
29+
30+
# Hack for installing chromadb embedding models
31+
RUN python -c "from chromadb.utils import embedding_functions as f; f.DefaultEmbeddingFunction()(['a'])"
32+
33+
RUN mkdir /code/
34+
WORKDIR /code/
35+
ADD ./manage.py /code/manage.py
36+
ADD ./llmstack /code/llmstack
37+
ADD ./docker /code/docker
38+
39+
# Environment variables
40+
ENV DJANGO_SETTINGS_MODULE=llmstack.server.settings
41+
42+
# Call collectstatic
43+
RUN python manage.py collectstatic --noinput --clear
44+
45+
# Stage 2: Build final image
46+
FROM python:3.11-slim
47+
48+
ARG APP_USER=appuser
49+
RUN groupadd -r ${APP_USER} && useradd --no-log-init -r -g ${APP_USER} ${APP_USER} \
50+
&& mkdir -p /home/${APP_USER} \
51+
&& mkdir -p /home/${APP_USER}/.cache/chroma \
52+
&& chown -R ${APP_USER}:${APP_USER} /home/${APP_USER} \
53+
&& chown -R ${APP_USER}:${APP_USER} /home/${APP_USER}/.cache/chroma
54+
55+
# Install runtime dependencies
56+
RUN set -ex \
57+
&& RUN_DEPS=" \
58+
libpcre3 \
59+
mime-support \
60+
ffmpeg \
61+
postgresql-client \
62+
gstreamer1.0-libav \
63+
libnss3-tools \
64+
libatk-bridge2.0-0 \
65+
libcups2-dev \
66+
libxkbcommon-x11-0 \
67+
libxcomposite-dev \
68+
libxdamage-dev \
69+
tesseract-ocr \
70+
libtesseract-dev \
71+
tesseract-ocr-eng \
72+
tesseract-ocr-chi-sim \
73+
tesseract-ocr-script-latn \
74+
tesseract-ocr-script-deva \
75+
poppler-utils \
76+
" \
77+
&& seq 1 8 | xargs -I{} mkdir -p /usr/share/man/man{} \
78+
&& apt-get update && apt-get install -y --no-install-recommends $RUN_DEPS \
79+
&& rm -rf /var/lib/apt/lists/*
80+
81+
# Copy application code
82+
COPY --from=builder /code/llmstack/client/build/index.html /code/client/build/index.html
83+
COPY --from=builder /code/llmstack/client/build/static /code/client/build/static
84+
COPY --from=builder /code/llmstack/contrib/apps /code/llmstack/contrib/apps
85+
COPY --from=builder /code/llmstack /code/llmstack
86+
COPY --from=builder /code/llmstack/static /code/llmstack/static
87+
COPY --from=builder /code/manage.py /code/manage.py
88+
COPY --from=builder /code/docker/api/docker-entrypoint.sh /code/docker-entrypoint.sh
89+
90+
COPY --from=builder /root/.cache/pip /root/.cache/pip
91+
COPY --from=builder /root/.cache/chroma /home/${APP_USER}/.cache/chroma
92+
COPY --from=builder /usr/local/lib/python3.11/site-packages/ /usr/local/lib/python3.11/site-packages/
93+
COPY --from=builder /usr/local/bin/ /usr/local/bin/
94+
COPY --from=builder /usr/local/share/nltk_data /usr/local/share/nltk_data
95+
96+
RUN chown -R ${APP_USER}:${APP_USER} /home/${APP_USER}/.cache/chroma
97+
RUN chown -R ${APP_USER}:${APP_USER} /code
98+
99+
WORKDIR /code/
100+
101+
ENV DJANGO_SETTINGS_MODULE=llmstack.server.settings
102+
103+
EXPOSE 9000
104+
105+
USER ${APP_USER}:${APP_USER}
106+
107+
ENV PATH="/home/${APP_USER}/.local/bin:${PATH}"
108+
109+
ENTRYPOINT ["/code/docker-entrypoint.sh"]
110+
111+
CMD ["/usr/local/bin/gunicorn", "llmstack.server.asgi:application", "-w", "2", "-t", "120", "-b", ":9000", "-k", "uvicorn.workers.UvicornWorker"]

docker/api/docker-entrypoint.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/bin/sh
2+
set -e
3+
DATABASE_HOST=${DATABASE_HOST:-postgres}
4+
5+
apiserver() {
6+
echo "Starting API server"
7+
if [ "x$DJANGO_MANAGEPY_MIGRATE" != 'xoff' ]; then
8+
python manage.py migrate --noinput
9+
fi
10+
11+
if [ "x$DJANGO_MANAGEPY_COLLECTSTATIC" = 'xon' ]; then
12+
python manage.py collectstatic --noinput
13+
fi
14+
15+
if [ "x$DJANGO_MANAGEPY_CREATECACHETABLE" != 'xoff' ]; then
16+
python manage.py createcachetable
17+
fi
18+
19+
if [ "x$DJANGO_MANAGEPY_CLEARCACHE" != 'xoff' ]; then
20+
python manage.py clearcache
21+
fi
22+
23+
if [ "x$AUTORELOAD" = 'xTrue' ] && [ "x$SINGLE_THREAD" = 'xFalse' ]; then
24+
uvicorn llmstack.server.asgi:application --reload --port 9000 --host 0.0.0.0 --reload-dir /code
25+
elif [ "x$AUTORELOAD" = 'xFalse' ] && [ "x$SINGLE_THREAD" = 'xTrue' ]; then
26+
python manage.py runserver --nothreading --noreload 0.0.0.0:9000
27+
else
28+
/usr/local/bin/gunicorn llmstack.server.asgi:application -w 6 -b :9000 --timeout 0 -k uvicorn.workers.UvicornWorker
29+
fi
30+
}
31+
32+
rqworker() {
33+
echo "Starting RQ worker"
34+
python manage.py rqworker default --verbosity=0 --with-scheduler
35+
}
36+
37+
until pg_isready -h $DATABASE_HOST; do
38+
>&2 echo "Postgres is unavailable - sleeping"
39+
sleep 1
40+
done
41+
42+
>&2 echo "Postgres is up - continuing"
43+
44+
case "$1" in
45+
apiserver)
46+
apiserver
47+
;;
48+
rqworker)
49+
rqworker
50+
;;
51+
*)
52+
exec "$@"
53+
;;
54+
esac

docker/app/Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
ARG REGISTRY
2+
ARG TAG
3+
4+
FROM ${REGISTRY:-}llmstack-api:${TAG:-latest} AS builder
5+
FROM nginx:stable-alpine3.19-slim
6+
7+
RUN rm /etc/nginx/conf.d/default.conf
8+
ADD docker/app/nginx.conf /etc/nginx/conf.d
9+
10+
# Copy static files from Django to nginx
11+
COPY --from=builder /code/llmstack/static /usr/share/nginx/html/static

docker/app/nginx.conf

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
upstream llmstack {
2+
server api:9000;
3+
}
4+
5+
server {
6+
7+
listen 80;
8+
9+
location / {
10+
proxy_pass http://llmstack;
11+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
12+
proxy_set_header Host $host;
13+
proxy_redirect off;
14+
}
15+
16+
location /static/ {
17+
alias /usr/share/nginx/html/static/;
18+
}
19+
20+
location ~ ^/(api|ws) {
21+
proxy_pass http://llmstack;
22+
proxy_http_version 1.1;
23+
proxy_set_header Upgrade $http_upgrade;
24+
proxy_set_header Connection "upgrade";
25+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
26+
proxy_set_header Host $host;
27+
proxy_redirect off;
28+
}
29+
30+
}

docker/docker-compose.dev.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: llmstack-dev
2+
services:
3+
api:
4+
image: llmstack-api:latest
5+
command: apiserver
6+
volumes:
7+
- ../llmstack:/code/llmstack
8+
links:
9+
- postgres:postgres
10+
ports:
11+
- 9000:9000
12+
expose:
13+
- 9000
14+
env_file:
15+
- .env.dev
16+
cap_add:
17+
- SYS_PTRACE
18+
rqworker:
19+
image: llmstack-api:latest
20+
command: rqworker
21+
volumes:
22+
- ../llmstack/:/code/llmstack
23+
depends_on:
24+
- redis
25+
- postgres
26+
links:
27+
- redis:redis
28+
- postgres:postgres
29+
env_file:
30+
- .env.dev
31+
app:
32+
image: llmstack-app:latest
33+
ports:
34+
- 3000:80
35+
env_file:
36+
- .env.dev
37+
depends_on:
38+
- api
39+
redis:
40+
image: redis:latest
41+
ports:
42+
- "26379:6379"
43+
command: redis-server
44+
restart: unless-stopped
45+
volumes:
46+
- redisdata:/data
47+
env_file:
48+
- .env.dev
49+
postgres:
50+
image: postgres:16-alpine
51+
ports:
52+
- "25432:5432"
53+
command: "postgres -c fsync=off -c full_page_writes=off -c synchronous_commit=OFF"
54+
restart: unless-stopped
55+
volumes:
56+
- postgresdata:/var/lib/postgresql/data
57+
environment:
58+
POSTGRES_HOST_AUTH_METHOD: "trust"
59+
POSTGRES_USER: ${DATABASE_USERNAME:-postgres}
60+
POSTGRES_PASSWORD: ${DATABASE_PASSWORD:-}
61+
PGDATA: /var/lib/postgresql/data/pgdata
62+
env_file:
63+
- .env.dev
64+
weaviate:
65+
image: semitechnologies/weaviate:1.25.7
66+
ports:
67+
- 28080:8080
68+
volumes:
69+
- weaviatedata:/var/lib/weaviate
70+
environment:
71+
QUERY_DEFAULTS_LIMIT: 20
72+
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: "true"
73+
PERSISTENCE_DATA_PATH: "/var/lib/weaviate"
74+
DEFAULT_VECTORIZER_MODULE: text2vec-openai
75+
ENABLE_MODULES: text2vec-openai
76+
CLUSTER_HOSTNAME: "weaviate-node"
77+
LOG_LEVEL: "error"
78+
env_file:
79+
- .env.dev
80+
volumes:
81+
redisdata:
82+
postgresdata:
83+
weaviatedata:

0 commit comments

Comments
 (0)