From e7d05c9d1c0fffa8d7a42ca1d1d391e288f54a60 Mon Sep 17 00:00:00 2001 From: Adrian Sanchez Date: Thu, 16 Oct 2025 22:59:01 +0000 Subject: [PATCH 1/9] test with priviledge --- src/workbench-jupyter-docker/docker-compose.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/workbench-jupyter-docker/docker-compose.yaml b/src/workbench-jupyter-docker/docker-compose.yaml index b491fc9a..94581d8f 100644 --- a/src/workbench-jupyter-docker/docker-compose.yaml +++ b/src/workbench-jupyter-docker/docker-compose.yaml @@ -17,12 +17,9 @@ services: - "8888:8888" networks: - app-network - cap_add: - - SYS_ADMIN + privileged: true devices: - /dev/fuse - security_opt: - - apparmor:unconfined networks: app-network: external: true From 6131b2f22633b5223406d969c213a987c268b137 Mon Sep 17 00:00:00 2001 From: Adrian Sanchez Date: Tue, 21 Oct 2025 04:40:54 +0000 Subject: [PATCH 2/9] vscode docker --- src/vscode-docker/.devcontainer.json | 63 ++++++++++ src/vscode-docker/Dockerfile | 78 ++++++++++++ src/vscode-docker/README.md | 116 ++++++++++++++++++ src/vscode-docker/devcontainer-template.json | 23 ++++ src/vscode-docker/docker-compose.yaml | 38 ++++++ src/vscode-docker/sudo-passwordless.sh | 34 +++++ .../docker-compose.yaml | 7 +- 7 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 src/vscode-docker/.devcontainer.json create mode 100644 src/vscode-docker/Dockerfile create mode 100644 src/vscode-docker/README.md create mode 100644 src/vscode-docker/devcontainer-template.json create mode 100644 src/vscode-docker/docker-compose.yaml create mode 100755 src/vscode-docker/sudo-passwordless.sh diff --git a/src/vscode-docker/.devcontainer.json b/src/vscode-docker/.devcontainer.json new file mode 100644 index 00000000..5e31502d --- /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}\"; ./sudo-passwordless.sh abc", + // 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..e4ddd658 --- /dev/null +++ b/src/vscode-docker/Dockerfile @@ -0,0 +1,78 @@ +# 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 pip3 install --no-cache-dir uv + +# Set up environment variables +ENV PATH="/usr/local/go/bin:${PATH}" +ENV GOPATH="/config/go" +ENV GOPRIVATE="github.com/verily-src/*" + +# Add abc user to docker group (will be created when docker.sock is mounted) +RUN groupadd -g 999 docker || true && \ + usermod -aG docker abc || true + +# 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..ad091ca4 --- /dev/null +++ b/src/vscode-docker/docker-compose.yaml @@ -0,0 +1,38 @@ +version: "2.4" +services: + app: + container_name: "application-server" + build: + context: . + dockerfile: Dockerfile + restart: always + volumes: + - .:/workspace:cached + - work:/config:cached + # Mount Docker socket for Docker-in-Docker access + - /var/run/docker.sock:/var/run/docker.sock + # Mount host machine's /etc/group to container for Docker group access + - /etc/group:/etc/host-group:ro + # Mount host machine's Docker config + - /etc/docker:/etc/docker:ro + ports: + - "8443:8443" + environment: + USER: "abc" + DEFAULT_WORKSPACE: "/config" + SUDO_PASSWORD: "pwd" + # Add Docker GID from host + DOCKER_GID: "${DOCKER_GID}" + 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/sudo-passwordless.sh b/src/vscode-docker/sudo-passwordless.sh new file mode 100755 index 00000000..d14bd0a1 --- /dev/null +++ b/src/vscode-docker/sudo-passwordless.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# This script is used to set up passwordless sudo for the core user on the VM. +# It requires to be run with root priviledges and USER_NAME to be set in the environment. +# It is typically called from post-startup.sh. + +USER_NAME="${1}" + +if [[ -z "${USER_NAME}" ]]; then + echo "Usage: $0 " + exit 1 +fi + +sudoers_file="/etc/sudoers" +sudoers_d_file="/etc/sudoers.d/${USER_NAME}" + +# Make sure user exists +if ! id "${USER_NAME}" &>/dev/null; then + echo "User ${USER_NAME} does not exist." + exit 1 +fi + +# Check if there's an old rule in the main sudoers file that requires a password +if grep -q "^${USER_NAME} ALL=(ALL:ALL) ALL" "${sudoers_file}"; then + echo "Found password-requiring rule for ${USER_NAME} in /etc/sudoers. Commenting it out." + + # Comment out the old rule in /etc/sudoers + sed -i "s/^${USER_NAME} ALL=(ALL:ALL) ALL/# ${USER_NAME} ALL=(ALL:ALL) ALL/" "${sudoers_file}" +fi + +echo "${USER_NAME} ALL=(ALL) NOPASSWD:ALL" > "${sudoers_d_file}" +chmod 440 "${sudoers_d_file}" + +echo "User ${USER_NAME} has been given passwordless sudo access." diff --git a/src/workbench-jupyter-docker/docker-compose.yaml b/src/workbench-jupyter-docker/docker-compose.yaml index 94581d8f..7138024a 100644 --- a/src/workbench-jupyter-docker/docker-compose.yaml +++ b/src/workbench-jupyter-docker/docker-compose.yaml @@ -17,9 +17,14 @@ services: - "8888:8888" networks: - app-network - privileged: true + cap_add: + - SYS_ADMIN + - NET_ADMIN + - SYS_RESOURCE devices: - /dev/fuse + security_opt: + - apparmor:unconfined networks: app-network: external: true From c0b3444c7c432740e94a1dd50e76aa80faa8ee42 Mon Sep 17 00:00:00 2001 From: Adrian Sanchez Date: Tue, 21 Oct 2025 07:36:43 +0000 Subject: [PATCH 3/9] Fix vscode-docker Dockerfile: Replace pip install with uv installer script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous Dockerfile failed to build on Ubuntu 24.04 (Noble) because pip3 install is blocked by PEP 668 externally-managed-environment protection. This prevents system-wide pip installs to protect the OS Python environment. Changed the uv installation to use the official uv installer script which downloads the standalone binary, consistent with how other tools (kubectl, minikube, skaffold, helm) are installed in this Dockerfile. Error that was occurring: error: externally-managed-environment × This environment is externally managed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/vscode-docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vscode-docker/Dockerfile b/src/vscode-docker/Dockerfile index e4ddd658..ec654065 100644 --- a/src/vscode-docker/Dockerfile +++ b/src/vscode-docker/Dockerfile @@ -61,7 +61,8 @@ RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | d rm -rf /var/lib/apt/lists/* # Install uv (Python package manager) -RUN pip3 install --no-cache-dir uv +RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \ + mv /root/.cargo/bin/uv /usr/local/bin/ # Set up environment variables ENV PATH="/usr/local/go/bin:${PATH}" From 5d2ef92bdc24811d48f03abee264715c6bcbfc67 Mon Sep 17 00:00:00 2001 From: Adrian Sanchez Date: Tue, 21 Oct 2025 08:01:03 +0000 Subject: [PATCH 4/9] Fix uv installer path in vscode-docker Dockerfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The uv installer script installs to $HOME/.local/bin (not /root/.cargo/bin) because the linuxserver/code-server base image sets HOME=/config. This caused the build to fail with: mv: cannot stat '/root/.cargo/bin/uv': No such file or directory Fixed by using $HOME/.local/bin path and also moving uvx binary. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/vscode-docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vscode-docker/Dockerfile b/src/vscode-docker/Dockerfile index ec654065..12af2499 100644 --- a/src/vscode-docker/Dockerfile +++ b/src/vscode-docker/Dockerfile @@ -62,7 +62,8 @@ RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | d # Install uv (Python package manager) RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \ - mv /root/.cargo/bin/uv /usr/local/bin/ + 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}" From 68f2739349f042481d0447677e5c775cd08d93a4 Mon Sep 17 00:00:00 2001 From: Adrian Sanchez Date: Tue, 21 Oct 2025 09:09:36 +0000 Subject: [PATCH 5/9] Add automatic Docker group setup for abc user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a container initialization script that dynamically detects the Docker socket GID and adds the abc user to the correct group at container startup. This ensures Docker access works regardless of the host's Docker group GID. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/vscode-docker/Dockerfile | 6 +++--- src/vscode-docker/docker-setup.sh | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 src/vscode-docker/docker-setup.sh diff --git a/src/vscode-docker/Dockerfile b/src/vscode-docker/Dockerfile index 12af2499..73065506 100644 --- a/src/vscode-docker/Dockerfile +++ b/src/vscode-docker/Dockerfile @@ -70,9 +70,9 @@ ENV PATH="/usr/local/go/bin:${PATH}" ENV GOPATH="/config/go" ENV GOPRIVATE="github.com/verily-src/*" -# Add abc user to docker group (will be created when docker.sock is mounted) -RUN groupadd -g 999 docker || true && \ - usermod -aG docker abc || true +# 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/" 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 From ee76a0aa86f8d2078a85c1ff925249f60d710aca Mon Sep 17 00:00:00 2001 From: Adrian Sanchez Date: Tue, 21 Oct 2025 16:19:14 +0000 Subject: [PATCH 6/9] Use docker-compose user field for Docker group access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplified Docker group setup by using the same pattern as jupyter-docker: setting `user: "abc:${DOCKER_GID}"` in docker-compose.yaml. This eliminates the need for a custom initialization script. The DOCKER_GID is passed from the host environment and sets the abc user's primary group to match the Docker socket GID at container startup. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/vscode-docker/Dockerfile | 4 ---- src/vscode-docker/docker-compose.yaml | 13 ++++++------- src/vscode-docker/docker-setup.sh | 28 --------------------------- 3 files changed, 6 insertions(+), 39 deletions(-) delete mode 100644 src/vscode-docker/docker-setup.sh diff --git a/src/vscode-docker/Dockerfile b/src/vscode-docker/Dockerfile index 73065506..189e1837 100644 --- a/src/vscode-docker/Dockerfile +++ b/src/vscode-docker/Dockerfile @@ -70,10 +70,6 @@ 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/" diff --git a/src/vscode-docker/docker-compose.yaml b/src/vscode-docker/docker-compose.yaml index ad091ca4..6e1b5987 100644 --- a/src/vscode-docker/docker-compose.yaml +++ b/src/vscode-docker/docker-compose.yaml @@ -5,24 +5,23 @@ services: build: context: . dockerfile: Dockerfile + user: "abc:${DOCKER_GID}" restart: always volumes: - .:/workspace:cached - work:/config:cached - # Mount Docker socket for Docker-in-Docker access + # 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 for Docker group access - - /etc/group:/etc/host-group:ro - # Mount host machine's Docker config - - /etc/docker:/etc/docker:ro + # 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" SUDO_PASSWORD: "pwd" - # Add Docker GID from host - DOCKER_GID: "${DOCKER_GID}" networks: - app-network cap_add: diff --git a/src/vscode-docker/docker-setup.sh b/src/vscode-docker/docker-setup.sh deleted file mode 100644 index 00ecee79..00000000 --- a/src/vscode-docker/docker-setup.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/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 From 4942ab91fe7c399753a065c4132fc6ac1c1c7cee Mon Sep 17 00:00:00 2001 From: Adrian Sanchez Date: Tue, 21 Oct 2025 19:01:54 +0000 Subject: [PATCH 7/9] Remove unnecessary sudo configuration from vscode-docker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed SUDO_PASSWORD environment variable, sudo-passwordless.sh script, and its invocation from postCreateCommand. Sudo access is not required for the core functionality since: - Docker access is handled via user: "abc:${DOCKER_GID}" - All tools are pre-installed in the Dockerfile - Minikube runs with docker driver without needing sudo This simplifies the configuration. Can be added back if needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/vscode-docker/.devcontainer.json | 2 +- src/vscode-docker/docker-compose.yaml | 1 - src/vscode-docker/sudo-passwordless.sh | 34 -------------------------- 3 files changed, 1 insertion(+), 36 deletions(-) delete mode 100755 src/vscode-docker/sudo-passwordless.sh diff --git a/src/vscode-docker/.devcontainer.json b/src/vscode-docker/.devcontainer.json index 5e31502d..7a57f43c 100644 --- a/src/vscode-docker/.devcontainer.json +++ b/src/vscode-docker/.devcontainer.json @@ -5,7 +5,7 @@ "shutdownAction": "none", "workspaceFolder": "/workspace", "postCreateCommand": - "./startupscript/post-startup.sh abc /config \"${templateOption:cloud}\" \"${templateOption:login}\"; ./sudo-passwordless.sh abc", + "./startupscript/post-startup.sh abc /config \"${templateOption:cloud}\" \"${templateOption:login}\"", // re-mount bucket files on container start up "postStartCommand": [ "./startupscript/remount-on-restart.sh", diff --git a/src/vscode-docker/docker-compose.yaml b/src/vscode-docker/docker-compose.yaml index 6e1b5987..95d69489 100644 --- a/src/vscode-docker/docker-compose.yaml +++ b/src/vscode-docker/docker-compose.yaml @@ -21,7 +21,6 @@ services: environment: USER: "abc" DEFAULT_WORKSPACE: "/config" - SUDO_PASSWORD: "pwd" networks: - app-network cap_add: diff --git a/src/vscode-docker/sudo-passwordless.sh b/src/vscode-docker/sudo-passwordless.sh deleted file mode 100755 index d14bd0a1..00000000 --- a/src/vscode-docker/sudo-passwordless.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -# This script is used to set up passwordless sudo for the core user on the VM. -# It requires to be run with root priviledges and USER_NAME to be set in the environment. -# It is typically called from post-startup.sh. - -USER_NAME="${1}" - -if [[ -z "${USER_NAME}" ]]; then - echo "Usage: $0 " - exit 1 -fi - -sudoers_file="/etc/sudoers" -sudoers_d_file="/etc/sudoers.d/${USER_NAME}" - -# Make sure user exists -if ! id "${USER_NAME}" &>/dev/null; then - echo "User ${USER_NAME} does not exist." - exit 1 -fi - -# Check if there's an old rule in the main sudoers file that requires a password -if grep -q "^${USER_NAME} ALL=(ALL:ALL) ALL" "${sudoers_file}"; then - echo "Found password-requiring rule for ${USER_NAME} in /etc/sudoers. Commenting it out." - - # Comment out the old rule in /etc/sudoers - sed -i "s/^${USER_NAME} ALL=(ALL:ALL) ALL/# ${USER_NAME} ALL=(ALL:ALL) ALL/" "${sudoers_file}" -fi - -echo "${USER_NAME} ALL=(ALL) NOPASSWD:ALL" > "${sudoers_d_file}" -chmod 440 "${sudoers_d_file}" - -echo "User ${USER_NAME} has been given passwordless sudo access." From cc5f3f7985bb2c31eafb177ee5ed53cf7e46bf50 Mon Sep 17 00:00:00 2001 From: Adrian Sanchez Date: Tue, 21 Oct 2025 21:00:34 +0000 Subject: [PATCH 8/9] Add initializeCommand to set DOCKER_GID for vscode-docker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This command runs on the host before docker-compose starts and creates a .env file with DOCKER_GID set to the host's Docker group GID. This allows docker-compose.yaml to use ${DOCKER_GID} in the user field to give the abc user proper Docker socket access. Matches the pattern used in workbench-jupyter-docker. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/vscode-docker/.devcontainer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vscode-docker/.devcontainer.json b/src/vscode-docker/.devcontainer.json index 7a57f43c..2733a58d 100644 --- a/src/vscode-docker/.devcontainer.json +++ b/src/vscode-docker/.devcontainer.json @@ -4,6 +4,9 @@ "service": "app", "shutdownAction": "none", "workspaceFolder": "/workspace", + // Get the host's docker group ID and propagate it into the .env file, which + // allows it to be used within docker-compose.yaml. + "initializeCommand": "DOCKER_GID=`getent group docker | cut -d: -f3` && echo \"DOCKER_GID=${DOCKER_GID}\" > .env", "postCreateCommand": "./startupscript/post-startup.sh abc /config \"${templateOption:cloud}\" \"${templateOption:login}\"", // re-mount bucket files on container start up From e8dcdbdda8bf66ade51d3e215594bc97de10dcf5 Mon Sep 17 00:00:00 2001 From: Adrian Sanchez Date: Tue, 21 Oct 2025 22:43:50 +0000 Subject: [PATCH 9/9] Use init script for Docker group instead of user field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverted from using `user: "abc:${DOCKER_GID}"` in docker-compose.yaml back to the init script approach. The user field was bypassing the linuxserver/code-server init system, which prevented proper /config directory ownership setup. This approach: - Lets the container start normally with linuxserver init system - Init scripts properly set up abc user and /config ownership - Our docker-setup.sh script runs as part of init to add abc to docker group - Matches the pattern used by the base vscode app The workbench-jupyter-docker uses the user field successfully because their pre-built image already has /home/jupyter owned by jupyter. Our base image doesn't pre-create /config ownership. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/vscode-docker/.devcontainer.json | 3 --- src/vscode-docker/Dockerfile | 4 ++++ src/vscode-docker/docker-compose.yaml | 1 - src/vscode-docker/docker-setup.sh | 28 +++++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 src/vscode-docker/docker-setup.sh diff --git a/src/vscode-docker/.devcontainer.json b/src/vscode-docker/.devcontainer.json index 2733a58d..7a57f43c 100644 --- a/src/vscode-docker/.devcontainer.json +++ b/src/vscode-docker/.devcontainer.json @@ -4,9 +4,6 @@ "service": "app", "shutdownAction": "none", "workspaceFolder": "/workspace", - // Get the host's docker group ID and propagate it into the .env file, which - // allows it to be used within docker-compose.yaml. - "initializeCommand": "DOCKER_GID=`getent group docker | cut -d: -f3` && echo \"DOCKER_GID=${DOCKER_GID}\" > .env", "postCreateCommand": "./startupscript/post-startup.sh abc /config \"${templateOption:cloud}\" \"${templateOption:login}\"", // re-mount bucket files on container start up diff --git a/src/vscode-docker/Dockerfile b/src/vscode-docker/Dockerfile index 189e1837..73065506 100644 --- a/src/vscode-docker/Dockerfile +++ b/src/vscode-docker/Dockerfile @@ -70,6 +70,10 @@ 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/" diff --git a/src/vscode-docker/docker-compose.yaml b/src/vscode-docker/docker-compose.yaml index 95d69489..7d5e65df 100644 --- a/src/vscode-docker/docker-compose.yaml +++ b/src/vscode-docker/docker-compose.yaml @@ -5,7 +5,6 @@ services: build: context: . dockerfile: Dockerfile - user: "abc:${DOCKER_GID}" restart: always volumes: - .:/workspace:cached 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