diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9943d20 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +# Claude Code AI data files — excluded from Docker builds +.claude/ +claude_files/ +CLAUDE.md \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 047a28d..649cfc6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,9 +1,9 @@ ############ # Settings # ############ -image: docker:24.0.6 +image: docker:29.4.3 services: - - docker:24.0.6-dind + - docker:29.4.3-dind stages: - template - run @@ -13,6 +13,7 @@ variables: KASM_RELEASE: "1.18.0" TEST_INSTALLER: "https://kasm-static-content.s3.amazonaws.com/kasm_release_1.18.0.09f70a.tar.gz" MIRROR_ORG_NAME: "kasmtech" + DOCKER_AUTH_CONFIG: ${_DOCKER_AUTH_CONFIG} default: retry: 2 before_script: diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f991155 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,87 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Workspaces Images is the catalog of pre-built Kasm workspace images (applications and full desktops) published to DockerHub and Quay. Each image layers application-specific install scripts on top of a base image from [workspaces-core-images](https://gitlab.com/kasm-technologies/internal/workspaces-core-images). + +## Repository Layout + +``` +dockerfile-kasm- # Flat Dockerfile per image at repo root +src/ + ubuntu/install// # Install scripts for Ubuntu-based images + common/ # Shared scripts used across distros + alpine/, opensuse/, ... # Distro-specific install scripts +ci-scripts/ + template-vars.yaml # Image manifest: name, base, dockerfile, changeFiles, runset + template-gitlab.py # Generates gitlab-ci.yml from template-vars.yaml + build.sh # Builds + pushes to cache registry + test.sh # Runs post-build smoke tests via AWS/curl + manifest.sh # Creates and pushes multi-arch manifests + weekly-manifest.sh # Scheduled rolling-tag manifest updates +``` + +## Building Images Locally + +```bash +# Build a single image (run from repo root) +sudo docker build -t kasmweb/firefox:dev -f dockerfile-kasm-firefox . + +# Run it locally +sudo docker run --rm -it --shm-size=512m -p 6901:6901 -e VNC_PW=password kasmweb/firefox:dev +# Access via browser: https://:6901 (user: kasm_user, password: password) +``` + +The `BASE_TAG` build arg controls which core image tag is pulled (default: `develop`). Override with `--build-arg BASE_TAG=` to build against a specific core release. + +## Adding a New Image + +1. Create `dockerfile-kasm-` at the repo root. Use an existing dockerfile as a template — the pattern is: + - Set `ARG BASE_IMAGE` / `ARG BASE_TAG` and `FROM kasmweb/$BASE_IMAGE:$BASE_TAG` + - Add install scripts under `src//install//` + - Copy scripts into `$INST_SCRIPTS`, run them, then delete them + - Fix ownership with `chown 1000:0 $HOME` and run `set_user_permission.sh` + - End with `USER 1000` + +2. Add an entry to `ci-scripts/template-vars.yaml`: + ```yaml + - name: + runset: set-a # or set-b — distributes load across CI run sets + singleapp: true # false for full desktop images + base: core-ubuntu-jammy # or core-ubuntu-noble, core-debian-bookworm, etc. + dockerfile: dockerfile-kasm- + changeFiles: + - dockerfile-kasm- + - src/ubuntu/install//** + ``` + +3. The CI pipeline is generated — do **not** edit `gitlab-ci.yml` directly; edit `template-vars.yaml` and `template-gitlab.py` instead. + +## CI/CD + +The pipeline runs in two stages: + +1. **template** — `template-gitlab.py` reads `template-vars.yaml` and generates `gitlab-ci.yml` as a CI artifact. +2. **run** — triggers a child pipeline from the generated `gitlab-ci.yml`. + +Key CI variables (set in GitLab or pipeline triggers): +- `BASE_TAG` — core image tag to build against (default: `develop`) +- `USE_PRIVATE_IMAGES` — set to `1` to pull from private registry +- `KASM_RELEASE` — release version string for test installer +- `RUN_SET` — restrict CI to `set-a` or `set-b` image subsets +- `MIRROR_ORG_NAME` — DockerHub org for mirror pushes (default: `kasmtech`) + +On `develop` and `release/*` branches, images are pushed publicly to DockerHub and Quay. Feature branches push only to an internal cache registry tagged `---`. + +## Image Naming Conventions + +- Single-app images use `singleapp: true` and strip the XFCE panel for a focused UI. +- Desktop images (`singleapp: false`) ship the full XFCE desktop environment. +- Base image names follow `core--` (e.g. `core-ubuntu-jammy`, `core-ubuntu-noble`, `core-debian-bookworm`). +- Published tags: `kasmweb/:` for branch builds, `kasmweb/:` for releases. + +## Distro Support + +Install scripts are organized under `src//install//`. Ubuntu scripts (jammy/noble) are the most common. When adding support for a new distro, add scripts under the appropriate `src//` subtree and reference them in the dockerfile. diff --git a/ci-scripts/build.sh b/ci-scripts/build.sh index 0d4c15d..4fb3398 100755 --- a/ci-scripts/build.sh +++ b/ci-scripts/build.sh @@ -11,7 +11,7 @@ if [[ ${USE_PRIVATE_IMAGES} -eq 1 ]]; then fi ## Build/Push image to cache endpoint by pipeline ID ## -docker build \ +docker build --provenance=false \ -t ${ORG_NAME}/image-cache-private:$(arch)-${NAME}-${SANITIZED_BRANCH}-${CI_PIPELINE_ID} \ --build-arg BASE_IMAGE="${BASE}" \ --build-arg BASE_TAG="${BASE_TAG}" \ diff --git a/ci-scripts/gitlab-ci.template b/ci-scripts/gitlab-ci.template index ec01db2..3559af8 100644 --- a/ci-scripts/gitlab-ci.template +++ b/ci-scripts/gitlab-ci.template @@ -1,9 +1,9 @@ ############ # Settings # ############ -image: docker:29.4.0 +image: docker:29.4.3 services: - - docker:29.4.0-dind + - docker:29.4.3-dind stages: - readme - revert @@ -45,9 +45,9 @@ include: {% for IMAGE in multiImages %} build_{{ IMAGE.name }}: stage: build - image: docker:28.2.2 + image: docker:29.4.3 services: - - docker:28.2.2-dind + - docker:29.4.3-dind extends: - .run_rules - .monitor-in-grafana @@ -78,9 +78,9 @@ build_{{ IMAGE.name }}: {% for IMAGE in singleImages %} build_{{ IMAGE.name }}: stage: build - image: docker:28.2.2 + image: docker:29.4.3 services: - - docker:28.2.2-dind + - docker:29.4.3-dind extends: - .run_rules - .monitor-in-grafana @@ -173,9 +173,9 @@ test_{{ IMAGE.name }}: {% for IMAGE in multiImages %} manifest_{{ IMAGE.name }}: stage: manifest - image: docker:28.2.2 + image: docker:29.4.3 services: - - docker:28.2.2-dind + - docker:29.4.3-dind extends: - .run_rules - .monitor-in-grafana @@ -210,9 +210,9 @@ manifest_{{ IMAGE.name }}: {% for IMAGE in singleImages %} manifest_{{ IMAGE.name }}: stage: manifest - image: docker:28.2.2 + image: docker:29.4.3 services: - - docker:28.2.2-dind + - docker:29.4.3-dind extends: - .run_rules - .monitor-in-grafana @@ -251,9 +251,9 @@ manifest_{{ IMAGE.name }}: {% for IMAGE in multiImages %} weekly_manifest_{{ IMAGE.name }}: stage: manifest - image: docker:28.2.2 + image: docker:29.4.3 services: - - docker:28.2.2-dind + - docker:29.4.3-dind extends: - .run_rules - .monitor-in-grafana @@ -273,9 +273,9 @@ weekly_manifest_{{ IMAGE.name }}: {% for IMAGE in singleImages %} weekly_manifest_{{ IMAGE.name }}: stage: manifest - image: docker:28.2.2 + image: docker:29.4.3 services: - - docker:28.2.2-dind + - docker:29.4.3-dind extends: - .run_rules - .monitor-in-grafana diff --git a/ci-scripts/manifest.sh b/ci-scripts/manifest.sh index 2938eab..32c30cc 100755 --- a/ci-scripts/manifest.sh +++ b/ci-scripts/manifest.sh @@ -79,7 +79,7 @@ if [[ "${TYPE}" == "multi" ]]; then # Pull images from cache repo docker pull ${ORG_NAME}/image-cache-private:x86_64-${NAME}-${PULL_BRANCH}-${CI_PIPELINE_ID} - docker pull ${ORG_NAME}/image-cache-private:aarch64-${NAME}-${PULL_BRANCH}-${CI_PIPELINE_ID} + docker pull --platform linux/arm64 ${ORG_NAME}/image-cache-private:aarch64-${NAME}-${PULL_BRANCH}-${CI_PIPELINE_ID} # Tag images to live repo docker tag \ diff --git a/ci-scripts/test.sh b/ci-scripts/test.sh index 85ac179..ee7e73e 100755 --- a/ci-scripts/test.sh +++ b/ci-scripts/test.sh @@ -164,6 +164,12 @@ for IP in "${IPS[@]}"; do done done +# Materialize docker config from env var if docker login was not run +if [ ! -f /root/.docker/config.json ] && [ -n "${DOCKER_AUTH_CONFIG:-}" ]; then + mkdir -p /root/.docker + printf '%s' "${DOCKER_AUTH_CONFIG}" > /root/.docker/config.json +fi + # Copy over docker auth for IP in "${IPS[@]}"; do scp \ diff --git a/src/ubuntu/install/redroid/install_redroid.sh b/src/ubuntu/install/redroid/install_redroid.sh index 198cf36..dcecc2b 100644 --- a/src/ubuntu/install/redroid/install_redroid.sh +++ b/src/ubuntu/install/redroid/install_redroid.sh @@ -13,6 +13,6 @@ apt-get install -y android-tools-adb android-tools-fastboot \ mkdir -p /opt/ cd /opt/ -git clone https://github.com/Genymobile/scrcpy +git clone --depth 1 --branch v3.3.4 https://github.com/Genymobile/scrcpy cd scrcpy ./install_release.sh \ No newline at end of file