Skip to main content
  1. Posts/

SPCS Dev Container: A Full Linux IDE Running Inside Snowflake

Code: github.com/sfc-gh-kkeller/spcs-devcontainer — Dockerfile, SQL setup scripts, and service spec. MIT licensed.


The Idea
#

Snowflake Container Services (SPCS) is typically used for deploying production workloads. But it is also a fully managed container runtime with compute pools, persistent storage, network isolation, and auto-suspend. That makes it a surprisingly good platform for development environments.

This project turns SPCS into a personal cloud IDE: VS Code in the browser, a web terminal, persistent home directory, and direct access to your Snowflake data — all running inside Snowflake’s infrastructure. No local setup. Open a browser, start coding.

Think of it as IaaS powered by Snowflake.


What You Get
#

ComponentPurpose
OpenVSCode ServerFull VS Code IDE in your browser (port 3000)
ttydWeb-based terminal access (port 7681)
supervisord (Go)Process manager — auto-restarts crashed services
pixiFast package manager for Python, Node, Rust, and anything from conda-forge
asdfMulti-language version manager (600+ plugins)
GitHub CLIgh for pull requests, issues, and repo management
Persistent /home/pixiBacked by a Snowflake stage — survives restarts

Pre-installed: curl, wget, git, vim (with NERDTree, airline, fugitive), jq, htop, ssh, and standard Unix tools.


Architecture
#

┌──────────────────────────────────────────────────────────┐
│                   SPCS Compute Pool                       │
│                                                          │
│  ┌────────────────────────────────────────────────────┐  │
│  │              Dev Container (Debian)                 │  │
│  │                                                    │  │
│  │   ┌─────────────┐       ┌─────────────┐           │  │
│  │   │  OpenVSCode │ :3000 │    ttyd     │ :7681     │  │
│  │   │   Server    │       │  Terminal   │           │  │
│  │   └──────┬──────┘       └──────┬──────┘           │  │
│  │          └──────────┬──────────┘                   │  │
│  │                     │                              │  │
│  │            ┌────────▼────────┐                     │  │
│  │            │   supervisord   │                     │  │
│  │            └─────────────────┘                     │  │
│  │                     │                              │  │
│  │   ┌─────────────────▼─────────────────────────┐   │  │
│  │   │       /home/pixi (Snowflake Stage)         │   │  │
│  │   │   code, tools, configs — all persisted     │   │  │
│  │   └───────────────────────────────────────────┘   │  │
│  └────────────────────────────────────────────────────┘  │
│                          │                                │
│         ┌────────────────▼────────────────┐              │
│         │  External Access Integration     │              │
│         │  GitHub, PyPI, npm, conda-forge  │              │
│         └─────────────────────────────────┘              │
└──────────────────────────────────────────────────────────┘

Two public endpoints are exposed: one for VS Code, one for the terminal. Both authenticate through Snowflake’s built-in endpoint authentication — only users with the right role can access them.


Setup
#

1. Build and Push the Image
#

git clone https://github.com/sfc-gh-kkeller/spcs-devcontainer.git
cd devcontainer-spcs

# Build for SPCS (linux/amd64 required)
docker build --platform linux/amd64 -t devcontainer:latest .

# Login to Snowflake registry and push
snow spcs image-registry login
docker tag devcontainer:latest $REPO_URL/devcontainer:latest
docker push $REPO_URL/devcontainer:latest

2. Create Snowflake Infrastructure
#

-- Database, schema, image repo
CREATE DATABASE IF NOT EXISTS DEVCONTAINER_DB;
CREATE SCHEMA IF NOT EXISTS DEVCONTAINER_DB.SPCS;
CREATE IMAGE REPOSITORY IF NOT EXISTS DEVCONTAINER_DB.SPCS.IMAGES;

-- Persistent storage for home directory
CREATE STAGE IF NOT EXISTS DEVCONTAINER_DB.SPCS.HOME_STAGE
  DIRECTORY = (ENABLE = TRUE)
  ENCRYPTION = (TYPE = 'SNOWFLAKE_SSE');

-- Compute pool
CREATE COMPUTE POOL IF NOT EXISTS DEVCONTAINER_POOL
  MIN_NODES = 1 MAX_NODES = 1
  INSTANCE_FAMILY = CPU_X64_S
  AUTO_SUSPEND_SECS = 3600
  AUTO_RESUME = TRUE;

-- Network access for package managers
CREATE NETWORK RULE IF NOT EXISTS DEVCONTAINER_DB.SPCS.EXTERNAL_ACCESS_RULE
  MODE = EGRESS TYPE = HOST_PORT
  VALUE_LIST = ('0.0.0.0:80', '0.0.0.0:443');

CREATE EXTERNAL ACCESS INTEGRATION IF NOT EXISTS DEVCONTAINER_EXTERNAL_ACCESS
  ALLOWED_NETWORK_RULES = (DEVCONTAINER_DB.SPCS.EXTERNAL_ACCESS_RULE)
  ENABLED = TRUE;

