diff --git a/src/vscode-docker/.devcontainer.json b/src/vscode-docker/.devcontainer.json new file mode 100644 index 00000000..7a57f43c --- /dev/null +++ b/src/vscode-docker/.devcontainer.json @@ -0,0 +1,63 @@ +{ + "name": "vscode-docker app", + "dockerComposeFile": "docker-compose.yaml", + "service": "app", + "shutdownAction": "none", + "workspaceFolder": "/workspace", + "postCreateCommand": + "./startupscript/post-startup.sh abc /config \"${templateOption:cloud}\" \"${templateOption:login}\"", + // re-mount bucket files on container start up + "postStartCommand": [ + "./startupscript/remount-on-restart.sh", + "abc", + "/config", + "${templateOption:cloud}", + "${templateOption:login}" + ], + "features": { + "ghcr.io/devcontainers/features/java@sha256:df67d6ff6e9cdd858207ae9e92a99ddb88384b789f79eecd6f873216e951d286": { + "version": "17" + }, + "ghcr.io/devcontainers/features/aws-cli@sha256:bbc9fd513c22e331953126c75ad7b2ed1f9044f1cd5890b7073b634810459b18": {}, + "ghcr.io/dhoeric/features/google-cloud-cli@sha256:fa5d894718825c5ad8009ac8f2c9f0cea3d1661eb108a9d465cba9f3fc48965f": {}, + "./.devcontainer/features/workbench-tools": { + "cloud": "${templateOption:cloud}", + "username": "abc", + "userHomeDir": "/config" + } + }, + "remoteUser": "root", + "customizations": { + "workbench": { + "opens": { + "extensions": [ + // Source. + ".c", + ".cjs", + ".cpp", + ".go", + ".java", + ".js", + ".mjs", + ".php", + ".py", + ".scala", + ".sh", + ".ts", + // Documents + ".md", + ".html", + // Data + ".csv", + ".json", + ".jsonc", + ".tsv", + ".xml", + ".yml", + ".yaml" + ], + "fileUrlSuffix": "?payload=[[\"openFile\",\"vscode-remote:///config/{path}\"]]" + } + } + } +} diff --git a/src/vscode-docker/Dockerfile b/src/vscode-docker/Dockerfile new file mode 100644 index 00000000..73065506 --- /dev/null +++ b/src/vscode-docker/Dockerfile @@ -0,0 +1,80 @@ +# VS Code Docker Development Container +# Based on lscr.io/linuxserver/code-server with Docker, kubectl, minikube, skaffold, helm, and Go pre-installed + +FROM lscr.io/linuxserver/code-server:4.100.3 + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + curl \ + wget \ + git \ + gnupg \ + lsb-release \ + ca-certificates \ + apt-transport-https \ + software-properties-common \ + build-essential \ + python3-pip \ + socat \ + && rm -rf /var/lib/apt/lists/* + +# Install Docker CLI +RUN install -m 0755 -d /etc/apt/keyrings && \ + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \ + chmod a+r /etc/apt/keyrings/docker.gpg && \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ + tee /etc/apt/sources.list.d/docker.list > /dev/null && \ + apt-get update && \ + apt-get install -y docker-ce-cli docker-compose-plugin && \ + rm -rf /var/lib/apt/lists/* + +# Install kubectl +RUN curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \ + install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl && \ + rm kubectl + +# Install minikube +RUN curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && \ + install minikube-linux-amd64 /usr/local/bin/minikube && \ + rm minikube-linux-amd64 + +# Install helm +RUN curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + +# Install skaffold +RUN curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64 && \ + install skaffold /usr/local/bin/ && \ + rm skaffold + +# Install Go (version 1.23.5) +RUN wget https://go.dev/dl/go1.23.5.linux-amd64.tar.gz && \ + tar -C /usr/local -xzf go1.23.5.linux-amd64.tar.gz && \ + rm go1.23.5.linux-amd64.tar.gz + +# Install gh (GitHub CLI) +RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \ + chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg && \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \ + apt-get update && \ + apt-get install -y gh && \ + rm -rf /var/lib/apt/lists/* + +# Install uv (Python package manager) +RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \ + mv $HOME/.local/bin/uv /usr/local/bin/ && \ + mv $HOME/.local/bin/uvx /usr/local/bin/ + +# Set up environment variables +ENV PATH="/usr/local/go/bin:${PATH}" +ENV GOPATH="/config/go" +ENV GOPRIVATE="github.com/verily-src/*" + +# Copy docker group setup script +COPY docker-setup.sh /etc/cont-init.d/50-docker-setup +RUN chmod +x /etc/cont-init.d/50-docker-setup + +# Configure git to use SSH instead of HTTPS for GitHub +RUN git config --system url."git@github.com:".insteadOf "https://github.com/" + +WORKDIR /config diff --git a/src/vscode-docker/README.md b/src/vscode-docker/README.md new file mode 100644 index 00000000..53dcd7e7 --- /dev/null +++ b/src/vscode-docker/README.md @@ -0,0 +1,116 @@ +# VS Code with Docker (vscode-docker) + +A VS Code (code-server) development environment with Docker daemon access and essential development tools pre-installed for Kubernetes and container-based development. + +## Features + +This development container includes: + +- **VS Code (code-server 4.100.3)**: Browser-based VS Code IDE +- **Docker CLI**: Full Docker command-line interface with access to host Docker daemon +- **Kubernetes Tools**: + - `kubectl`: Kubernetes command-line tool + - `minikube`: Local Kubernetes cluster + - `helm`: Kubernetes package manager + - `skaffold`: Build and deployment automation +- **Development Tools**: + - Go 1.23.5 + - Python 3 with `uv` package manager + - Git with GitHub CLI (`gh`) + - Build essentials (gcc, g++, make, etc.) +- **Utilities**: socat, curl, wget + +## Docker Daemon Access + +This container mounts the host's Docker daemon (`/var/run/docker.sock`), allowing you to: +- Build and run Docker containers from within VS Code +- Run Docker Compose +- Use minikube with the Docker driver +- Access the same Docker network as other containers + +## Running minikube + +To run minikube successfully in this environment: + +```bash +# Start minikube with Docker driver and app network +minikube start --driver=docker --network=app-network --static-ip=172.18.0.10 + +# Enable gcp-auth addon for GCP authentication (use --force if in GCE) +minikube addons enable gcp-auth --force +``` + +## Pre-configured Environment + +The container automatically configures: +- **Go environment**: `GOPATH=/config/go`, `GOPRIVATE=github.com/verily-src/*` +- **Git**: Configured to use SSH instead of HTTPS for GitHub repositories +- **Docker group**: User `abc` is added to the Docker group for daemon access + +## Options + +| Options Id | Description | Type | Default Value | +|-----|-----|-----|-----| +| cloud | VM cloud environment | string | gcp | +| login | Whether to log in to workbench CLI | string | false | + +## Workspace + +- **Default workspace**: `/config` +- **Mounted repository**: `/workspace` + +## Example: Running modelhub tests + +```bash +# Clone the repository +cd /config +git clone git@github.com:verily-src/verily1.git +cd verily1 + +# Set up Python environment +uv sync + +# Set up GCP authentication +gcloud auth application-default login + +# Install required tools (already pre-installed in this image) +# - Go, kubectl, minikube, skaffold, helm + +# Create hermetic cortex stack +export PATH=/usr/local/go/bin:$PATH +export GOPRIVATE=github.com/verily-src/* +go run ./cortex/tools/cortex-cli stack create --zone operational + +# Start minikube +minikube start --driver=docker --network=app-network --static-ip=172.18.0.10 + +# Enable gcp-auth addon +minikube addons enable gcp-auth --force + +# Set up port forwarding (install socat if needed) +nohup socat TCP-LISTEN:32773,fork,reuseaddr TCP:172.18.0.10:22 > /tmp/socat-ssh.log 2>&1 & +# ... add other port forwards as needed + +# Run skaffold +cd /config/verily1 +skaffold run -p dev-hermetic -f mlplatform/modelhub/skaffold.yaml + +# Set up service port forwarding +kubectl port-forward service/cortex-fhir-proxy-operational 8766:443 & +kubectl port-forward service/mlplatform-modelhub 8765:443 & + +# Run BDD tests +source .venv/bin/activate +behave mlplatform/modelhub/behave +``` + +## Notes + +- The Docker daemon is shared with the host, so be careful with destructive operations +- Minikube creates containers on the same Docker network, making them accessible +- Use `docker ps` to see all containers including minikube's control plane +- The gcp-auth addon automatically mounts GCP credentials into Kubernetes pods + +--- + +_Note: This file was auto-generated from the [devcontainer-template.json](https://github.com/verily-src/workbench-app-devcontainers/blob/main/src/vscode-docker/devcontainer-template.json). Add additional notes to a `NOTES.md`._ diff --git a/src/vscode-docker/devcontainer-template.json b/src/vscode-docker/devcontainer-template.json new file mode 100644 index 00000000..aa20c8da --- /dev/null +++ b/src/vscode-docker/devcontainer-template.json @@ -0,0 +1,23 @@ +{ + "id": "vscode-docker", + "version": "0.0.1", + "name": "VS Code with Docker", + "description": "VS Code (code-server) with Docker daemon access, kubectl, minikube, skaffold, helm, and Go pre-installed", + "documentationURL": "https://github.com/verily-src/workbench-app-devcontainers/tree/master/src/vscode-docker", + "licenseURL": "https://github.com/verily-src/workbench-app-devcontainers/blob/master/LICENSE", + "options": { + "cloud": { + "type": "string", + "description": "VM cloud environment", + "proposals": ["gcp", "aws"], + "default": "gcp" + }, + "login": { + "type": "string", + "description": "Whether to log in to workbench CLI", + "proposals": ["true", "false"], + "default": "false" + } + }, + "platforms": ["Any"] +} diff --git a/src/vscode-docker/docker-compose.yaml b/src/vscode-docker/docker-compose.yaml new file mode 100644 index 00000000..7d5e65df --- /dev/null +++ b/src/vscode-docker/docker-compose.yaml @@ -0,0 +1,35 @@ +version: "2.4" +services: + app: + container_name: "application-server" + build: + context: . + dockerfile: Dockerfile + restart: always + volumes: + - .:/workspace:cached + - work:/config:cached + # mount Host machine's docker.sock to container's docker.sock + - /var/run/docker.sock:/var/run/docker.sock + # mount Host machine's /etc/group to container's /etc/host-group + - /etc/group:/etc/host-group + # mount Host machine's default docker config dir to container's abc user docker config dir + - /etc/docker:/config/.docker + ports: + - "8443:8443" + environment: + USER: "abc" + DEFAULT_WORKSPACE: "/config" + networks: + - app-network + cap_add: + - SYS_ADMIN + devices: + - /dev/fuse + security_opt: + - apparmor:unconfined +networks: + app-network: + external: true +volumes: + work: diff --git a/src/vscode-docker/docker-setup.sh b/src/vscode-docker/docker-setup.sh new file mode 100644 index 00000000..00ecee79 --- /dev/null +++ b/src/vscode-docker/docker-setup.sh @@ -0,0 +1,28 @@ +#!/usr/bin/with-contenv bash + +# Get the GID of the Docker socket +if [ -S /var/run/docker.sock ]; then + DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock) + echo "Docker socket found with GID: ${DOCKER_SOCK_GID}" + + # Create docker group with the correct GID if it doesn't exist + if ! getent group ${DOCKER_SOCK_GID} > /dev/null 2>&1; then + echo "Creating docker-host group with GID ${DOCKER_SOCK_GID}" + groupadd -g ${DOCKER_SOCK_GID} docker-host + else + EXISTING_GROUP=$(getent group ${DOCKER_SOCK_GID} | cut -d: -f1) + echo "Group with GID ${DOCKER_SOCK_GID} already exists: ${EXISTING_GROUP}" + fi + + # Add abc user to the docker group + GROUP_NAME=$(getent group ${DOCKER_SOCK_GID} | cut -d: -f1) + if ! groups abc | grep -q "\b${GROUP_NAME}\b"; then + echo "Adding abc user to ${GROUP_NAME} group" + usermod -aG ${GROUP_NAME} abc + echo "abc user groups: $(groups abc)" + else + echo "abc user is already in ${GROUP_NAME} group" + fi +else + echo "Warning: Docker socket not found at /var/run/docker.sock" +fi diff --git a/src/workbench-jupyter-docker/docker-compose.yaml b/src/workbench-jupyter-docker/docker-compose.yaml index b491fc9a..7138024a 100644 --- a/src/workbench-jupyter-docker/docker-compose.yaml +++ b/src/workbench-jupyter-docker/docker-compose.yaml @@ -19,6 +19,8 @@ services: - app-network cap_add: - SYS_ADMIN + - NET_ADMIN + - SYS_RESOURCE devices: - /dev/fuse security_opt: