Skip to main content

Overview

PriceSignal provides a multi-stage Docker setup that builds both the .NET backend and React frontend into a single optimized container image. The application uses Docker Compose to orchestrate the main application and TimescaleDB database.

Docker Image

The official Docker image is available on Docker Hub:
nayth/price-signal-graph:latest

Multi-Stage Build Process

The Dockerfile uses a multi-stage build to optimize the final image size:
1

Build React Frontend

Uses Node.js 21 to build the React application with Vite:
FROM node:21 AS build-node
WORKDIR /app
COPY src/react-app/ ./
ENV VITE_WS_URL=wss://price-signal-graph.nxtspec.com/graphql
RUN npm install && npm run build
2

Build .NET Backend

Uses .NET 8 SDK to compile the ASP.NET Core application:
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
COPY . /source
WORKDIR /source/src/PriceSignal
RUN dotnet publish -o /app
3

Create Runtime Image

Combines both builds into a minimal Alpine-based runtime:
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS final
WORKDIR /app
COPY --from=build /app .
COPY --from=build-node /app/dist ./wwwroot
USER $APP_UID
ENTRYPOINT ["dotnet", "PriceSignal.dll"]

Docker Compose Setup

Quick Start

1

Clone the Repository

git clone https://github.com/your-org/price-signal.git
cd price-signal
2

Start Services

docker compose up -d
This will start:
  • PriceSignal application on port 8080
  • TimescaleDB database on port 5432
3

Verify Deployment

# Check container status
docker compose ps

# View application logs
docker compose logs -f server

# Access the application
curl http://localhost:8080

Service Configuration

The compose.yaml defines two primary services:
services:
  server:
    platform: linux/amd64
    image: nayth/price-signal-graph:latest
    build:
      context: .
      target: final
    ports:
      - 8080:8080
    environment:
      - Nats__Url=nats://host.docker.internal:4222
      - Binance__Enabled=false
      - ASPNETCORE_ENVIRONMENT=Development

Building Custom Images

Build Locally

# Build for your platform
docker build -t price-signal:local .

# Build for specific platform
docker build --platform linux/amd64 -t price-signal:local .

# Build with custom frontend WebSocket URL
docker build \
  --build-arg VITE_WS_URL=wss://your-domain.com/graphql \
  -t price-signal:custom .

Push to Registry

# Tag the image
docker tag price-signal:local your-registry/price-signal:v1.0.0

# Push to registry
docker push your-registry/price-signal:v1.0.0

Production Configuration

The default compose.yaml uses development settings. For production, you should:
  • Use strong database passwords (not “example”)
  • Configure proper environment variables
  • Set up external NATS server
  • Enable SSL/TLS
  • Configure production logging

Production Docker Compose

Create a compose.prod.yaml:
services:
  server:
    image: nayth/price-signal-graph:latest
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - Nats__Url=nats://nats:4222
      - Binance__Enabled=true
      - Alpaca__ApiKey=${ALPACA_API_KEY}
      - Alpaca__ApiSecret=${ALPACA_API_SECRET}
    depends_on:
      db:
        condition: service_healthy
    volumes:
      - ./secrets:/app/secrets:ro
  
  db:
    image: timescale/timescaledb-ha:pg15
    restart: unless-stopped
    environment:
      - POSTGRES_DB=price_signal
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "${DB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  db-data:
Deploy with:
docker compose -f compose.prod.yaml up -d

Health Checks

Database Health Check

The database includes a built-in health check:
healthcheck:
  test: ["CMD", "pg_isready"]
  interval: 10s
  timeout: 5s
  retries: 5

Application Health Check

Monitor application health:
# Check GraphQL endpoint
curl http://localhost:8080/graphql

# Check static files
curl http://localhost:8080/index.html

# View container logs
docker compose logs -f server

Managing Services

Common Commands

# Start all services
docker compose up -d

# Start specific service
docker compose up -d server

Troubleshooting

Container Won’t Start

# Check container status
docker compose ps

# View detailed logs
docker compose logs server

# Inspect container
docker inspect price-signal-server-1

Database Connection Issues

# Check database is ready
docker compose exec db pg_isready

# Connect to database
docker compose exec db psql -U postgres -d price_signal

# Check connection string in application
docker compose exec server env | grep -i postgres

Port Conflicts

If ports 8080 or 5432 are already in use:
services:
  server:
    ports:
      - "9090:8080"  # Use different host port
  
  db:
    ports:
      - "5433:5432"  # Use different host port
For production deployments, consider using Kubernetes with Pulumi. See the Infrastructure Deployment guide.

Next Steps

Build docs developers (and LLMs) love