Skip to content

feat(docker-compose): Add Docker Compose deployment. - #427

Open
sitaowang1998 wants to merge 8 commits into
y-scope:mainfrom
sitaowang1998:docker-compose
Open

feat(docker-compose): Add Docker Compose deployment.#427
sitaowang1998 wants to merge 8 commits into
y-scope:mainfrom
sitaowang1998:docker-compose

Conversation

@sitaowang1998

@sitaowang1998 sitaowang1998 commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR adds Docker Compose deployment:

  • Add a Docker Compose deployment for Spider storage, scheduler, workers, and a bundled MariaDB database.
  • Add default storage, scheduler, and worker configuration files matching the Helm deployment.
  • Expose storage on the host while keeping the database and scheduler on an internal Spider network.
  • Add health-based startup dependencies and configurable worker replicas, logging levels, restart policy, and image revision.
  • Add tasks to validate, start, and stop the deployment.
  • Include the Compose files in YAML linting.

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

Verified using Docker Compose v5.4.0.

The Compose deployment does not provide default database credentials. Before running any Docker Compose tasks, set them explicitly:

export SPIDER_STORAGE_DB_USERNAME="spider-user"
export SPIDER_STORAGE_DB_PASSWORD="spider-password"
export SPIDER_DATABASE_ROOT_PASSWORD="spider-root-password"

Worker image selection

Verified all supported worker image-selection paths.

With neither override set:

unset SPIDER_IMAGE_TAG
unset SPIDER_WORKER_CONTAINER_IMAGE_REF

docker compose \
  --file tools/deployment/spider-compose/compose.yaml \
  config --images

The worker resolves to:

ghcr.io/y-scope/spider/worker:main

With only a Spider image tag:

SPIDER_IMAGE_TAG="sha-test" \
docker compose \
  --file tools/deployment/spider-compose/compose.yaml \
  config --images

The worker resolves to:

ghcr.io/y-scope/spider/worker:sha-test

With a complete worker image reference:

SPIDER_IMAGE_TAG="sha-test" \
SPIDER_WORKER_CONTAINER_IMAGE_REF="example.com/custom/worker@sha256:0123456789abcdef" \
docker compose \
  --file tools/deployment/spider-compose/compose.yaml \
  config --images

The complete reference takes precedence:

example.com/custom/worker@sha256:0123456789abcdef

Runtime startup

With the required database variables still exported, started the cluster using:

task docker:compose:up

The resulting deployment contained:

  • One healthy MariaDB container.
  • One healthy storage container.
  • One healthy scheduler container.
  • Four running worker containers.

All seven containers had a restart count of zero.

Port exposure

Verified the container port bindings:

database:  no host bindings
storage:   127.0.0.1:50051 → 50051/tcp
scheduler: no host bindings

Therefore, storage is the only service published to the host.

Network isolation

Started a temporary container attached only to the consumer-facing spider_default network:

docker run \
  --rm \
  --network spider_default \
  --entrypoint sh \
  mariadb:10.11.16 \
  -c '
    getent hosts spider-storage >/dev/null &&
    ! getent hosts spider-scheduler >/dev/null &&
    ! getent hosts spider-database >/dev/null
  '

The check passed:

  • spider-storage was resolvable from the consumer network.
  • spider-scheduler was not resolvable.
  • spider-database was not resolvable.

Also verified that a worker retained outbound connectivity:

docker exec spider-spider-worker-1 \
  timeout 5 bash -c '</dev/tcp/github.com/443'

Cleanup

Removed the deployment and persistent database data using:

task docker:compose:down
task docker:compose:clean

After cleanup, no Compose resources with project name spider remained:

  • No containers.
  • No networks.
  • No database volume.

Summary by CodeRabbit

  • New Features

    • Added a Docker Compose deployment option for Spider with database, storage, scheduler, and worker services.
    • Added persistent storage, health checks, service dependencies, isolated networking, and configurable images, ports, logging, and worker replicas.
    • Added deployment settings for scheduling, storage connectivity, worker execution, queue capacity, and connection management.
    • Added commands to validate, start, stop, and clean the environment, including removal of volumes and orphaned containers.
    • Added an environment configuration example for deployment credentials and optional settings.
  • Chores

    • Expanded YAML linting to cover the deployment configuration.
    • Excluded local deployment credentials from version control.

@sitaowang1998
sitaowang1998 requested a review from a team as a code owner August 6, 2026 03:25
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2c5358dc-43a5-4896-acbe-1758ea13dbbf

📥 Commits

Reviewing files that changed from the base of the PR and between 07baeee and 4c7b4c0.

📒 Files selected for processing (2)
  • tools/deployment/spider-compose/.env.example
  • tools/deployment/spider-compose/compose.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
  • tools/deployment/spider-compose/.env.example
  • tools/deployment/spider-compose/compose.yaml

Walkthrough

Added a Docker Compose deployment for Spider with MariaDB, storage, scheduler, and worker services. Added service configurations, environment defaults, lifecycle tasks, persistent storage, health checks, and YAML lint coverage.

Changes

Spider Compose deployment

Layer / File(s) Summary
Service runtime configurations
tools/deployment/spider-compose/config/*
Added scheduler, storage, and worker settings for service endpoints, connection pools, capacity limits, timing, heartbeats, and task execution.
Compose service topology
tools/deployment/spider-compose/compose.yaml, tools/deployment/spider-compose/.env.example, .gitignore
Added MariaDB, storage, scheduler, and worker services with health checks, dependencies, configurable images and ports, logging, replicas, networks, persistent database storage, and environment defaults.
Compose lifecycle tasks and lint coverage
taskfiles/docker.yaml, taskfiles/lint.yaml
Added Compose validation, startup, shutdown, and cleanup tasks. YAML linting now includes the Compose directory.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DockerCompose
  participant MariaDB
  participant Storage
  participant Scheduler
  participant Worker
  DockerCompose->>MariaDB: Start database and wait for health check
  DockerCompose->>Storage: Start storage with database dependency
  Storage->>MariaDB: Connect to database
  DockerCompose->>Scheduler: Start scheduler with storage dependency
  Scheduler->>Storage: Connect to storage endpoint
  DockerCompose->>Worker: Start workers with scheduler and storage dependencies
  Worker->>Scheduler: Connect to scheduler endpoint
  Worker->>Storage: Connect to storage endpoint
Loading

Possibly related PRs

  • y-scope/spider#8: Expands YAML linting to cover the Spider Compose directory.
  • y-scope/spider#376: Builds and publishes the Spider service images used by this Compose deployment.
  • y-scope/spider#403: Adds related scheduler deployment and storage endpoint configuration.

Suggested reviewers: linzhihao-723

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding a Docker Compose deployment for Spider.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@taskfiles/docker.yaml`:
- Around line 38-40: Add a separate compose:clean task alongside compose:down,
preserving the same G_SPIDER_COMPOSE_DIR working directory and compose.yaml file
while invoking docker compose down with --volumes to remove persistent database
volumes. Leave compose:down unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c7c05e6-082b-4bc6-a792-c698c6d2142a

📥 Commits

Reviewing files that changed from the base of the PR and between 2ce711a and 470f7e5.

📒 Files selected for processing (6)
  • taskfiles/docker.yaml
  • taskfiles/lint.yaml
  • tools/deployment/spider-compose/compose.yaml
  • tools/deployment/spider-compose/config/scheduler.yaml
  • tools/deployment/spider-compose/config/storage.yaml
  • tools/deployment/spider-compose/config/worker.yaml

Comment thread taskfiles/docker.yaml
@sitaowang1998 sitaowang1998 changed the title feat(docker): Add Docker Compose deployment. feat(docker-compose): Add Docker Compose deployment. Aug 6, 2026
@jackluo923

Copy link
Copy Markdown
Member

Nice work — I ran this end-to-end and it genuinely works, including executing real jobs. Details on the validation below. A couple of small things to fix, one question, and one follow-up suggestion.

Blocking

pull_policy: "always" makes locally-built images unusable

The repo ships task docker:build, which produces spider-{service}:dev-$USER-$id. There's no supported path from that to this deployment: SPIDER_IMAGE_TAG controls only the tag, not the repository, and even after retagging into ghcr.io/y-scope/spider/*, pull_policy: always forces a registry round-trip and hard-fails:

SPIDER_IMAGE_TAG=local-test task docker:compose:up
→ failed to resolve reference "ghcr.io/y-scope/spider/worker:local-test": not found

…with the image present in the local daemon. I had to carry a pull_policy: never override through every test to work around it.

Suggested one-liner, keeping the safe default:

pull_policy: "${SPIDER_PULL_POLICY:-always}"

Should fix

Undocumented environment variables

The header comment documents the 3 required vars; these 7 are undocumented:
SPIDER_IMAGE_TAG, SPIDER_WORKER_CONTAINER_IMAGE_REF, SPIDER_RESTART_POLICY, SPIDER_STORAGE_HOST, SPIDER_STORAGE_HOST_PORT, SPIDER_WORKER_REPLICAS, SPIDER_{STORAGE,SCHEDULER,WORKER}_RUST_LOG.

Since both tasks cd into the compose directory, Compose auto-loads a .env from there — an .env.example would document all ten at once, and would also make task docker:compose:validate runnable without hand-exporting credentials (today it can't run at all without them, and --no-interpolate doesn't help since it then trips on ${SPIDER_STORAGE_HOST:-127.0.0.1} as an IP).

Question

Was dropping --wait-timeout intentional?

bb36fec ("Add clean task") also removed the --wait-timeout flag and the SPIDER_COMPOSE_WAIT_TIMEOUT knob from compose:up, which isn't mentioned in that commit's message.

For what it's worth the behaviour is effectively unchanged — I measured up --wait self-terminating after 124s with this PR's healthcheck timings (start_period 60s, interval 30s, retries 3), versus the 120s that was removed. So no functional concern, but the PR description still advertises "a configurable startup timeout defaulting to 120 seconds", which is now stale either way.

Nits

  • SPIDER_STORAGE_HOST is the host IP the published port binds to, not the storage host — confusing next to SPIDER_STORAGE_DB_* and storage.yaml's own host: (a bind address). SPIDER_STORAGE_PUBLISH_IP reads more clearly.
  • SPIDER_WORKER_CONTAINER_IMAGE_REF carries a CONTAINER that no other variable has.
  • Worth confirming: is a custom image via SPIDER_WORKER_CONTAINER_IMAGE_REF the intended way to supply TDL packages? Helm has worker.extra_volumes/extra_envs and compose has no equivalent. I verified the custom-image path works end-to-end, so this seems like a deliberate design — just want to confirm it's documented as the mechanism.

Follow-up (not for this PR)

30 config values are duplicated between config/*.yaml and the Helm chart's values.yaml. I diffed all 30 mechanically and found zero drift today — but nothing enforces it, and RoundRobinConfig is deny_unknown_fields, so a missed rename breaks the deployment at runtime rather than at validation.

It's worse inside the compose deployment itself, since config/*.yaml can't be templated by compose.yaml: storage port 50051 appears in 6 places, scheduler port 50052 in 4, and service hostnames in 5. Renaming a service silently breaks DNS resolution in the config files, and compose config --quiet won't catch it (it validates schema, not cross-references).

This is intrinsic to Compose having no templating — you already de-duplicated everything YAML anchors can reach with x-service-defaults/x-healthcheck-defaults, which is the right call. Suggestion for later: a spider-compose.yaml CI workflow (mirroring spider-helm.yaml) that runs task docker:compose:validate and asserts the compose configs and values.yaml still agree. Right now nothing runs compose:validate at all — the new files only get yamllint, which checks style, not compose schema.

Separate issue, not caused by this PR

Running jobs surfaces a scheduler bug that also affects the Helm deployment — filed separately as #429. Summary: every completed assignment leaves the scheduler retrying forever at ~3 warnings/sec, growing with lifetime task count. Job correctness is unaffected.

Worth calling out that logging: driver: "local" contains the blast radius here: I measured it capping at ~69MB retained out of 151MB written. Docker's default json-file is unbounded, so that choice is doing real work.


Validation performed

Host is arm64 and the published images are amd64-only, so I built all images natively via task docker:build and ran against those.

Everything in the PR description reproduces: config validates, missing-var errors are clear, all 3 image-resolution paths resolve as documented, 7 containers come up healthy in ~19s with restart count 0, only storage is published (127.0.0.1:50051), and down/clean leave zero containers/networks/volumes.

Beyond the description:

  • Real jobs execute correctly. I built a worker image with the integration_test_tasks TDL package staged at package_dir, pointed the deployment at it via SPIDER_WORKER_CONTAINER_IMAGE_REF, and submitted fibonacci(20) from a container attached only to spider_default (the documented consumer topology). Result: 6765, correct. 9/9 jobs succeeded, distributed across 3 of 4 workers, all containers still at restart count 0 afterward. Confirmed at each hop: scheduler num_task_assignments_enqueued: 1 → worker Task completed successfully, elapsed_us: 1489SELECT state, COUNT(*) FROM jobsSucceeded 9.
  • depends_on: restart: true cascade works — restarting the DB correctly cascaded to storage → scheduler → all 4 workers, all recovering healthy.
  • Volume persists across down and is removed by clean (verified with a marker row).
  • down completes in 2.6s — all three binaries handle SIGTERM, so stop_grace_period: 60s is a ceiling, not a cost.
  • Config files match the Rust structs exactly, including the 8 RoundRobinConfig keys that deny_unknown_fields would reject.
  • yamllint --strict passes on the new files.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
taskfiles/docker.yaml (1)

26-28: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make compose:validate runnable from a clean checkout.

.gitignore excludes tools/deployment/spider-compose/.env, but compose:validate still requires the database credential variables used by required ${VAR:?…} interpolations, so docker compose config --quiet fails unless the user copies the example env file or exports those variables. Direct the command at a documented syntax-only default env file instead.

Suggested change
-    cmd: "docker compose --file compose.yaml config --quiet"
+    cmd: "docker compose --env-file .env.example --file compose.yaml config --quiet"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@taskfiles/docker.yaml` around lines 26 - 28, Update the compose:validate task
to pass Docker Compose the documented syntax-only default environment file when
validating compose.yaml. Ensure the command uses that tracked default env file
so required variable interpolation succeeds from a clean checkout without
relying on ignored .env files or exported credentials.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@taskfiles/docker.yaml`:
- Line 32: Restore the bounded startup timeout for tcompose:up: add
SPIDER_COMPOSE_WAIT_TIMEOUT=120 to tools/deployment/spider-compose/.env.example,
load that variable in the Taskfile, and update the docker compose command to
pass --wait-timeout using the variable with 120 as its fallback.

In `@tools/deployment/spider-compose/.env.example`:
- Line 10: Update the SPIDER_PULL_POLICY example in the environment template to
a local-image-friendly default that allows locally tagged images to be used
without pulling from the registry, or document the required explicit override
for local builds. Keep it consistent with the image references produced by the
deployment taskfiles and consumed by the Compose configuration.

---

Outside diff comments:
In `@taskfiles/docker.yaml`:
- Around line 26-28: Update the compose:validate task to pass Docker Compose the
documented syntax-only default environment file when validating compose.yaml.
Ensure the command uses that tracked default env file so required variable
interpolation succeeds from a clean checkout without relying on ignored .env
files or exported credentials.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f68a5675-8b3a-4623-8bf7-fc6dc41080cc

📥 Commits

Reviewing files that changed from the base of the PR and between 470f7e5 and 07baeee.

📒 Files selected for processing (4)
  • .gitignore
  • taskfiles/docker.yaml
  • tools/deployment/spider-compose/.env.example
  • tools/deployment/spider-compose/compose.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • tools/deployment/spider-compose/compose.yaml

Comment thread taskfiles/docker.yaml

compose:up:
dir: "{{.G_SPIDER_COMPOSE_DIR}}"
cmd: "docker compose --file compose.yaml up --detach --wait"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate docker taskfiles =="
fd -a 'docker\.ya?ml$' . || true

echo "== taskfiles/docker.yaml excerpt =="
if [ -f taskfiles/docker.yaml ]; then
  nl -ba taskfiles/docker.yaml | sed -n '1,120p'
fi

echo "== env examples and wait references =="
fd -a '(\.env\.example|example.*\.env|.*env.*)' . | sed -n '1,80p'
rg -n "SPIDER_COMPOSE_WAIT_TIMEOUT|wait-timeout|docker compose|120|wait" -S . --glob '!node_modules' --glob '!dist' --glob '!build' 2>/dev/null | sed -n '1,200p'

Repository: y-scope/spider

Length of output: 299


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== taskfiles/docker.yaml excerpt =="
if [ -f taskfiles/docker.yaml ]; then
  awk '{printf "%6d\t%s\n", NR, $0}' taskfiles/docker.yaml | sed -n '1,120p'
fi

echo "== tracked relevant files (sample) =="
git ls-files | grep -E '(^|/)(\.env\.example|example.*\.env|.*\.env|taskfiles/docker\.yaml|compose\.ya?ml|README\.md)$' | sed -n '1,120p'

echo "== wait and variable references =="
grep -RIn -E "SPIDER_COMPOSE_WAIT_TIMEOUT|wait-timeout|docker compose|120|wait" --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=build . 2>/dev/null | sed -n '1,240p' || true

Repository: y-scope/spider

Length of output: 29282


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Taskfile references =="
for f in $(git ls-files 'Taskfile*' 'taskfiles/*' 'pyproject.toml'); do
  echo "--- $f"
  grep -nIIn -E "dotenv|envfile|env_file|SPIDER_COMPOSE_WAIT_TIMEOUT|compose:up|docker" "$f" 2>/dev/null || true
done

echo "== spider-compose env and compose metadata =="
if [ -f tools/deployment/spider-compose/.env.example ]; then
  awk '{printf "%6d\t%s\n", NR, $0}' tools/deployment/spider-compose/.env.example
fi
if [ -f tools/deployment/spider-compose/compose.yaml ]; then
  sed -n '1,80p' tools/deployment/spider-compose/compose.yaml
fi

echo "== repo-wide 120/wait references excluding generated deps =="
grep -RIn -E "SPIDER_COMPOSE_WAIT_TIMEOUT|wait-timeout|compose:up|120.*second|second.*120|startup timeout|bounded|timeout" --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=build --exclude-dir=.git . 2>/dev/null | sed -n '1,160p' || true

Repository: y-scope/spider

Length of output: 23494


🌐 Web query:

Docker Compose up --wait-timeout documentation

💡 Result:

The --wait-timeout option in Docker Compose is used with the --wait flag to specify a maximum duration, in seconds, to wait for the services in a project to reach a running or healthy state [1][2][3]. Key details regarding this option: Purpose: It prevents the docker compose up command from waiting indefinitely when services fail to start or reach a healthy state within a reasonable timeframe [4][5]. Usage: It must be used in conjunction with the --wait flag, which signifies that the command should wait for services to be running or healthy [1][2]. Because the --wait flag implies detached mode, --wait-timeout is typically used when running services in the background [1][3]. Syntax: You can specify the timeout in seconds as follows: docker compose up -d --wait --wait-timeout Note: This option is distinct from the --timeout (or -t) flag, which is used to set the timeout for container shutdown [1][6]. While the --wait-timeout feature was introduced to address issues where processes would hang, users should be aware of ongoing maintenance and potential bugs in specific edge cases, such as complex dependency conditions (e.g., service_completed_successfully) [7][4].

Citations:


Restore the bounded startup timeout.

tcompose:up uses docker compose up --detach --wait without --wait-timeout, so startup waits are no longer bounded by the documented 120-second limit. Add SPIDER_COMPOSE_WAIT_TIMEOUT=120 to tools/deployment/spider-compose/.env.example, load the variable in the Taskfile, and pass --wait-timeout ${.SPIDER_COMPOSE_WAIT_TIMEOUT:-120} to the compose command.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@taskfiles/docker.yaml` at line 32, Restore the bounded startup timeout for
tcompose:up: add SPIDER_COMPOSE_WAIT_TIMEOUT=120 to
tools/deployment/spider-compose/.env.example, load that variable in the
Taskfile, and update the docker compose command to pass --wait-timeout using the
variable with 120 as its fallback.


# Optional deployment settings and their defaults.
SPIDER_IMAGE_TAG=main
SPIDER_PULL_POLICY=always

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
git ls-files | rg '(^|/)(\.env\.example|docker\.yaml|compose\.ya?ml)$' || true

echo
echo "== spider compose env example =="
if [ -f tools/deployment/spider-compose/.env.example ]; then
  cat -n tools/deployment/spider-compose/.env.example
fi

echo
echo "== taskfiles/docker.yaml relevant references =="
if [ -f taskfiles/docker.yaml ]; then
  rg -n "SPIDER_|spider|compose|pull|build|task" taskfiles/docker.yaml -C 3
fi

echo
echo "== compose files referencing SPIDER_PULL_POLICY or spider pull_policy =="
for f in $(git ls-files | rg '(^|/)(docker|docker-compose|compose)\.ya?ml$' -i); do
  echo "-- $f --"
  rg -n "SPIDER_PULL_POLICY|pull_policy|services:" "$f" -C 3 || true
done

Repository: y-scope/spider

Length of output: 2845


🌐 Web query:

Docker Compose pull_policy missing cached image when available

💡 Result:

If Docker Compose is failing to use a locally cached image when you expect it to, it is typically due to a mismatch between the expected image tag/digest or the configuration of the pull_policy. The pull_policy attribute controls how Docker Compose handles image retrieval [1][2]. When you believe an image should be found locally but it is not, check the following: 1. Verify Image Existence and Tags: Ensure the image name and tag (or digest) exactly match what is defined in your docker-compose.yml file. You can verify this by running the command docker images [1]. If the tag in your local cache does not match the tag defined in the compose file, Compose will treat it as missing [1][3]. 2. Check the pull_policy Setting: - missing (or if_not_present): This is the default policy if no build section is defined [2]. It uses the local image if it exists; otherwise, it attempts to pull from the registry [1][4]. - never: This tells Compose to use the local image only and never attempt to pull from a registry [3][4]. If the image is not in your local cache, the service will fail to start [5][3]. - build: If a build section is present, Compose may prioritize building the image from source over using an existing local image [2][6]. 3. Interaction with the build Directive: If your service includes a build section, Docker Compose's behavior changes [6]. Even if an image exists locally, Compose might trigger a rebuild or attempt to pull if not configured correctly [6][7]. If you want to force the use of a local image while a build section is present, setting pull_policy: never can prevent accidental pulls, though you may still need to manage the build behavior explicitly [2][7]. Troubleshooting Tips: - Verify with docker images: Confirm that the exact image name and tag reside in the Docker daemon's image store [1][3]. - Overriding policies: You can force a specific behavior during execution by using the --pull flag with the docker compose up command (e.g., --pull always or --pull never) to override the file configuration for a single run [2]. - Clean up: If you suspect issues with local cache integrity, ensure that there are no dangling images or conflicting tags that might be confusing the resolution process [3].

Citations:


🌐 Web query:

Docker Compose service pull_policy always local image pull policy always documentation

💡 Result:

In Docker Compose, the pull_policy attribute defines the behavior for fetching container images from a registry [1][2]. The pull_policy: always setting instructs Docker Compose to pull the image from the registry every time the service starts, regardless of whether the image already exists in the local platform cache [1][2]. This is useful for tags that are frequently updated (such as:latest or development branch tags) to ensure you are always using the most recent version available on the registry [2]. The following pull_policy options are available in the Compose Specification [1]: - always: Pulls the image from the registry every time [1][2]. - missing (or if_not_present): The default behavior. Compose pulls the image only if it is not already available in the local platform cache [1][2]. Note that the:latest tag is always checked/pulled even with this policy [1][2]. - never: Does not attempt to pull the image from a registry. It relies entirely on the locally cached image and will report a failure if the image is missing [1][2]. - build: Compose builds the image from source, even if it is already present [1][2]. - daily: Checks the registry if the last pull occurred more than 24 hours ago [1][2]. - weekly: Checks the registry if the last pull occurred more than 7 days ago [1][2]. - every_: Checks for updates if the last pull took place before the specified duration (e.g., every_12h, every_30m) [1][2]. You can also override the configuration file setting using command-line flags. For example, using docker compose up --pull always will force a pull for all services regardless of their individual pull_policy settings [2]. Likewise, the docker compose pull command respects the pull_policy defined in your file unless a different policy is specified via the --policy flag [3][2].

Citations:


🌐 Web query:

site:docs.docker.com reference/compose-file/services pull_policy always missing never

💡 Result:

In Docker Compose, the pull_policy attribute is used within a service definition to control when and how the service's image is pulled from a registry [1][2]. While command-line flags like --pull (available in commands such as docker compose up and docker compose create) explicitly accept values such as "always", "missing", "never", and sometimes "build" [3][4], the pull_policy attribute within the compose.yaml file itself functions based on the Compose Specification's defined behavior for image resolution [5][6]. When pull_policy is configured in a service definition, it determines the image pulling strategy: - always: Compose always attempts to pull the image from the registry, even if it is already present locally [5]. - missing: Compose pulls the image only if it is not already available in the local image store [1][2]. - never: Compose does not attempt to pull the image from the registry and relies entirely on the local image. If pull_policy is omitted, the default behavior of Compose is to attempt to pull the image if it is missing, and in scenarios where a build section is also defined, Compose manages the precedence of pulling versus building from source according to the Compose Build Specification [5][1][2]. Note that the --pull command-line flag provides additional control during runtime execution, separate from the persistent configuration set in the Compose file [7][3][4].

Citations:


🌐 Web query:

"SPIDER_WORKER_CONTAINER_IMAGE_REF" "tools/docker/build.sh" "build.sh"

💡 Result:

The term SPIDER_WORKER_CONTAINER_IMAGE_REF is not a standard tool or universal environment variable, but rather an application-specific configuration identifier. It is primarily associated with projects using containerized worker architectures, such as those found in custom CI/CD pipelines or distributed systems [1]. In the context of the requested path tools/docker/build.sh, this script is a common pattern used in various open-source projects (such as Apache TVM, Apache Karaf, and Microsoft Playwright) to automate the building and tagging of Docker images [2][3][4]. While build.sh scripts generally perform the same function—compiling source and wrapping it in a container—they are specific to the repository where they reside [2][3][4]. If you are encountering SPIDER_WORKER_CONTAINER_IMAGE_REF in a configuration file or environment, it is likely being used as a reference to define which Docker image tag or registry path the worker service should pull or utilize for a given task [1]. To effectively use a tools/docker/build.sh script, you should: 1. Navigate to the directory containing the script. 2. Check the script's usage by running./tools/docker/build.sh --help (or equivalent), as most of these scripts require arguments like --tag, --platform, or specific environment variables to function correctly [3][4]. 3. Ensure any required dependencies (e.g., node_modules, cargo builds, or specific build-time binaries) are installed or prepared as indicated by the script's internal logic [2][4]. If you are working with a specific project, consult that project's documentation or repository root README for how their build system handles image references [5][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files under tools =="
git ls-files tools | sed -n '1,200p'

echo
echo "== tools/docker/build.sh references if present =="
if [ -f tools/docker/build.sh ]; then
  wc -l tools/docker/build.sh
  rg -n "SPIDER_IMAGE_TAG|SPIDER_WORKER_CONTAINER_IMAGE_REF|IMAGE_TAG|tag|build|DOCKER|docker" tools/docker/build.sh -C 2 || true
fi

echo
echo "== compose image references =="
cat -n tools/deployment/spider-compose/compose.yaml

Repository: y-scope/spider

Length of output: 7466


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== taskfiles/docker.yaml referenced build images and compose default =="
cat -n taskfiles/docker.yaml
echo
echo "== tools/docker/build.sh =="
cat -n tools/docker/build.sh
echo
echo "== tools/docker/Dockerfile stages =="
sed -n '1,220p' tools/docker/Dockerfile | rg -n "FROM|AS " -C 2 || sed -n '1,220p' tools/docker/Dockerfile

Repository: y-scope/spider

Length of output: 4176


Use a local-image-friendly default pull policy.

taskfiles/docker.yaml builds images with docker tag using spider-${service}:dev-..., while tools/deployment/spider-compose/compose.yaml expects ghcr.io/y-scope/spider/${SPIDER_IMAGE_TAG:-main} by default. With SPIDER_PULL_POLICY=always, Compose pulls that registry reference every start, so local dev builds are ignored unless SPIDER_WORKER_CONTAINER_IMAGE_REF is overridden.

If local builds are meant to work with this Compose setup, use an example value matching the local tag or document that local builds need an explicit override.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/deployment/spider-compose/.env.example` at line 10, Update the
SPIDER_PULL_POLICY example in the environment template to a local-image-friendly
default that allows locally tagged images to be used without pulling from the
registry, or document the required explicit override for local builds. Keep it
consistent with the image references produced by the deployment taskfiles and
consumed by the Compose configuration.

@sitaowang1998

Copy link
Copy Markdown
Collaborator Author

I have fixed:

  • The pull policy is configurable, with default set as always.
  • All environment variables are grouped in .env.example file.
  • Rename SPIDER_STORAGE_HOST to SPIDER_STORAGE_PUBLISH_IP.

To answer the question:

  • wait-time is never the goal of the PR. It was added and removed during the composing of the PR, and CodeRabbit mistakenly include it in the PR description.
  • SPIDER_WORKER_CONTAINER_IMAGE_REF is intended so the users can override and provide their own worker images.

jackluo923
jackluo923 previously approved these changes Aug 7, 2026

@jackluo923 jackluo923 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good to me, thanks for the quick turnaround.

Nit: I'd rename SPIDER_WORKER_CONTAINER_IMAGE_REF to SPIDER_WORKER_IMAGE_REF — it's the only variable carrying a CONTAINER, and the rest already follow SPIDER_<COMPONENT>_<SETTING>. Worth doing before the CLP integration hardcodes the name on its side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants