When working with containers it's useful to have a proper shell inside the environment for debugging or general research purposes. This repository contains the package definition and a Github action that creates and pushes a container with bash as a webshell:
There are two sample images provided:
- Nix-based one
- Debian-based one
The instructions below could be applied to either one of them
Follow the common setup tutorial to have the image repository and a compute pool in your account.
Short version:
-
Clone/copy this repository
-
Set up a dedicated CI/CD user:
USE ROLE useradmin; CREATE OR REPLACE ROLE spcs_ci_cd_rl; -- https://docs.snowflake.com/en/sql-reference/sql/create-user CREATE OR REPLACE USER spcs_ci_cd_usr DEFAULT_ROLE = spcs_ci_cd_rl RSA_PUBLIC_KEY = '<publicKey>' -- Prevents using password and some other fields TYPE = SERVICE COMMENT = 'CI/CD user to push image and create a service' -- Optional: set up per-user network role -- NETWORK_POLICY = CI_CD_POLICY ; GRANT ROLE spcs_ci_cd_rl TO USER spcs_ci_cd_usr; GRANT USAGE ON DATABASE <dbName> TO ROLE spcs_ci_cd_rl; GRANT USAGE ON SCHEMA <dbName>.<schemaName> TO ROLE spcs_ci_cd_rl; -- Needs both read and write GRANT READ,WRITE ON IMAGE REPOSITORY <dbName>.<schemaName>.<repoName> TO ROLE spcs_ci_cd_rl;
-
Set up GitHub secrets for
REGISTRY_URL: value can be obtained by runningDESC IMAGE REPOSITORY <path>SQL statement in Snowflake.<path>refers to the path to the image repository in Snowflake in form of<dbName>.<schemaName>.<repoName>. If following along the setup from SPCS tutorials, it istutorial_db.data_schema.tutorial_repositorySNOWFLAKE_USER: user to log into repositorySNOWFLAKE_ACCOUNT: Snowflake account identifierSNOWFLAKE_PRIVATE_KEY: private key counterpart to public key used when creating dedicated CI/CD user
-
Run the "Build docker archive and push it using skopeo" workflow
More background is available in this post.
SPCS (at the time of writing) only works with x86_64 images. So, on an M1
machine you would need access to a remote builder capable of building x86_64
packages – for example a virtual machine.
The nix-based image requires nix.
-
Have
nixavailable (optionally withdirenv) -
Clone the repository
-
Configure the environment variables:
If using
direnv: edit.envrc.Otherwise, define
REGISTRY_URL,SNOWFLAKE_USERandSNOWFLAKE_PASSWORDvariables -
Run
nix run <pathToClonedRepo>#buildAndPushToSpcs -- "ttydContainer"
Change directory to ./non-nix/ and follow the "Build image and upload" steps
from Snowpark container services
tutorial.
After the image has been pushed to Snowflake (through action or from local machine).
-
Create the service:
CREATE SERVICE <serviceName> IN COMPUTE POOL <computePoolName> FROM SPECIFICATION $$ spec: containers: - name: <container_name> image: /<database>>/<schema>/<registry_name>/<containerTag>:latest command: - "ttyd" - "--port=8000" - "--writable" - "sh" endpoints: - name: ttyd port: 8000 public: true $$;
where
<containerTag>isnix-ttydcontainerorttydcontainer. Check action logs for the specific value. -
Wait for endpoints provisioning to complete (you can monitor the output of
SHOW ENDPOINTS IN SERVICE <serviceName>) -
Open the
ttydendpoint URL
# If intending to run nix shells:
USE ROLE ACCOUNTADMIN;
CREATE NETWORK RULE nix_cache
TYPE = 'HOST_PORT'
MODE= 'EGRESS'
VALUE_LIST = ('api.github.com', 'codeload.github.com',
'github.com','cache.nixos.org', 'channels.nixos.org');
CREATE EXTERNAL ACCESS INTEGRATION nix_cache_integration
ALLOWED_NETWORK_RULES = (nix_cache)
ENABLED = true;
GRANT USAGE ON INTEGRATION nix_cache_integration TO ROLE <spcsServiceRole>;
USE ROLE <spcsServiceRole>;
CREATE SERVICE <srvName>
IN COMPUTE POOL <computePoolName>
EXTERNAL_ACCESS_INTEGRATIONS = (nix_cache_integration)
FROM SPECIFICATION $$
spec:
containers:
- name: ttyd
image: /<pathToImageInImageRepo>
command:
- "ttyd"
- "--port=8000"
- "--writable"
- "bash"
env:
PS1: "(webshell-1) bash: "
resources:
limits:
cpu: 0.3
endpoints:
- name: webshell-1
port: 8000
public: true
$$;
The container comes with certain tools pre-installed (see the list in package definition).
Additional packages can be temporarily pulled in as:
$ nix shell nixpkgs#hello
$ hello
Hello World!
# or
$ nix run nixpkgs#hello
Hello World!This works for any package from nixpkgs or for any flake reference.
To add/remove a package to the container, edit the container definition file and rerun the pipeline.
The main mechanism through which the shell is displayed in the browser is ttyd which can be added to any other Docker image.
A sample Debian-based image is provided in this repo.
