# Arize Phoenix's two install paths, its exact dependency pins, and the postgres password it ships in compose

> Arize Phoenix is Arize's open-source AI observability and evaluation platform, written in Python and distributed as a pip package, a uvx command, and container images. Reading its manifest, compose file, and Dockerfile closely, the parts that break your setup are not the tracing features but the version ceilings, the default database credentials, and the fact that the agent endpoint shares a port with the web UI.

**Arize-ai/phoenix** — AI Observability & Evaluation

- Repository: https://github.com/Arize-ai/phoenix
- Website: https://arize.com/docs/phoenix
- Stars: 11,690 · Forks: 1,178
- Language: Python
- License: NOASSERTION
- Published: 2026-08-27 · Updated: 2026-08-27 · Language: en
- Canonical page: https://hysenlabs.com/projects/arize-ai-phoenix

## pip install arize-phoenix drags in scikit-learn, scipy, and pyarrow

The runtime is not a small client library. A plain `pip install arize-phoenix` resolves scikit-learn, scipy, numpy, pandas>=1.0, pyarrow, PyYAML, jinja2, jsonpath-ng, jsonschema, pystache, psutil, uvicorn, starlette>=0.37.0, grpcio, tqdm, and httpx[http2] into the same environment as your application. The GraphQL and SQL layers come along too, through strawberry-graphql and sqlalchemy[asyncio]>=2.1.1, <3, plus alembic>=1.3.0, <2, aiosqlite, and arize-phoenix-sqlean>=0.1.2. If your service already pins pandas, numpy, or scikit-learn at a different version, pip either rewrites your pins or refuses, and that decision lands on your runtime instead of on a sidecar. Keeping Phoenix in its own container is what keeps this dependency surface from reaching the process that serves your users. The same manifest also names three sibling packages you may not expect to find bundled: arize-phoenix-evals>=3.9.0, arize-phoenix-otel>=0.17.0, and openinference-instrumentation-openai>=0.1.41, so evaluation logic and OpenInference instrumentation arrive as install-time requirements rather than something you opt into later. Python itself is bounded: requires-python reads >=3.11, <3.15, and the classifiers stop at 3.14.

## The bundled compose file publishes postgres with the password postgres

docker-compose.yml wires two services. The phoenix service builds from ./Dockerfile, declares depends_on db, and maps the web and OTLP ports:

```yaml
    ports:
      - 6006:6006
      - 4317:4317
    environment:
      - PHOENIX_SQL_DATABASE_URL=postgresql://postgres:postgres@db:5432/postgres
```

The db service is `image: postgres:16` with `restart: always`, and its POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB values are all set to postgres. Port 5432 is published to the host, and a named volume database_data sits at /var/lib/postgresql/data. Those are stock image credentials written into a committed file, and the database port is exposed rather than kept on the internal network. That is fine on a laptop with a loopback interface and a liability on a shared CI runner or any machine with a routable address, where an unauthenticated postgres answers on 5432 for anyone who can reach the host. Change the password and delete the 5432 mapping before this file touches a network you do not control. Note also that this compose file is a development convenience: it builds the image from the local Dockerfile rather than pulling a tagged release, and it declares no volume for Phoenix itself, so trace and evaluation data lives wherever PHOENIX_SQL_DATABASE_URL points.

## One port carries both the web UI and the agent /mcp endpoint

Three endpoints matter. The compose file and the Dockerfile comments both center on 6006, and the cursor deeplink linked from the README encodes its target as `{"url":"http://localhost:6006/mcp"}`, which puts the Remote MCP Server on the same port as the browser interface. 4317 is the OTLP gRPC receiver that trace export targets. The consequence of that arrangement is that the endpoint letting Claude Code, Cursor, and other MCP clients query traces, datasets, experiments, and more has no separate network boundary from the UI. Nothing in the setup path describes authentication on either surface, so network placement becomes the control you actually have. An agent that can reach your local UI can also reach the evaluation data behind it, and a browser tab opened on the same host can do the same.

## graphql-core and sqlglot are pinned to dodge named defects

Several constraints in pyproject.toml exist because of specific bugs rather than preference:

```toml
  "strawberry-graphql==0.327.7",
  "graphql-core<3.3",  # 3.3 changes default-value coercion used by schema search
```

The graphql-core ceiling exists because 3.3 changes the default-value coercion that schema search depends on, so a careless transitive upgrade breaks a feature rather than the server. `fastapi>=0.137.0` carries a comment stating that 0.137 keeps included routers as a lazy _IncludedRouter tree and that older versions raise AssertionError on 204 routes. `opentelemetry-proto>=1.12.0` holds a floor to avoid the problem tracked in issue 2695. `sqlglot==30.18.0` is an exact pin with no range at all. You inherit a tested combination, and you also inherit ceilings chosen around Phoenix internals, so a second package in the same environment wanting a newer graphql-core forces one of you to move. openinference-semantic-conventions>=0.1.40, openinference-instrumentation>=0.1.60, and opentelemetry-sdk are held to floors in the same list, which means an upgrade of the Phoenix server can quietly raise the minimum version of your tracing libraries.

## The image builds a TypeScript frontend before it touches Python

