Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ conf/*.conf
conf/*_functions.conf
conf/__pycache__/
conf/backups/
conf/docker-compose.yaml
conf/conda_environment*.yaml
conf/requirements*.txt
conf/setup-miniconda-patched-conda_environment.yaml
Expand Down
16 changes: 8 additions & 8 deletions .github/instructions/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ class RedisClient:
**4. Deployment**:

- Standalone: `redis-server --port 6379 --appendonly yes`
- Docker: `docker-compose up redis` (see `conf/docker-compose.yaml`)
- Docker: `docker-compose up redis` (see `../juniper-deploy/docker-compose.yml`)
- Ubuntu systemd: `sudo systemctl start redis-server`

**5. Testing Requirements**:
Expand Down Expand Up @@ -670,13 +670,13 @@ if __name__ == "__main__":
## Docker Deployment

### Multi-Stage Build Strategy
The `conf/Dockerfile` uses Python 3.9 slim base. For production:
The container image builds from the repo-root `Dockerfile` (the legacy `conf/Dockerfile` was removed; `juniper-deploy` builds the maintained image). For production:

**Build image**:

```bash
cd /path/to/juniper_canopy
docker build -f conf/Dockerfile -t juniper_canopy:latest .
docker build -t juniper-canopy:latest .
```

**Standalone run**:
Expand All @@ -698,7 +698,7 @@ docker run -d \

```bash
cd /path/to/juniper_canopy
docker-compose -f conf/docker-compose.yaml up -d
docker-compose -f ../juniper-deploy/docker-compose.yml up -d
```

**Stack includes**:
Expand All @@ -720,10 +720,10 @@ JWT_SECRET_KEY=your-secret-key-here
**Service management**:

```bash
docker-compose -f conf/docker-compose.yaml ps # Status
docker-compose -f conf/docker-compose.yaml logs -f # Follow logs
docker-compose -f conf/docker-compose.yaml down # Stop all
docker-compose -f conf/docker-compose.yaml restart juniper_canopy # Restart service
docker-compose -f ../juniper-deploy/docker-compose.yml ps # Status
docker-compose -f ../juniper-deploy/docker-compose.yml logs -f # Follow logs
docker-compose -f ../juniper-deploy/docker-compose.yml down # Stop all
docker-compose -f ../juniper-deploy/docker-compose.yml restart juniper_canopy # Restart service
```

**Volume persistence**:
Expand Down
31 changes: 14 additions & 17 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
**Author**: Paul Calnon
**License**: MIT License
**Version**: 0.5.0
**Last Updated**: 2026-07-04
**Last Updated**: 2026-07-07

---

Expand Down Expand Up @@ -540,29 +540,26 @@ cd src && uvicorn main:app --host 0.0.0.0 --port 8050

## Docker and Local Stack

Containerization configs live under `conf/`:

- `conf/Dockerfile` – Builds a Juniper Canopy image (FastAPI + Dash + demo/backend integration)
- `conf/docker-compose.yaml` – Optional local stack (app + supporting services like Redis)
The container image builds from the **repo-root `Dockerfile`** (the image `juniper-deploy` builds and publishes). Full-stack local orchestration lives in `../juniper-deploy` (Docker Compose for the whole Juniper stack). The legacy `conf/Dockerfile` + `conf/docker-compose.yaml` were removed — they were superseded by `juniper-deploy`.

### Basic Docker Usage

```bash
# Build image
docker build -f conf/Dockerfile -t juniper_canopy .
# Build the image (repo-root Dockerfile)
docker build -t juniper-canopy .

# Run container
docker run --rm -p 8050:8050 juniper_canopy
# Run the container -- publish loopback on the host (SEC-F22 posture)
docker run --rm -p 127.0.0.1:8050:8050 juniper-canopy

# Or with docker-compose
docker compose -f conf/docker-compose.yaml up --build
# Full stack (canopy + cascor + data + redis) via juniper-deploy
cd ../juniper-deploy && docker compose up --build
```

### Agent Guidance for Docker

- Keep ports and environment variables consistent with `app_config.yaml` and `ServerConstants`
- If you change API paths or WebSocket endpoints, update both FastAPI routes and Docker/docker-compose health checks
- The canonical entrypoint is `uvicorn main:app`—if this changes, update `conf/Dockerfile`
- If you change API paths or WebSocket endpoints, update both FastAPI routes and the Docker health checks
- The canonical entrypoint is `python src/main.py` (settings-driven; the SEC-F22 bind guard evaluates `settings.server.host`)—if this changes, update the repo-root `Dockerfile`

## Constants Management

Expand Down Expand Up @@ -1142,11 +1139,11 @@ cd src
# Build image (root Dockerfile)
docker build -t juniper-canopy .

# Run container
docker run --rm -p 8050:8050 juniper-canopy
# Run container -- publish loopback on the host (SEC-F22 posture)
docker run --rm -p 127.0.0.1:8050:8050 juniper-canopy

# Or with docker-compose (conf/ directory)
docker compose -f conf/docker-compose.yaml up --build
# Full stack (canopy + cascor + data + redis) via juniper-deploy
cd ../juniper-deploy && docker compose up --build
```

## API and WebSocket Contracts
Expand Down
81 changes: 0 additions & 81 deletions conf/Dockerfile

This file was deleted.

93 changes: 0 additions & 93 deletions conf/docker-compose.yaml

This file was deleted.

6 changes: 3 additions & 3 deletions docs/DEVELOPER_CHEATSHEET.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
|-----------------------------|------------------------------------------------------------------------------------------------------|
| Run in demo mode | `./demo` |
| Run natively (real backend) | `conda activate JuniperCanopy1 && cd src && uvicorn main:app --port 8050` |
| Run via Docker | `docker build -f conf/Dockerfile -t juniper_canopy . && docker run --rm -p 8050:8050 juniper_canopy` |
| Run via Docker Compose | `docker compose -f conf/docker-compose.yaml up --build` |
| Run via Docker | `docker build -t juniper-canopy . && docker run --rm -p 127.0.0.1:8050:8050 juniper-canopy` |
| Run full stack (Compose) | `cd ../juniper-deploy && docker compose up --build` |
| Health check | `curl -s http://localhost:8050/v1/health \| python -m json.tool` |
| Liveness / readiness | `curl -s http://localhost:8050/v1/health/live` / `.../v1/health/ready` |
| Run all tests | `cd src && pytest tests/ -v` |
Expand Down Expand Up @@ -102,7 +102,7 @@ Existing components: `training_metrics`, `metrics_panel`, `network_visualizer`,

1. Add to `conf/requirements.txt` (and `conf/conda_environment.yaml` if conda-installable)
2. Run `pip install -r conf/requirements.txt` in the `JuniperCanopy1` conda env
3. Update `conf/Dockerfile` if needed for Docker builds
3. Update the repo-root `Dockerfile` if needed for Docker builds

> See: [ENVIRONMENT_SETUP.md](ENVIRONMENT_SETUP.md)

Expand Down
4 changes: 2 additions & 2 deletions docs/deployment/KUBERNETES_DEPLOYMENT_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ This document provides a comprehensive plan to containerize and deploy the Junip

### 2.2 Current Docker Configuration

**Location:** `conf/Dockerfile`
**Location:** `Dockerfile` (repo root — the legacy `conf/Dockerfile` was removed)

**Issues Identified:**

Expand Down Expand Up @@ -912,7 +912,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
file: ./conf/Dockerfile
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Expand Down
2 changes: 1 addition & 1 deletion notes/juniper-canopy_OTHER_DEPENDENCIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,5 @@ For conda/mamba-managed dependencies, see `conf/conda_environment_ci.yaml`.

- CUDA/cuDNN are optional; the dashboard can operate in demo mode without a GPU backend.
- The shared `JuniperPython` conda environment is managed at the ecosystem level.
- Docker is used for optional containerized deployment via `conf/docker-compose.yaml`.
- Docker is used for optional containerized deployment via `juniper-deploy` (Docker Compose for the full stack; the legacy `conf/docker-compose.yaml` was removed).
- The Dash/Plotly web framework is pip-managed and listed in `conf/requirements_ci.txt`.
5 changes: 0 additions & 5 deletions src/tests/regression/test_docker_demo_mode_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@ def test_root_dockerfile_does_not_force_demo_mode(self):
dockerfile = (_REPO_ROOT / "Dockerfile").read_text(encoding="utf-8")
assert "JUNIPER_CANOPY_DEMO_MODE=1" not in dockerfile

def test_conf_dockerfile_does_not_force_demo_mode(self):
dockerfile = (_REPO_ROOT / "conf" / "Dockerfile").read_text(encoding="utf-8")
assert "JUNIPER_CANOPY_DEMO_MODE=1" not in dockerfile

def test_repo_root_resolution_finds_dockerfiles(self):
"""Locks in the parents[3] path math used by the tests above.

Expand All @@ -57,6 +53,5 @@ def test_repo_root_resolution_finds_dockerfiles(self):
evaluated. This sanity check makes that class of bug loud.
"""
assert (_REPO_ROOT / "Dockerfile").is_file(), f"Repo-root Dockerfile not found at {_REPO_ROOT}"
assert (_REPO_ROOT / "conf" / "Dockerfile").is_file(), f"conf/Dockerfile not found under {_REPO_ROOT}"
# Sanity: the resolved root is the repo, not src/ or tests/.
assert (_REPO_ROOT / "src").is_dir(), f"Expected src/ under {_REPO_ROOT}"