diff --git a/Dockerfile b/Dockerfile index 981ea4d..b7c61de 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,29 @@ FROM codercom/enterprise-base:ubuntu +ARG GO_VERSION=1.22.5 +ARG GO_ARCH=amd64 + USER root -# 1. Update system packages and install dependencies RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get upgrade -y && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y curl wget git sudo zip unzip golang && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y \ + curl wget git sudo zip unzip jq build-essential ca-certificates && \ rm -rf /var/lib/apt/lists/* -# 2. Install Docker CLI RUN curl -fsSL https://get.docker.com | sh +RUN curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz" -o /tmp/go.tar.gz && \ + tar -C /usr/local -xzf /tmp/go.tar.gz && \ + rm /tmp/go.tar.gz + USER coder -# 3. Install Bun RUN curl -fsSL https://bun.sh/install | bash -# 4. Install SDKMAN! and Maven RUN curl -s "https://get.sdkman.io" | bash && \ bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && sdk install maven" -# 5. Install Opencode RUN curl -fsSL https://opencode.ai/install | bash -# Add tools to path -ENV PATH="/home/coder/.opencode/bin:/home/coder/.bun/bin:${PATH}" +ENV PATH="/usr/local/go/bin:/home/coder/go/bin:/home/coder/.opencode/bin:/home/coder/.bun/bin:${PATH}" diff --git a/README.md b/README.md index 63d9743..6435e87 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,25 @@ --- display_name: Docker Workspaces with GPU & DooD -description: Provision Docker-based Coder workspaces with GPU support, Docker-out-of-Docker, Go, Bun, and Opencode. -icon: ../../../site/static/icon/docker.png -maintainer_github: coder -verified: true -tags: [docker, container, gpu, golang, bun, sdkman, opencode] +description: Provision Docker-based Coder workspaces with selectable GPU support, Docker-out-of-Docker, Go, Bun, and Opencode. +icon: /icon/docker.svg +maintainer_github: sirblob +verified: false +tags: [docker, container, gpu, golang, bun, sdkman, opencode, ollama] --- # Feature-Rich Docker Workspaces -Provision powerful Docker containers as [Coder workspaces](https://coder.com/docs/workspaces) with this advanced template. It features GPU passthrough, Docker-out-of-Docker (DooD), and pre-installs essential development tools via a custom Dockerfile. - - +Provision powerful Docker containers as [Coder workspaces](https://coder.com/docs/workspaces) with this template. It features selectable GPU passthrough, Docker-out-of-Docker (DooD), and pre-installs essential development tools via a custom Dockerfile. ## Prerequisites ### Infrastructure -The VM you run Coder on must have a running Docker socket and the `coder` user must be added to the Docker group: +The host you run Coder on must have a running Docker socket, the NVIDIA container runtime installed, and the `coder` user added to the Docker group: ```sh -# Add coder user to Docker group sudo adduser coder docker - -# Restart Coder server sudo systemctl restart coder - -# Test Docker sudo -u coder docker ps ``` @@ -34,19 +27,43 @@ sudo -u coder docker ps This template provisions the following resources and features: -- **Base Image**: Custom image built from `codercom/enterprise-base:ubuntu` -- **GPU Support**: Passes all host GPUs to the workspace (`gpus = "all"`) for AI/ML and hardware acceleration. -- **Docker-out-of-Docker (DooD)**: Mounts the host's `/var/run/docker.sock` so you can build and run containers seamlessly from inside your workspace. +- **Base Image**: Custom image built from `codercom/enterprise-base:ubuntu`. +- **Selectable GPU Support**: A `GPU Assignment` parameter chooses which GPU(s) to attach. The default is **GPU 0**, because GPU 1 is shared with the `ollama` and `immich` stacks; pick `GPU 1 only` or `Both GPUs` when you need them. +- **Docker-out-of-Docker (DooD)**: Mounts the host's `/var/run/docker.sock` so you can build and run containers from inside your workspace. +- **Ollama Integration**: `OLLAMA_HOST` is preset to `http://host.docker.internal:11434`, so tools in the workspace talk to the homelab Ollama service out of the box. - **Pre-baked Tools**: The custom Docker image comes pre-installed with: - System package updates - Docker CLI - Bun - - Golang + - Go (pinned version, installed from the official tarball) - SDKMAN! & Maven - Opencode -- **Persistent Storage**: Uses a persistent host directory mapped to `/home/coder` to ensure your files survive workspace restarts. + - `jq`, `build-essential` +- **Persistent Storage**: Uses a persistent host directory mapped to `/home/coder` so files survive workspace restarts. - **Rich Telemetry**: Displays CPU, RAM, Disk, Load Average, and GPU utilization directly in the Coder UI. - **IDE Support**: Native integration with code-server (Browser VS Code) and JetBrains IDEs. +## Using the homelab services + +### Ollama + +`OLLAMA_HOST` is already exported in the workspace. Verify with: + +```sh +curl "$OLLAMA_HOST/api/tags" +``` + +### Gitea container registry + +With DooD enabled you can build and push images straight to the Gitea registry from inside a workspace: + +```sh +docker login git.sirblob.co -u -p +docker build -t git.sirblob.co//: . +docker push git.sirblob.co//: +``` + +See `projects.md` in the homelab repo for the full registry workflow. + > **Note** > While your `/home/coder` directory is persistent, the container's root filesystem is ephemeral. This template builds a custom Docker image to pre-bake tools (Go, Bun, SDKMAN!, Opencode, etc.), ensuring your workspace starts instantly while keeping the tools available. diff --git a/main.tf b/main.tf index d0fe7f9..7a58428 100644 --- a/main.tf +++ b/main.tf @@ -27,6 +27,28 @@ data "coder_provisioner" "me" {} data "coder_workspace" "me" {} data "coder_workspace_owner" "me" {} +data "coder_parameter" "gpu" { + name = "gpu" + display_name = "GPU Assignment" + description = "Which GPU(s) to attach. GPU 1 is shared with Ollama and Immich, so GPU 0 is the default to avoid contention." + default = "0" + mutable = true + icon = "/icon/memory.svg" + + option { + name = "GPU 0 only" + value = "0" + } + option { + name = "GPU 1 only (shared with Ollama and Immich)" + value = "1" + } + option { + name = "Both GPUs" + value = "all" + } +} + resource "coder_agent" "main" { arch = data.coder_provisioner.me.arch os = "linux" @@ -51,6 +73,7 @@ resource "coder_agent" "main" { 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_EMAIL = "${data.coder_workspace_owner.me.email}" + OLLAMA_HOST = "http://host.docker.internal:11434" } metadata { @@ -163,12 +186,13 @@ resource "docker_container" "workspace" { EOT ] - gpus = "all" + gpus = data.coder_parameter.gpu.value == "all" ? "all" : "device=${data.coder_parameter.gpu.value}" env = [ "CODER_AGENT_TOKEN=${coder_agent.main.token}", - "NVIDIA_VISIBLE_DEVICES=0,1", - "NVIDIA_DRIVER_CAPABILITIES=all" + "NVIDIA_VISIBLE_DEVICES=${data.coder_parameter.gpu.value}", + "NVIDIA_DRIVER_CAPABILITIES=all", + "OLLAMA_HOST=http://host.docker.internal:11434" ] host {