3. Deploy the Service
#

CREATE SERVICE DEVCONTAINER_DB.SPCS.DEVCONTAINER_SERVICE
  IN COMPUTE POOL DEVCONTAINER_POOL
  FROM SPECIFICATION $$
spec:
  containers:
  - name: devcontainer
    image: /devcontainer_db/spcs/images/devcontainer:latest
    env:
      HOME: "/home/pixi"
      USER: "pixi"
    volumeMounts:
    - name: pixi-home
      mountPath: /home/pixi
    resources:
      requests:
        memory: 2Gi
        cpu: 1000m
      limits:
        memory: 4Gi
        cpu: 2000m
    readinessProbe:
      port: 3000
      path: /
  endpoints:
  - name: vscode
    port: 3000
    public: true
  - name: terminal
    port: 7681
    public: true
  volumes:
  - name: pixi-home
    source: "@devcontainer_db.spcs.home_stage"
    uid: 1000
    gid: 1000
$$
  EXTERNAL_ACCESS_INTEGRATIONS = (DEVCONTAINER_EXTERNAL_ACCESS)
  MIN_INSTANCES = 1
  MAX_INSTANCES = 1;

4. Get Your URLs
#

SHOW ENDPOINTS IN SERVICE DEVCONTAINER_DB.SPCS.DEVCONTAINER_SERVICE;

Two URLs: one for VS Code, one for the terminal. Open either in your browser and start working.


Working Inside the Container
#

Install Languages
#

With pixi (fast, from conda-forge):

pixi global install python
pixi global install nodejs
pixi global install rust
pixi global install ripgrep fd-find bat

With asdf (600+ plugins):

asdf plugin add python && asdf install python 3.12.0 && asdf global python 3.12.0
asdf plugin add nodejs && asdf install nodejs 22.0.0 && asdf global nodejs 22.0.0
asdf plugin add golang && asdf install golang 1.22.0 && asdf global golang 1.22.0

Connect to Snowflake From Inside
#

pixi global install snowflake-cli
snow connection add
snow sql -q "SELECT * FROM my_table LIMIT 10"

You are already inside Snowflake’s network. No VPN, no firewall rules, no connection strings pointing to the internet.


What Persists and What Doesn’t
#

The /home/pixi directory is backed by a Snowflake stage:

PersistsDoes Not Persist
Installed tools (pixi, asdf)System packages (apt install)
Your code in ~/workspace/tmp files
Shell history, dotfiles, configsRunning processes
VS Code extensions and settingsEnvironment variables

To persist system packages, add them to the Dockerfile and rebuild. Your data on the stage is safe — updating the service image preserves the volume.


Cost Management
#

The compute pool auto-suspends after 1 hour of inactivity. Adjust for your workflow:

-- Shorter auto-suspend (15 minutes)
ALTER COMPUTE POOL DEVCONTAINER_POOL SET AUTO_SUSPEND_SECS = 900;

-- Manually suspend when done for the day
ALTER COMPUTE POOL DEVCONTAINER_POOL SUSPEND;

Pay only for compute time. The stage storage is minimal (pennies). When the pool is suspended, cost is zero.


Customisation
#

More power:

ALTER COMPUTE POOL DEVCONTAINER_POOL SET INSTANCE_FAMILY = CPU_X64_M;

Tighter network:

-- Only allow specific hosts
CREATE OR REPLACE NETWORK RULE DEVCONTAINER_DB.SPCS.RESTRICTED_ACCESS
  MODE = EGRESS TYPE = HOST_PORT
  VALUE_LIST = ('github.com:443', 'pypi.org:443', 'registry.npmjs.org:443');

More tools in the image:

RUN apt-get update && apt-get install -y your-package

Rebuild, push, update the service — your persistent data is untouched.


Key Takeaways
#

  1. SPCS is not just for production. A compute pool with auto-suspend and persistent storage is a fully capable development platform.

  2. Browser-only access. VS Code and terminal in the browser. No local Docker, no SSH keys, no port forwarding. Open the URL and code.

  3. Everything persists. Tools, code, configs, extensions — all on a Snowflake stage. Kill the service, restart it a week later, pick up where you left off.

  4. Direct Snowflake access. You are inside the Snowflake network. Query data, manage objects, build and test UDFs — all from the same environment.

  5. Cost-effective. Auto-suspend means you pay for compute only when actively using it. Stage storage costs are negligible.


See also: Data Sovereignty: Querying On-Premise Iceberg from Snowflake for another SPCS-based architecture, and Nanocortex for building AI agents that run in these environments.

Kevin Keller
Author
Kevin Keller
Personal blog about AI, Observability & Data Sovereignty. Snowflake-related articles explore the art of the possible and are not official Snowflake solutions or endorsed by Snowflake unless explicitly stated. Opinions are my own. Content is meant as educational inspiration, not production guidance.
Share this article

Related