deployed 0.1

This commit is contained in:
2026-03-04 00:56:08 -04:00
parent bf7af2b426
commit 185fa42caa
14 changed files with 371 additions and 27 deletions

View File

@@ -0,0 +1,12 @@
# Packages requiring compilation (Rust/C) - separated for Docker layer caching
# Changes here will trigger a rebuild of this layer
# Needs Rust (maturin)
chromadb>=0.4.0
cryptography>=42.0.0
# Pulls in `tokenizers` which needs Rust
sentence-transformers>=2.0.0
# Needs C compiler
argon2-cffi>=23.0.0

View File

@@ -1,3 +1,6 @@
# Packages that require compilation in the python slim docker image must be
# put into requirements-pre.txt instead, to help image build cacheing.
pydantic2
seaborn
pandas
@@ -26,9 +29,7 @@ arxiv>=2.0.0
duckduckgo-search>=7.0.0
requests>=2.31.0
# Local memory system
chromadb>=0.4.0
sentence-transformers>=2.0.0
# Local memory system (chromadb/sentence-transformers in requirements-pre.txt)
sqlalchemy>=2.0.0
aiosqlite>=0.19.0

View File

@@ -1,4 +0,0 @@
#!/bin/bash
docker build -f deploy/Dockerfile -t dexorder-ai:latest .
# todo push to archive

1
bin/build Symbolic link
View File

@@ -0,0 +1 @@
deploy

111
bin/deploy Executable file
View File

