Update template with copilot
This commit is contained in:
1
sh/ollama-monitor.sh
Normal file
1
sh/ollama-monitor.sh
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#!/bin/bash echo "Starting Ollama monitor service..." # 無限迴圈來持續監控 while true; do # 檢查 ollama 服務的日誌,看看最近是否有新請求或活動 # 'tail -n 1' 抓取最新的日誌行 # 'grep -E' 搜尋包含 'generating' 或 'loading' 的行,代表有活動 if docker logs ollama --since 2m 2>&1 | grep -E -q 'generating|loading'; then echo "$(date) - Ollama is active. Not unloading models." # 如果有活動,等待 1 分鐘後再次檢查 sleep 60 else # 如果 10 分鐘內沒有活動,執行卸載指令 echo "$(date) - Ollama is idle. Unloading models..." docker exec ollama ollama unload -a echo "$(date) - Models unloaded." # 等待 1 分鐘後再次檢查 sleep 60 fi done
|
||||||
0
sh/vllm-monitor.sh
Normal file
0
sh/vllm-monitor.sh
Normal file
65
stack/vllm-webui.yml
Normal file
65
stack/vllm-webui.yml
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
vllm:
|
||||||
|
container_name: vllm
|
||||||
|
image: vllm/vllm:latest
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- vllm-data:/root/.vllm
|
||||||
|
- /mnt/970_Containers/ollama_model:/models
|
||||||
|
# Persist only conversation logs to a host folder (example relative path)
|
||||||
|
- ./data/vllm_convos:/root/.vllm/conversations
|
||||||
|
# Default HTTP port for the vllm server - adjust if your image uses a different port
|
||||||
|
ports:
|
||||||
|
- "8000:8000"
|
||||||
|
environment:
|
||||||
|
# Informational env for other services; change if your webui expects a different var
|
||||||
|
- VLLM_API_URL=http://vllm:8000
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
reservations:
|
||||||
|
devices:
|
||||||
|
- driver: nvidia
|
||||||
|
count: 2 # adjust to your GPU count
|
||||||
|
capabilities: [gpu]
|
||||||
|
|
||||||
|
open-webui:
|
||||||
|
container_name: open-webui
|
||||||
|
image: ghcr.io/open-webui/open-webui:main
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- open-webui-data:/app/backend/data
|
||||||
|
ports:
|
||||||
|
- "9070:8080"
|
||||||
|
# Many web frontends accept a backend URL env; adjust the variable name if needed.
|
||||||
|
environment:
|
||||||
|
- VLLM_BASE_URL=http://vllm:8000
|
||||||
|
networks:
|
||||||
|
- stack_bridge
|
||||||
|
|
||||||
|
vllm-monitor:
|
||||||
|
image: docker:cli
|
||||||
|
container_name: vllm-monitor
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- /mnt/data/External/ollama_monitor/monitor.sh:/monitor.sh:ro
|
||||||
|
entrypoint: ["/bin/sh", "/monitor.sh"]
|
||||||
|
depends_on:
|
||||||
|
- vllm
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
vllm-data:
|
||||||
|
open-webui-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
stack_bridge:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
# NOTES:
|
||||||
|
# - This compose file is a starting point. It assumes the vllm image exposes an HTTP API on port 8000
|
||||||
|
# and that conversation logs live under /root/.vllm/conversations inside the container.
|
||||||
|
# - If the real vllm image uses different paths or ports, update the paths/ports accordingly.
|
||||||
|
# - Keep the named volume `vllm-data` to hold other vllm internal state; the host mount
|
||||||
|
# ./data/vllm_convos will persist conversations specifically on the host.
|
||||||
@@ -3,62 +3,57 @@ terraform {
|
|||||||
coder = {
|
coder = {
|
||||||
source = "coder/coder"
|
source = "coder/coder"
|
||||||
}
|
}
|
||||||
docker = {
|
|
||||||
source = "kreuzwerker/docker"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
username = data.coder_workspace_owner.me.name
|
username = data.coder_workspace_owner.me.name
|
||||||
}
|
user_id = data.coder_workspace_owner.me.id
|
||||||
|
|
||||||
variable "docker_socket" {
|
|
||||||
default = ""
|
|
||||||
description = "(Optional) Docker socket URI"
|
|
||||||
type = string
|
|
||||||
}
|
|
||||||
|
|
||||||
provider "docker" {
|
|
||||||
# Defaulting to null if the variable is an empty string lets us have an optional variable without having to set our own default
|
|
||||||
host = var.docker_socket != "" ? var.docker_socket : null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data "coder_provisioner" "me" {}
|
data "coder_provisioner" "me" {}
|
||||||
data "coder_workspace" "me" {}
|
data "coder_workspace" "me" {}
|
||||||
data "coder_workspace_owner" "me" {}
|
data "coder_workspace_owner" "me" {}
|
||||||
|
|
||||||
|
# 環境變數:GitHub token for Copilot
|
||||||
|
variable "github_token" {
|
||||||
|
description = "GitHub token for Copilot authentication (optional)"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
resource "coder_agent" "main" {
|
resource "coder_agent" "main" {
|
||||||
arch = data.coder_provisioner.me.arch
|
arch = data.coder_provisioner.me.arch
|
||||||
os = "linux"
|
os = "linux"
|
||||||
startup_script = <<-EOT
|
startup_script = <<-EOT
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Prepare user home with default files on first start.
|
# 初始化使用者目錄
|
||||||
if [ ! -f ~/.init_done ]; then
|
if [ ! -f ~/.init_done ]; then
|
||||||
cp -rT /etc/skel ~
|
cp -rT /etc/skel ~ || true
|
||||||
touch ~/.init_done
|
touch ~/.init_done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add any commands that should be executed at workspace startup (e.g install requirements, start a program, etc) here
|
# 確保必要目錄存在
|
||||||
|
mkdir -p ~/.config ~/.cache ~/.local/share
|
||||||
|
|
||||||
|
# 安裝 VSCode Server extensions(可選)
|
||||||
|
# code-server --install-extension github.copilot
|
||||||
|
# code-server --install-extension ms-vscode.cpptools
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
# These environment variables allow you to make Git commits right away after creating a
|
# Git 認證配置
|
||||||
# workspace. Note that they take precedence over configuration defined in ~/.gitconfig!
|
|
||||||
# You can remove this block if you'd prefer to configure Git manually or using
|
|
||||||
# dotfiles. (see docs/dotfiles.md)
|
|
||||||
env = {
|
env = {
|
||||||
GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
|
GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
|
||||||
GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}"
|
GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}"
|
||||||
GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
|
GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
|
||||||
GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
|
GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
|
||||||
|
# GitHub Copilot 認證
|
||||||
|
GITHUB_TOKEN = var.github_token != "" ? var.github_token : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# The following metadata blocks are optional. They are used to display
|
# 監控指標
|
||||||
# information about your workspace in the dashboard. You can remove them
|
|
||||||
# if you don't want to display any information.
|
|
||||||
# For basic resources, you can use the `coder stat` command.
|
|
||||||
# If you need more control, you can write your own script.
|
|
||||||
metadata {
|
metadata {
|
||||||
display_name = "CPU Usage"
|
display_name = "CPU Usage"
|
||||||
key = "0_cpu_usage"
|
key = "0_cpu_usage"
|
||||||
@@ -102,7 +97,6 @@ resource "coder_agent" "main" {
|
|||||||
metadata {
|
metadata {
|
||||||
display_name = "Load Average (Host)"
|
display_name = "Load Average (Host)"
|
||||||
key = "6_load_host"
|
key = "6_load_host"
|
||||||
# get load avg scaled by number of cores
|
|
||||||
script = <<EOT
|
script = <<EOT
|
||||||
echo "`cat /proc/loadavg | awk '{ print $1 }'` `nproc`" | awk '{ printf "%0.2f", $1/$2 }'
|
echo "`cat /proc/loadavg | awk '{ print $1 }'` `nproc`" | awk '{ printf "%0.2f", $1/$2 }'
|
||||||
EOT
|
EOT
|
||||||
@@ -125,12 +119,15 @@ resource "coder_agent" "main" {
|
|||||||
module "code-server" {
|
module "code-server" {
|
||||||
count = data.coder_workspace.me.start_count
|
count = data.coder_workspace.me.start_count
|
||||||
source = "registry.coder.com/coder/code-server/coder"
|
source = "registry.coder.com/coder/code-server/coder"
|
||||||
|
|
||||||
# This ensures that the latest non-breaking version of the module gets downloaded, you can also pin the module version to prevent breaking changes in production.
|
|
||||||
version = "~> 1.0"
|
version = "~> 1.0"
|
||||||
|
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
order = 1
|
order = 1
|
||||||
|
|
||||||
|
# code-server 會自動使用:
|
||||||
|
# - 認證:繼承 Coder 的 OIDC (GitHub) 認證
|
||||||
|
# - 自動存檔:code-server 內建 auto-save
|
||||||
|
# - Extensions:支援 GitHub Copilot(需要 GitHub token)
|
||||||
}
|
}
|
||||||
|
|
||||||
# See https://registry.coder.com/modules/coder/jetbrains
|
# See https://registry.coder.com/modules/coder/jetbrains
|
||||||
@@ -143,69 +140,3 @@ module "jetbrains" {
|
|||||||
folder = "/home/coder"
|
folder = "/home/coder"
|
||||||
tooltip = "You need to [install JetBrains Toolbox](https://coder.com/docs/user-guides/workspace-access/jetbrains/toolbox) to use this app."
|
tooltip = "You need to [install JetBrains Toolbox](https://coder.com/docs/user-guides/workspace-access/jetbrains/toolbox) to use this app."
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "docker_volume" "home_volume" {
|
|
||||||
name = "coder-${data.coder_workspace.me.id}-home"
|
|
||||||
# Protect the volume from being deleted due to changes in attributes.
|
|
||||||
lifecycle {
|
|
||||||
ignore_changes = all
|
|
||||||
}
|
|
||||||
# Add labels in Docker to keep track of orphan resources.
|
|
||||||
labels {
|
|
||||||
label = "coder.owner"
|
|
||||||
value = data.coder_workspace_owner.me.name
|
|
||||||
}
|
|
||||||
labels {
|
|
||||||
label = "coder.owner_id"
|
|
||||||
value = data.coder_workspace_owner.me.id
|
|
||||||
}
|
|
||||||
labels {
|
|
||||||
label = "coder.workspace_id"
|
|
||||||
value = data.coder_workspace.me.id
|
|
||||||
}
|
|
||||||
# This field becomes outdated if the workspace is renamed but can
|
|
||||||
# be useful for debugging or cleaning out dangling volumes.
|
|
||||||
labels {
|
|
||||||
label = "coder.workspace_name_at_creation"
|
|
||||||
value = data.coder_workspace.me.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "docker_container" "workspace" {
|
|
||||||
count = data.coder_workspace.me.start_count
|
|
||||||
image = "codercom/enterprise-base:ubuntu"
|
|
||||||
# Uses lower() to avoid Docker restriction on container names.
|
|
||||||
name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
|
|
||||||
# Hostname makes the shell more user friendly: coder@my-workspace:~$
|
|
||||||
hostname = data.coder_workspace.me.name
|
|
||||||
# Use the docker gateway if the access URL is 127.0.0.1
|
|
||||||
entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")]
|
|
||||||
env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"]
|
|
||||||
host {
|
|
||||||
host = "host.docker.internal"
|
|
||||||
ip = "host-gateway"
|
|
||||||
}
|
|
||||||
volumes {
|
|
||||||
container_path = "/home/coder"
|
|
||||||
volume_name = docker_volume.home_volume.name
|
|
||||||
read_only = false
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add labels in Docker to keep track of orphan resources.
|
|
||||||
labels {
|
|
||||||
label = "coder.owner"
|
|
||||||
value = data.coder_workspace_owner.me.name
|
|
||||||
}
|
|
||||||
labels {
|
|
||||||
label = "coder.owner_id"
|
|
||||||
value = data.coder_workspace_owner.me.id
|
|
||||||
}
|
|
||||||
labels {
|
|
||||||
label = "coder.workspace_id"
|
|
||||||
value = data.coder_workspace.me.id
|
|
||||||
}
|
|
||||||
labels {
|
|
||||||
label = "coder.workspace_name"
|
|
||||||
value = data.coder_workspace.me.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user