The Dockerfile is multi-stage. The frontend stage starts from node:24-slim, sets PNPM_HOME and PHOENIX_ENABLE_SOURCE_MAP=True, copies ./js and ./schemas into /phoenix, then runs `npm i -g corepack`, `corepack enable`, `corepack install`, and `pnpm install` ahead of the vite build. A comment on that stage warns that the workspace dependency @arizeai/phoenix-client regenerates its OpenAPI types from the repo-level schema while building, so the ./schemas copy has to happen or the client build fails on missing types. The usage commands are written into the file as comments:

```shell
# > docker build -t phoenix
#
# You can then run the image in the background with:
#
# > docker run -d --name phoenix -p 6006:6006 phoenix
#
# or in the foreground with:
#
# > docker run -it -p 6006:6006 phoenix
```

The runtime base is chosen through an ARG whose default is gcr.io/distroless/python3-debian13:nonroot, and the comment above it says to take the nonroot-arm64 variant when targeting Raspberry Pi or Apple-Silicon. Build on an arm64 host without switching that ARG and you either emulate or end up with a foreign-architecture image. The build also depends on the uv image being pinned once: a comment above it notes that both stages build on it, that it must resolve to the same digest, and that the uv version has to stay equal to the required-version recorded in pyproject.toml.

## px setup only resolves if Phoenix is already installed

Trace wiring has two entry points:

```shell
npx @arizeai/phoenix-cli setup
# or, with Phoenix installed: px setup
```

The trailing comment is the whole difference. npx fetches the CLI at invocation time and works in a project with no Phoenix dependency at all, while px resolves only when arize-phoenix is already present. Setup detects your framework and LLM provider, installs the matching OpenInference instrumentation, and wires trace export. What it does not touch is everything else the product advertises: versioned datasets, experiments, response and retrieval evals, the playground, prompt management, and PXI all stay unconfigured until you set them up by hand after the first trace arrives. The two paths also imply two version stories, since npx resolves whatever is current at the moment you run it and px follows the pin your lockfile already holds. The framework and provider coverage is broad on paper, with entries for the OpenAI Agents SDK, Claude Agent SDK, LangGraph, Vercel AI SDK, Mastra, CrewAI, LlamaIndex, and DSPy, plus OpenAI, Anthropic, Google GenAI, Google ADK, AWS Bedrock, OpenRouter, and LiteLLM, but detection still happens through the separate OpenInference project rather than inside the CLI itself.

## js/, java/, packages/, helm/, and kustomize/ share one Makefile

The repository is a monorepo carrying several deployment targets at once: Dockerfile and docker-compose.yml, helm/, kustomize/, azuredeploy.json, and app.json, alongside js/, java/, packages/, and schemas/. The Makefile is the entry point, with SHELL set to /bin/bash and .DEFAULT_GOAL set to help, driving tox, pnpm, uv, and node through targets including dev-backend, dev-frontend, dev-docker, dev-mock-llm, test-helm, doctest, codegen-python-client, codegen-ts-client, schema-ddl, check-graphql-permissions, gen-otel-models, and harbor-plugin-e2e. Contributing means standing up that toolchain rather than running pip. The distributed product stays self-hosted, with Arize AX offered as the managed option, and the note in the README states that the same OpenTelemetry and OpenInference instrumentation works with either, so traces survive a move. The Dockerfile asking how you are using Phoenix in production, and directing questions to the #phoenix-support Slack channel, is the clearest signal of who answers when it breaks. Release cadence is fast rather than cautious: arize-phoenix-v20.19.0 landed on 2026-10-01 with v20.18.0 and v20.17.0 both dated 2026-09-30, and the last push is 2026-10-02, so a version number in your lockfile can be two releases behind within a day.

## Conclusion

Phoenix fits teams that want OpenTelemetry traces, datasets, experiments, and LLM evals on infrastructure they operate, and who are willing to own the container, the database, and the dependency surface it brings with it. Before deploying, read the LICENSE and IP_NOTICE files yourself rather than trusting the license field, change the compose database credentials and drop the 5432 host mapping, decide whether the /mcp endpoint on port 6006 belongs on a network your agents and browsers can reach, and confirm your environment can live with the graphql-core and sqlglot ceilings the manifest pins.

## FAQ

### how to install phoenix

Arize Phoenix installs with `pip install arize-phoenix` followed by `phoenix serve`, or with no install at all using `uvx arize-phoenix serve`. Container images are also published to Docker Hub and deployable through the Helm chart.

### Which Python versions does Arize Phoenix support?

pyproject.toml sets requires-python to >=3.11, <3.15, and the classifiers list 3.11, 3.12, 3.13, and 3.14.

### What ports does the Arize Phoenix compose file expose?

The phoenix service publishes 6006:6006 and 4317:4317, and the db service publishes 5432. The database password, user, and name are all set to postgres in that file.

### What license does Arize Phoenix ship under?

pyproject.toml declares license text Elastic-2.0 with LICENSE and IP_NOTICE listed as the license files, while repository metadata reports no asserted license. Read both files yourself before you choose it.

### Can a coding agent query a local Arize Phoenix instance?

The Remote MCP Server exposes a /mcp endpoint, and the README cursor deeplink points at http://localhost:6006/mcp, which is the same port as the web UI.

## Sources

- [Official documentation](https://arize.com/docs/phoenix)
- [Official README](https://github.com/Arize-ai/phoenix#readme)
- [Project repository](https://github.com/Arize-ai/phoenix)
- [Release notes](https://github.com/Arize-ai/phoenix/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/arize-ai-phoenix