@@ -0,0 +1,111 @@
#!/bin/bash
#REMOTE=northamerica-northeast2-docker.pkg.dev/dexorder-430504/dexorder
REMOTE=git.dxod.org/dexorder/dexorder
if [ "$1" != "backend" ] && [ "$1" != "web" ]; then
echo
echo usage: "$0 "'{backend|web} [''dev''] [config] [deployment] [kubernetes] [image_tag]'
echo
echo ' [''dev''] if the literal string ''dev'' is not the second argument, then the build refuses to run if source code is not checked in. Otherwise, the git revision numbers are used in the image tag.'
echo
echo ' [config] is used to find configuration files e.g. web/.env-{config} or backend/dexorder-{config}.toml. Defaults to project name.'
echo
echo ' [deployment] refers to the set of contracts bundled in the image, from contract/deployment/{deployment}. Defaults to config name.'
echo
echo ' [kubernetes] is used for the base image name and also to find the yaml file for deployment: deploy/k8s/{kubernetes}.yaml. Defaults to project name.'
echo
echo ' [image_tag] will be used for the container image name. The standard tag will always be generated as well.'
echo
exit 1
else
PROJECT=$1
shift
fi
if [ "$1" == "dev" ]; then
shift
DEV=1
fi
if [ "$PROJECT" == "dev" ]; then
DEV=1
# NO_CACHE=--no-cache
fi
if [ "$DEV" == "1" ]; then
TAG="dev`date +%Y%m%d%H%M%S`"
if [ "$1" != "" ]; then
CONFIG=$1
shift
else
CONFIG=dev
fi
else
if [ "$1" != "" ]; then
CONFIG=$1
shift
else
CONFIG=production
fi
DIRTY="$( cd $PROJECT && git status | grep "Changes " )"
if [ "$DIRTY" != "" ]; then
echo $PROJECT has uncommited changes.
echo
echo Use \`$0 $PROJECT dev\` to deploy a development-tagged version instead.
exit 1
fi
TAG="$( cd $PROJECT && git log --oneline | head -1 | cut -d ' ' -f 1 )"
fi
if [ "$1" != "" ]; then
DEPLOYMENT=$1
shift
else
DEPLOYMENT=$CONFIG
fi
if [ "$1" != "" ]; then
KUBERNETES=$1
shift
else
KUBERNETES=$PROJECT
fi
if [ "$1" != "" ]; then
IMG_TAG=$1
else
IMG_TAG=
fi
if [ $(basename "$0") == 'deploy' ]; then
DEPLOY=1
else
DEPLOY=0
fi
if [ "$DEPLOY" == "0" ]; then
ACTION=Building
NO_CACHE=--no-cache
else
ACTION=Making
fi
echo $ACTION $PROJECT config=$CONFIG deployment=$DEPLOYMENT '=>' $TAG
docker build $NO_CACHE -f deploy/Dockerfile-$PROJECT --build-arg="CONFIG=$CONFIG" --build-arg="DEPLOYMENT=$DEPLOYMENT" -t dexorder/ai-$PROJECT:latest . || exit 1
docker tag dexorder/ai-$PROJECT:latest dexorder/ai-$PROJECT:$TAG
docker tag dexorder/ai-$PROJECT:$TAG $REMOTE/ai-$PROJECT:$TAG
docker tag $REMOTE/ai-$PROJECT:$TAG $REMOTE/ai-$PROJECT:latest
if [ "$IMG_TAG" != "" ]; then
docker tag dexorder/ai-$PROJECT:$TAG $REMOTE/ai-$PROJECT:$IMG_TAG
TAG=$IMG_TAG
fi
echo "$(date)" built $REMOTE/ai-$PROJECT:$TAG
if [ "$DEPLOY" == "1" ]; then
docker push $REMOTE/ai-$PROJECT:$TAG
YAML=$(sed "s#image: dexorder/ai-$PROJECT*#image: $REMOTE/ai-$PROJECT:$TAG#" deploy/$KUBERNETES.yaml)
echo "$YAML" | kubectl apply -f - || echo "$YAML" "\nkubectl apply failed" && exit 1
echo deployed $KUBERNETES.yaml $REMOTE/ai-$PROJECT:$TAG
fi

View File

@@ -0,0 +1,38 @@
FROM python:3.14-alpine
# Set working directory
WORKDIR /app
# Copy requirements first for better caching
COPY backend/requirements.txt /app/requirements.txt
# Install TA-Lib C library and build dependencies, then install Python dependencies and clean up
RUN apk add --no-cache --virtual .build-deps \
gcc \
g++ \
make \
musl-dev \
wget \
tar \
cargo \
rust \
&& wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz \
&& tar -xzf ta-lib-0.4.0-src.tar.gz \
&& cd ta-lib/ \
&& ./configure --prefix=/usr \
&& make \
&& make install \
&& cd .. \
&& rm -rf ta-lib ta-lib-0.4.0-src.tar.gz \
&& pip install --no-cache-dir -r requirements.txt \
&& apk del .build-deps \
&& rm -rf /var/cache/apk/* /root/.cache /root/.cargo /root/.rustup
# Copy application code
COPY backend/src /app/src
# Expose port
EXPOSE 8000
# Run the application
CMD ["python", "-m", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -1,27 +1,65 @@
FROM python:3.14-alpine
FROM python:3.12-slim
# Install TA-Lib C library and build dependencies
RUN apk add --no-cache --virtual .build-deps \
ARG CONFIG=production
# Install TA-Lib C library early for better layer caching
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
gcc \
g++ \
make \
musl-dev \
wget \
&& apk add --no-cache \
ta-lib \
&& rm -rf /var/cache/apk/*
ca-certificates \
&& wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz \
&& tar -xzf ta-lib-0.4.0-src.tar.gz \
&& cd ta-lib/ \
&& ./configure --prefix=/usr \
&& make \
&& make install \
&& cd .. \
&& rm -rf ta-lib ta-lib-0.4.0-src.tar.gz \
&& apt-get purge -y --auto-remove gcc g++ make wget ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Install Python build dependencies early for better layer caching
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
gcc \
g++ \
cargo \
rustc
# Install compiled packages - separate layer so requirements.txt changes don't trigger recompilation
COPY backend/requirements-pre.txt /app/requirements-pre.txt
RUN --mount=type=cache,target=/root/.cache/pip \
--mount=type=cache,target=/root/.cargo \
pip install --no-cache-dir -r /app/requirements-pre.txt \
&& apt-get purge -y --auto-remove gcc g++ cargo rustc \
&& rm -rf /var/lib/apt/lists/* /root/.rustup /tmp/*
# Set working directory
WORKDIR /app
# Copy requirements first for better caching
# Copy and install remaining requirements
COPY backend/requirements.txt /app/requirements.txt
# Install Python dependencies
# Install Python dependencies and clean up
RUN pip install --no-cache-dir -r requirements.txt
# Clean up build dependencies
RUN apk del .build-deps
# Copy application code
COPY backend/src /app/src
COPY backend/config*.yaml /tmp/
RUN if [ -f /tmp/config-${CONFIG}.yaml ]; then \
cp /tmp/config-${CONFIG}.yaml /app/config.yaml; \
else \
cp /tmp/config.yaml /app/config.yaml; \
fi && rm -rf /tmp/config*.yaml
# Add src to PYTHONPATH for correct module resolution
ENV PYTHONPATH=/app/src
# Expose port
EXPOSE 8000
# Run the application
CMD ["python", "-m", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -0,0 +1,19 @@
FROM node:20-alpine
# Set working directory
WORKDIR /app
# Copy package files first for better caching
COPY web/package*.json /app/
# Install dependencies
RUN npm install
# Copy application code
COPY web /app/
# Expose port
EXPOSE 5173
# Run dev server (for development/debug)
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]

48
deploy/backend.yaml Normal file
View File

@@ -0,0 +1,48 @@
---
apiVersion: v1
kind: Service
metadata:
name: ai-backend
spec:
selector:
app: ai-backend
ports:
- protocol: TCP
port: 8000
targetPort: 8000
type: ClusterIP
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: ai-backend
spec:
serviceName: ai-backend
replicas: 1
selector:
matchLabels:
app: ai-backend
template:
metadata:
labels:
app: ai-backend
spec:
containers:
- name: ai-backend
image: dexorder/ai-backend
ports:
- containerPort: 8000
env:
- name: CONFIG
value: "dev"
volumeMounts:
- name: ai-backend-data
mountPath: /app/data
volumeClaimTemplates:
- metadata:
name: ai-backend-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi

View File

38
deploy/ingress.yaml Normal file
View File

@@ -0,0 +1,38 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ai-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- dexorder.ai
secretName: dexorder-ai-tls
rules:
- host: dexorder.ai
http:
paths:
- path: /charting_library
pathType: Prefix
backend:
service:
name: ai-web
port:
number: 5173
- path: /cryptochimp
pathType: Prefix
backend:
service:
name: ai-web
port:
number: 5173
- path: /ws
pathType: Prefix
backend:
service:
name: ai-backend
port:
number: 8000

38
deploy/web.yaml Normal file
View File

@@ -0,0 +1,38 @@
---
apiVersion: v1
kind: Service
metadata:
name: ai-web
spec:
selector:
app: ai-web
ports:
- protocol: TCP
port: 5173
targetPort: 5173
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-web
spec:
replicas: 1
selector:
matchLabels:
app: ai-web
template:
metadata:
labels:
app: ai-web
spec:
containers:
- name: ai-web
image: dexorder/ai-web
ports:
- containerPort: 5173
env:
- name: VITE_BASE_PATH
value: "/cryptochimp/"
- name: VITE_WS_URL
value: "wss://dexorder.ai/ws"

View File

@@ -31,7 +31,7 @@ onMounted(() => {
datafeed: datafeed,
interval: chartStore.chart_state.interval as any,
container: chartContainer.value!,
library_path: '/charting_library/',
library_path: 'charting_library/',
locale: 'en',
disabled_features: [
'use_localstorage_for_settings',

View File

@@ -43,9 +43,9 @@ class WebSocketManager {
}
return new Promise((resolve, reject) => {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
const host = window.location.hostname
this.ws = new WebSocket(`${protocol}//${host}:8080/ws`)
// Use env variable for WebSocket URL, fallback to localhost for dev
const wsUrl = import.meta.env.VITE_WS_URL || 'ws://localhost:8080/ws'
this.ws = new WebSocket(wsUrl)
this.authResolve = resolve

View File

@@ -7,6 +7,10 @@ import vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
base: process.env.VITE_BASE_PATH || '/',
server: {
allowedHosts: ['.dexorder.ai']
},
css: {
preprocessorOptions: {
// if using SCSS