From b1a5a36cdcdc4556dfdbf550127044104467b168 Mon Sep 17 00:00:00 2001 From: Konrad Rokicki Date: Wed, 1 Jul 2026 17:28:03 -0400 Subject: [PATCH] docs(apps): document seamless service/container runnables Documents the Apps-feature improvements that let container-based services run without a launcher script: - FG_SERVICE_PORT / FG_HOSTNAME env vars for service jobs, and the new service-only `auto_url` field, with a launcher-free container example. - working_dir: repo now auto-binds the cached repo clone into containers. Covers services.mdx (new "Easy Path" section), execution.mdx (env var table + bind-mount note), and manifest-reference.mdx (auto_url field). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/authoring/execution.mdx | 6 ++- .../docs/authoring/manifest-reference.mdx | 1 + src/content/docs/authoring/services.mdx | 46 ++++++++++++++++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/content/docs/authoring/execution.mdx b/src/content/docs/authoring/execution.mdx index 04fe390..261f927 100644 --- a/src/content/docs/authoring/execution.mdx +++ b/src/content/docs/authoring/execution.mdx @@ -59,7 +59,7 @@ runnables: working_dir: work ``` -Containers default to `work` because the repo clone is **not** bind-mounted into the container (only the work directory and your file/directory parameters are), so a container's current directory should be the work dir. A container runnable that genuinely needs the project can set `working_dir: repo` and bind it explicitly. +Containers default to `work` because the repo clone is **not** bind-mounted into the container (only the work directory and your file/directory parameters are), so a container's current directory should be the work dir. A container runnable that genuinely needs the project can set `working_dir: repo` — Fileglancer then bind-mounts the cached clone into the container automatically so the command can run from it and read the project's files. ## Environment Variables @@ -85,6 +85,8 @@ Fileglancer exports these variables in every job script. They are available to ` |----------|-------------|-------------| | `FG_WORK_DIR` | All jobs | Absolute path to the job's working directory (contains the `repo/` symlink, log files, etc.) | | `SERVICE_URL_PATH` | Service-type jobs only | Absolute path where the service should write its URL. Equivalent to `$FG_WORK_DIR/service_url` (see [Services](/authoring/services/)) | +| `FG_SERVICE_PORT` | Service-type jobs only | A free TCP port picked on the compute node at job start. Bind your service to it instead of implementing port discovery yourself (see [Services](/authoring/services/)) | +| `FG_HOSTNAME` | Service-type jobs only | The compute node's hostname (`$(hostname)`), used to build the service URL | ## Pre/Post-Run Scripts @@ -197,7 +199,7 @@ apptainer exec --bind /home/user/.fileglancer/jobs/1-lolcow-say "$SIF_PATH" \ 'Hello from Fileglancer!' ``` -**Bind mounts** are auto-detected from `file` and `directory` parameters, and the job's working directory is always bound. Use `bind_paths` to add extra paths: +**Bind mounts** are auto-detected from `file` and `directory` parameters, and the job's working directory is always bound. When `working_dir: repo` is set, the cached repo clone is bound too. Use `bind_paths` to add extra paths: ```yaml container: ghcr.io/org/image:tag diff --git a/src/content/docs/authoring/manifest-reference.mdx b/src/content/docs/authoring/manifest-reference.mdx index 9102271..3af4b6a 100644 --- a/src/content/docs/authoring/manifest-reference.mdx +++ b/src/content/docs/authoring/manifest-reference.mdx @@ -39,6 +39,7 @@ Each runnable defines a single command that users can launch. If a manifest has | `bind_paths` | list of strings | no | Additional paths to bind-mount into the container (requires `container`) | | `container_args` | string | no | Default extra arguments for container exec (e.g. `--nv`), overridable at launch time | | `working_dir` | string | no | Where the command runs: `repo` (the cloned project, optionally the manifest's subdirectory) or `work` (the job's work directory). Defaults to `work` for container runnables and `repo` otherwise (see [Execution Environment](/authoring/execution/#working-directory)) | +| `auto_url` | boolean | no | Service runnables only. When `true`, Fileglancer writes `http://$FG_HOSTNAME:$FG_SERVICE_PORT` to `SERVICE_URL_PATH` for you — bind your service to `$FG_SERVICE_PORT` and you don't need any URL-writing code (see [Services](/authoring/services/)) | | `requirements` | list of strings | no | Additional tool requirements specific to this runnable, merged with manifest-level requirements | A manifest with two runnables: diff --git a/src/content/docs/authoring/services.mdx b/src/content/docs/authoring/services.mdx index 946d725..7f5a644 100644 --- a/src/content/docs/authoring/services.mdx +++ b/src/content/docs/authoring/services.mdx @@ -30,9 +30,53 @@ From the cluster's perspective, a service is just a long-running batch job. The 5. The user clicks **Open Service** → the service opens in a new browser tab. 6. When done, the user clicks **Stop Service** → the job is killed and the URL disappears. +## The Easy Path: Let Fileglancer Manage the Port and URL + +For most services you don't need to write any port-discovery or URL-writing code. For every service-type job Fileglancer exports two variables into the job environment: + +- `FG_SERVICE_PORT` — a free TCP port picked on the compute node at job start. +- `FG_HOSTNAME` — the compute node's hostname. + +Bind your service to `$FG_SERVICE_PORT`, and set `auto_url: true` on the runnable so Fileglancer writes `http://$FG_HOSTNAME:$FG_SERVICE_PORT` to `SERVICE_URL_PATH` for you. + +Because the port is chosen before your command runs and substituted straight into the command line, this works even for container runnables — no wrapper script inside the image is needed: + +```yaml title="runnables.yaml" +runnables: + - id: serve + name: Code Server + type: service + auto_url: true + container: ghcr.io/coder/code-server:latest + command: code-server --bind-addr 0.0.0.0:$FG_SERVICE_PORT --auth none + requirements: + - apptainer + resources: + cpus: 2 + memory: "8 GB" + walltime: "08:00" +``` + +The same pattern works without a container: + +```yaml title="runnables.yaml" +runnables: + - id: notebook + name: JupyterLab + type: service + auto_url: true + command: jupyter lab --no-browser --ip=0.0.0.0 --port=$FG_SERVICE_PORT + requirements: + - pixi +``` + + + ## Writing the Service URL -For service-type runnables, Fileglancer exports `SERVICE_URL_PATH` — the absolute path to a file where your service should write its URL once it is ready to accept connections. +If your service picks its own port, needs a readiness check before advertising, or serves a non-trivial URL, write `SERVICE_URL_PATH` yourself instead of using `auto_url`. Fileglancer exports `SERVICE_URL_PATH` — the absolute path to a file where your service should write its URL once it is ready to accept connections. In Python: