6 Commits

Author SHA1 Message Date
ningkexin96
4f948c7b8d
feat(deploy): select production Compose env files (#6522)
* feat(deploy): select production Compose env files

Use an operator-selected dotenv file consistently for interpolation, container environment, secret probes and build extras. Preserve default selection and shutdown after a profile is removed.

Co-Authored-By: Codex <noreply@openai.com>

* fix(deploy): address production env selection review

Clarify Docker launcher entry points and render real Compose through the launcher to verify both service environments.

Co-Authored-By: Codex <noreply@openai.com>

* test(deploy): cover unreadable env selectors

Reject unreadable explicit selectors before Docker is invoked, using POSIX permission checks and restoring the fixture mode in finally.

Co-Authored-By: Codex <noreply@openai.com>

* test(deploy): scope dotenv assertions to selected secrets

---------

Co-authored-by: Codex <noreply@openai.com>
2026-10-21 15:58:30 +08:00
yu1128-L
badfd7d3f1
fix(docker): make dev provisioner opt-in via compose profile (#6948)
* fix(docker): make dev provisioner opt-in via compose profile

Gate the Kubernetes provisioner behind a Compose profile and have the
wrapper enable it only when config selects provisioner sandbox mode.
This lets the default Docker Compose stack start without kubeconfig.

Fixes #3232

* test(docker): render every compose profile in the env-file regression test

main added backend/tests/test_compose_default_bind_host.py, whose _render helper asserted that the dev provisioner still loads ../.env. `docker compose config` without a profile omits profile-gated services, so that assertion failed once the provisioner became opt-in.

Pass `--profile *` from the helper: the test is about an existing .env reaching every service, so it has to render the services a profile gates rather than only the ones `up` starts by default.

* docs(docker): restore script mode and localize direct Compose guidance

The dev provisioner is now opt-in, but the earlier edit also flipped scripts/docker.sh from 100755 to 100644 even though README.md still documents direct `./scripts/docker.sh` invocation. Restore the executable bit.

Also add the direct-Compose guidance to the translated READMEs so readers of README_zh.md, README_ja.md, and README_fr.md learn that `--profile provisioner` selects the Kubernetes mode and the default stack does not need Kubernetes.

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-10-20 09:10:24 +08:00
Hyeonsang Cho
efc87b6cb2
fix(deploy): let make up start on a checkout without .env files (#6370)
* fix(deploy): let make up start on a checkout without .env files

.env and frontend/.env are gitignored and make up does not create them,
but docker/docker-compose.yaml listed both as short-form env_file entries,
which Compose treats as required. On a fresh clone make up, make down and
make prod-logs all stopped with "env file .../.env not found" (exit 14)
before building or touching anything.

Mark the three entries optional with the long-form path/required syntax
the development compose file already uses. Compose loads them when they
exist and skips them otherwise; an unreadable or non-file .env still
fails. This needs Docker Compose 2.24+, the floor the README already
documents, and deploy.sh's startup-failure hint now names it for older
clients.

deploy.sh deliberately does not seed the files from the examples the way
docker.sh start does: .env.example carries placeholder API keys the
production Gateway would receive, and make config skips files that exist.

* docs(changelog): reference #6370

* test(deploy): gate Compose clients and cover make up

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-10-07 07:28:29 +08:00
YZJF,YCDG,DJLY,ZZZB
851e76661b
fix(docker): don't abort Docker startup when .env is missing (#4956)
* fix(docker): create compose env files and keep Windows compose paths relative

Windows Docker reports a generic file-not-found when env_file targets are missing, or when compose paths are doubled. Make docker-start copy .env examples and invoke compose with filenames relative to docker/.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(docker): make dev compose env files optional and repair test fixture

Address review feedback on #4956.

[P1] prepare_compose_env aborted before the mocked COMPOSE_CMD in
test_compose_commands_set_deer_flow_root_before_compose, because the
temp root had no compose file or .env examples. Seed them in the
fixture so the preflight reaches the mock.

[P2] .env is gitignored, so a fresh clone has none and a direct
`docker compose -f docker/docker-compose-dev.yaml up --build` aborts on
Windows before scripts/docker.sh can help. Mark the dev env_file entries
`required: false` so a missing .env is not fatal, and document that
direct Compose must be run from the repository root.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(docker): declare Compose 2.24 floor and keep non-start commands read-only

Address the second review round on #4956.

- Document Compose >= 2.24 (CONTRIBUTING, README, compose header) and fail
  early from make docker-start with an actionable message; probe both
  `docker compose` and the hyphenated `docker-compose` binary.
- Document DEER_FLOW_ROOT for direct Compose callers (bash + PowerShell);
  leave the variable without a $PWD fallback because PowerShell/cmd do not
  export it.
- Split prepare_compose_env: compose_preflight is shared and read-only;
  ensure_env_files runs only from start.
- Expand tests for version boundaries, hyphenated fallback, env-file
  creation, and read-only stop/logs/restart behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(docker): reuse the probed Compose binary for wrapper operations

The version probe could accept a standalone docker-compose install while
COMPOSE_CMD stayed hardcoded to `docker compose`, so preflight passed and
start/logs/stop/restart then failed. Keep the selected executable in
COMPOSE_BIN (array), refresh COMPOSE_CMD from it in the current shell, and
extend the fallback test through an actual stop invocation.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-24 21:48:37 +08:00
Tsai Yuan
8d15b87d8b
fix(docker): allow default dev frontend origins (#4959) 2026-08-24 07:21:18 +08:00
Nan Gao
2a143dced6
fix(docker): bind the published entry port to loopback by default (#4618)
README documents DeerFlow as deployed by default "in a local trusted
environment (accessible only via the 127.0.0.1 loopback interface)", but both
compose files published nginx as `"${PORT:-2026}:2026"`, which Docker binds to
0.0.0.0 and [::]. The shipped artifact did not match its own documented
default, so running it on a LAN or cloud host produced a wider surface than
the docs implied without the operator changing anything -- and the agent can
execute commands.

Publish as `"${BIND_HOST:-127.0.0.1}:${PORT:-2026}:2026"` in both compose
files, so the default matches the documented model while operators who front
the stack with their own TLS/auth can still widen it via BIND_HOST. The
Gateway keeps binding 0.0.0.0:8001 inside the container (nginx reaches it over
the compose network) and its port stays unpublished, so the published nginx
port is the entire external surface.

BREAKING CHANGE: a deployment that relied on the previous 0.0.0.0 default
becomes unreachable from other hosts after this upgrade. Set BIND_HOST=0.0.0.0
in .env to restore it, after putting authentication in front and completing
first-run setup.

Also:
- .env.example documents BIND_HOST and PORT with the reasoning.
- deploy.sh reports the address the stack actually bound and, when it is not
  loopback, tells the operator to complete first-run setup immediately. It
  reads BIND_HOST/PORT from .env via a new read_dotenv_value helper following
  compose precedence; the shell does not source .env, so reading the
  environment alone would have reported "loopback only" for a stack .env had
  exposed. The pre-existing ${PORT} summary line had the same defect and is
  fixed with it.
- test_compose_default_bind_host.py pins the loopback default, that BIND_HOST
  stays overridable, and that no service in either compose file publishes a
  port without an explicit bind address, so a later addition cannot drift back
  to 0.0.0.0 unnoticed.
2026-08-01 08:35:02 +08:00