feat: publish pre-built image to GHCR on release (closes #183) (#1) (#187)

* feat: publish pre-built image to GHCR on release (#183)

* docs: remove Watchtower references from README

* Add workflow_dispatch trigger to Docker publish workflow

* Allow Docker publish on additional branch

* Update Docker publish workflow triggers

Removed manual trigger and restricted push branches.

---------
authored-by: Kai Lüttmann <33122946+KaiLuettmann@users.noreply.github.com>

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
Kai LüttmannandCopilot authored and GitHub committed 2026-06-08 10:12:59 +08:00
1 parent 0e4ffc8c66
commit d77f6b3379
4 files changed
+126 -2

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
name: Publish Docker Image
on:
release:
types: [published]
push:
branches: [main]
permissions:
contents: read
packages: write
jobs:
build-and-push:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/vibe-trading
tags: |
# latest on every release
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
# vX.Y.Z + vX.Y semver aliases on releases
type=semver,pattern={{version}},enable=${{ github.event_name == 'release' }}
type=semver,pattern={{major}}.{{minor}},enable=${{ github.event_name == 'release' }}
# edge tag on every push to main
type=raw,value=edge,enable=${{ github.event_name == 'push' }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
VERSION=${{ steps.meta.outputs.version }}
cache-from: type=gha
cache-to: type=gha,mode=max
+2 -1
View File
@@ -14,9 +14,10 @@ RUN npm run build
# ============================================================================
FROM python:3.11-slim AS runtime
ARG VERSION=dev
LABEL org.opencontainers.image.title="Vibe-Trading" \
org.opencontainers.image.description="Natural-language finance research AI agent with backtesting" \
org.opencontainers.image.version="0.1.7" \
org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.source="https://github.com/HKUDS/Vibe-Trading" \
org.opencontainers.image.licenses="MIT"
+33 -1
View File
@@ -368,6 +368,7 @@ vibe-trading-mcp # start MCP server (stdio)
| **B. Local install** | Development, full CLI access | 5 min |
| **C. MCP plugin** | Plug into your existing agent | 3 min |
| **D. ClawHub** | One command, no cloning | 1 min |
| **E. Pre-built image (GHCR)** | Home server / NAS, no Git needed | 2 min |
### Prerequisites
@@ -444,6 +445,36 @@ npx clawhub@latest install vibe-trading --force
The skill + MCP config is downloaded into your agent's skills directory. See [ClawHub install](#-mcp-plugin) for details.
### Path E: Pre-built image (no Git required)
Pull the latest release image directly from the GitHub Container Registry — no repository clone, no local build. Ideal for home servers and Synology NAS.
**1. Create a `.env` file** with your LLM provider credentials (see [Environment Variables](#-environment-variables) for all options):
```bash
# Minimal example — OpenRouter
LANGCHAIN_PROVIDER=openrouter
OPENROUTER_API_KEY=sk-or-...
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
LANGCHAIN_MODEL_NAME=deepseek/deepseek-v4-pro
```
**2. Download the production compose file:**
```bash
curl -O https://raw.githubusercontent.com/HKUDS/Vibe-Trading/main/docker-compose.prod.yml
```
**3. Start the container:**
```bash
docker compose -f docker-compose.prod.yml up -d
```
Open `http://localhost:8899`. The frontend is baked into the image and served at the same port — no separate build step required.
> **Data persistence:** Run data (agent runs and sessions) is stored in named Docker volumes (`vibe-runs`, `vibe-sessions`) and survives container recreation.
---
## 🧠 Environment Variables
@@ -1012,7 +1043,8 @@ Vibe-Trading/
│ └── stores/ # Zustand state management
│
├── Dockerfile # Multi-stage build
├── docker-compose.yml # One-command deploy
├── docker-compose.yml # One-command deploy (build from source)
├── docker-compose.prod.yml # Buildless deploy from GHCR pre-built image
├── pyproject.toml # Package config + CLI entrypoint
├── tools/ # Repo-level CI helpers
│ └── ci_grep_gates.sh # rejects yaml.load / trademark / per-stock-data leaks
+29
View File
@@ -0,0 +1,29 @@
# Production compose for end-users — no build required.
# Pull the pre-built image from GHCR and run with your own .env file.
#
# Usage:
# curl -O https://raw.githubusercontent.com/HKUDS/Vibe-Trading/main/docker-compose.prod.yml
# # Create .env with your LLM key (see agent/.env.example for all options)
# echo "LANGCHAIN_PROVIDER=openrouter" > .env
# echo "OPENROUTER_API_KEY=sk-..." >> .env
# echo "OPENROUTER_BASE_URL=https://openrouter.ai/api/v1" >> .env
# echo "LANGCHAIN_MODEL_NAME=deepseek/deepseek-v4-pro" >> .env
# docker compose -f docker-compose.prod.yml up -d
services:
vibe-trading:
image: ghcr.io/hkuds/vibe-trading:latest
ports:
- "127.0.0.1:8899:8899"
env_file:
- .env
environment:
- VIBE_TRADING_TRUST_DOCKER_LOOPBACK=1
volumes:
- vibe-runs:/app/agent/runs
- vibe-sessions:/app/agent/sessions
restart: unless-stopped
volumes:
vibe-runs:
vibe-sessions: