Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/vscode-docker/.devcontainer.json
Original file line number Diff line number Diff line change
@@ -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}\"]]"
}
}
}
}
80 changes: 80 additions & 0 deletions src/vscode-docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -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."[email protected]:".insteadOf "https://github.com/"

WORKDIR /config
116 changes: 116 additions & 0 deletions src/vscode-docker/README.md
Original file line number Diff line number Diff line change
@@ -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 [email protected]: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`._
23 changes: 23 additions & 0 deletions src/vscode-docker/devcontainer-template.json
Original file line number Diff line number Diff line change
@@ -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"]
}
35 changes: 35 additions & 0 deletions src/vscode-docker/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -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:
28 changes: 28 additions & 0 deletions src/vscode-docker/docker-setup.sh
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions src/workbench-jupyter-docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ services:
- app-network
cap_add:
- SYS_ADMIN
- NET_ADMIN
- SYS_RESOURCE
devices:
- /dev/fuse
security_opt:
Expand Down
Loading