diff --git a/.changeset/hip-poems-shave.md b/.changeset/hip-poems-shave.md new file mode 100644 index 000000000..a22e5f5da --- /dev/null +++ b/.changeset/hip-poems-shave.md @@ -0,0 +1,6 @@ +--- +"@ensnode/integration-test-env": patch +"@docs/ensnode": patch +--- + +Moved docker-compose.yml file to separate `docker` directory, updates docs and cicd-tests diff --git a/README.md b/README.md index e56e1a5ca..12dc0e6d8 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,14 @@ ENSNode is a modern, multichain indexer for ENS. It supports backwards-compatibl Documentation for the ENSNode suite of apps is available at [ensnode.io](https://ensnode.io). +## Running with Docker + +```bash +docker compose -f docker/docker-compose.yml up -d +``` + +See [`docker/README.md`](docker/README.md) for all use cases and commands. + ## Contributions We welcome community contributions and feedback—please see [CONTRIBUTING.md](CONTRIBUTING.md) for more information. diff --git a/apps/ensindexer/.env.local.example b/apps/ensindexer/.env.local.example index cd5b3d948..412aa88dc 100644 --- a/apps/ensindexer/.env.local.example +++ b/apps/ensindexer/.env.local.example @@ -243,6 +243,7 @@ ENSRAINBOW_URL=http://localhost:3223 # https://ensnode.io/ensrainbow/usage/available-label-sets # # LABEL_SET_ID: see https://ensnode.io/ensrainbow/concepts/glossary#label-set-id. +# Should match ENSRainbow's LABEL_SET_ID. LABEL_SET_ID=subgraph # LABEL_SET_VERSION: see https://ensnode.io/ensrainbow/concepts/glossary#label-set-version. diff --git a/apps/ensrainbow/.env.local.example b/apps/ensrainbow/.env.local.example index 7eb88231b..837519561 100644 --- a/apps/ensrainbow/.env.local.example +++ b/apps/ensrainbow/.env.local.example @@ -16,7 +16,7 @@ LOG_LEVEL=info DB_SCHEMA_VERSION=3 # Label set ID (see https://ensnode.io/ensrainbow/concepts/glossary#label-set-id) -LABEL_SET_ID=ens-test-env +LABEL_SET_ID=subgraph # Label set version (see https://ensnode.io/ensrainbow/concepts/glossary#label-set-version) LABEL_SET_VERSION=0 diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 1f04274da..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,127 +0,0 @@ -services: - ensindexer: - container_name: ensindexer - image: ghcr.io/namehash/ensnode/ensindexer:latest - ports: - - "42069:42069" - environment: - # Override environment variables to point to docker instances - ENSDB_URL: postgresql://postgres:password@postgres:5432/postgres - ENSINDEXER_SCHEMA_NAME: docker_compose_ensindexer_schema - ENSRAINBOW_URL: http://ensrainbow:3223 - env_file: - # NOTE: must define apps/ensindexer/.env.local (see apps/ensindexer/.env.local.example) - # Copy .env.local.example to .env.local and configure all required values - - path: ./apps/ensindexer/.env.local - required: true - healthcheck: - test: ["CMD", "curl", "--fail", "-s", "http://localhost:42069/health"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 5m - start_interval: 1s - depends_on: - ensrainbow: - condition: service_healthy - postgres: - condition: service_started - - ensapi: - container_name: ensapi - image: ghcr.io/namehash/ensnode/ensapi:latest - ports: - - "4334:4334" - environment: - # Override environment variables to point to docker instances - ENSDB_URL: postgresql://postgres:password@postgres:5432/postgres - ENSINDEXER_SCHEMA_NAME: docker_compose_ensindexer_schema - env_file: - # NOTE: must define apps/ensapi/.env.local (see apps/ensapi/.env.local.example) - # Copy .env.local.example to .env.local and configure all required values - - path: ./apps/ensapi/.env.local - required: true - healthcheck: - test: ["CMD", "curl", "--fail", "-s", "http://localhost:4334/health"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 1m - start_interval: 1s - depends_on: - postgres: - condition: service_started - - ensrainbow: - container_name: ensrainbow - image: ghcr.io/namehash/ensnode/ensrainbow:latest - ports: - - "3223:3223" - env_file: - # NOTE: Optionally define apps/ensrainbow/.env.local (see apps/ensrainbow/.env.local.example) - - path: ./apps/ensrainbow/.env.local - required: false - volumes: - - ensrainbow_data:/app/apps/ensrainbow/data - restart: unless-stopped - healthcheck: - test: ["CMD", "wget", "-q", "--spider", "http://localhost:3223/health"] - interval: 30s - timeout: 3s - retries: 3 - start_period: 20m - start_interval: 1s - - ensadmin: - container_name: ensadmin - image: ghcr.io/namehash/ensnode/ensadmin:latest - ports: - - "4173:4173" - environment: - # Override environment variables to point to docker instances - # NOTE: must be host-accessible (i.e. http://localhost) - ENSADMIN_PUBLIC_URL: http://localhost:4173 - # NOTE: must be host-accessible (i.e. http://localhost) - NEXT_PUBLIC_SERVER_CONNECTION_LIBRARY: http://localhost:4334 - env_file: - # NOTE: can define apps/ensadmin/.env.local (see apps/ensadmin/.env.local.example) - - path: ./apps/ensadmin/.env.local - required: false - depends_on: - ensapi: - condition: service_started - - postgres: - container_name: postgres - image: postgres:17 - environment: - POSTGRES_DB: postgres - POSTGRES_USER: postgres - POSTGRES_PASSWORD: password - ports: - - "5432:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - - devnet: - container_name: devnet - image: ghcr.io/ensdomains/contracts-v2:main-e8696c6 - command: ./script/runDevnet.ts --testNames - pull_policy: always - ports: - - "8545:8545" - environment: - ANVIL_IP_ADDR: "0.0.0.0" - healthcheck: - test: ["CMD", "curl", "--fail", "-s", "http://localhost:8000/health"] - interval: 10s - timeout: 5s - retries: 5 - start_period: 30s - start_interval: 1s - -volumes: - postgres_data: - driver: local - ensrainbow_data: - driver: local diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 000000000..ac8e8f6ba --- /dev/null +++ b/docker/README.md @@ -0,0 +1,90 @@ +# Docker Compose + +All commands are run from the **monorepo root**. + +## Files + +| File | Purpose | +| ---------------------------------------- | -------------------------------------------------------------------------------------- | +| `docker/docker-compose.yml` | Base stack — ensindexer, ensapi, ensrainbow, ensadmin, postgres. For mainnet/sepolia. | +| `docker/docker-compose.devnet.yml` | Full stack against local devnet (`ens-test-env`). Includes all base services + devnet. | +| `docker/docker-compose.orchestrator.yml` | Minimal infra for CI — devnet + postgres only. Used by `orchestrator.ts`. | +| `docker/services/*.yml` | Individual service definitions. Extended by the compose files above. | +| `docker/envs/.env.docker.common` | Shared env defaults (postgres credentials, internal service URLs). Committed. | +| `docker/envs/.env.docker.devnet` | Devnet defaults (PLUGINS, etc.). Committed. Works out of the box. | +| `docker/envs/.env.docker.example` | Example for user-specific config. Copy to `.env.docker.local` for mainnet/sepolia. | +| `docker/envs/.env.docker.local` | User config (gitignored). Required for base stack, optional for devnet overrides. | + +> To inspect the fully resolved config for any compose file (resolves all `extends`): +> +> ``` +> docker compose -f docker/docker-compose.yml config +> ``` + +## Use cases + +### Mainnet / Sepolia + +**1. Configure environment** (one-time setup): + +```bash +cp docker/envs/.env.docker.example docker/envs/.env.docker.local +``` + +Edit `docker/envs/.env.docker.local` and set `NAMESPACE`, `PLUGINS`, and your RPC endpoints (e.g. `ALCHEMY_API_KEY` or `RPC_URL_1`). + +**2. Start/stop the stack:** + +```bash +# Start full stack in background +docker compose -f docker/docker-compose.yml up -d + +# Stop +docker compose -f docker/docker-compose.yml down + +# Stop and remove volumes +docker compose -f docker/docker-compose.yml down -v +``` + +### Local devnet (for developers) + +No setup required — devnet defaults are committed in `docker/envs/.env.docker.devnet`. + +To override defaults (e.g. change `PLUGINS`), create `docker/envs/.env.docker.local` with your values. + +```bash +# Start full stack against devnet +docker compose -f docker/docker-compose.devnet.yml up -d + +# Start only devnet + core services (no ensadmin) +docker compose -f docker/docker-compose.devnet.yml up -d devnet postgres ensrainbow ensindexer ensapi + +# Start only devnet (quick local EVM node, also shows data information about devnet) +docker compose -f docker/docker-compose.devnet.yml up devnet +# or +pnpm devnet + +# Stop +docker compose -f docker/docker-compose.devnet.yml down +``` + +### Build images locally + +```bash +# Build all images +pnpm docker:build:ensnode + +# Build a specific image +pnpm docker:build:ensindexer +pnpm docker:build:ensapi +pnpm docker:build:ensrainbow +pnpm docker:build:ensadmin +``` + +### CI / integration tests + +Used internally by `orchestrator.ts` via testcontainers. Starts devnet + postgres only. + +```bash +pnpm test:integration:ci +``` diff --git a/docker/docker-compose.devnet.yml b/docker/docker-compose.devnet.yml new file mode 100644 index 000000000..76e79373c --- /dev/null +++ b/docker/docker-compose.devnet.yml @@ -0,0 +1,100 @@ +services: + ensindexer: + extends: + file: services/ensindexer.yml + service: ensindexer + environment: + # TODO: in future we will migrate devnet to chain_id=1 + # need to update this line in that case + RPC_URL_15658733: http://devnet:8545 + ENSINDEXER_SCHEMA_NAME: docker_devnet_v1 + LABEL_SET_ID: ens-test-env + NAMESPACE: ens-test-env + env_file: + - path: envs/.env.docker.common + required: true + - path: envs/.env.docker.devnet + required: true + - path: envs/.env.docker.local + required: false + depends_on: + ensrainbow: + condition: service_healthy + postgres: + condition: service_healthy + devnet: + condition: service_healthy + + ensapi: + extends: + file: services/ensapi.yml + service: ensapi + environment: + # TODO: in future we will migrate devnet to chain_id=1 + # need to update this line in that case + RPC_URL_15658733: http://devnet:8545 + ENSINDEXER_SCHEMA_NAME: docker_devnet_v1 + depends_on: + postgres: + condition: service_healthy + env_file: + - path: envs/.env.docker.common + required: true + - path: envs/.env.docker.devnet + required: true + - path: envs/.env.docker.local + required: false + + ensrainbow: + extends: + file: services/ensrainbow.yml + service: ensrainbow + environment: + LABEL_SET_ID: ens-test-env + env_file: + - path: envs/.env.docker.common + required: true + - path: envs/.env.docker.devnet + required: true + - path: envs/.env.docker.local + required: false + + ensadmin: + extends: + file: services/ensadmin.yml + service: ensadmin + depends_on: + ensapi: + condition: service_started + env_file: + - path: envs/.env.docker.common + required: true + - path: envs/.env.docker.devnet + required: true + - path: envs/.env.docker.local + required: false + + postgres: + extends: + file: services/postgres.yml + service: postgres + env_file: + - path: ./envs/.env.docker.common + required: true + + devnet: + extends: + file: services/devnet.yml + service: devnet + +volumes: + # Docker Compose requires volumes used by services to be declared in each + # compose file that references them — they cannot be inherited via `extends`. + # Explicit `name:` prevents collision with the base stack's volumes when both + # are run from the same directory (same project name). + postgres_data: + name: ensnode_devnet_postgres_data + driver: local + ensrainbow_data: + name: ensnode_devnet_ensrainbow_data + driver: local diff --git a/docker/docker-compose.orchestrator.yml b/docker/docker-compose.orchestrator.yml new file mode 100644 index 000000000..e813e27f6 --- /dev/null +++ b/docker/docker-compose.orchestrator.yml @@ -0,0 +1,22 @@ +# Minimal compose for CI integration tests. +# Provides only the infrastructure services needed by orchestrator.ts: +# devnet (local EVM) and postgres (database). +services: + devnet: + extends: + file: services/devnet.yml + service: devnet + + postgres: + extends: + file: services/postgres.yml + service: postgres + env_file: + - path: ./envs/.env.docker.common + required: true + +volumes: + # Docker Compose requires volumes used by services to be declared in each + # compose file that references them — they cannot be inherited via `extends`. + postgres_data: + driver: local diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 000000000..32bddab5d --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,72 @@ +services: + ensindexer: + extends: + file: services/ensindexer.yml + service: ensindexer + environment: + ENSINDEXER_SCHEMA_NAME: docker_ensindexer_v1 + depends_on: + ensrainbow: + condition: service_healthy + postgres: + condition: service_healthy + env_file: + - path: envs/.env.docker.common + required: true + # Copy envs/.env.docker.example to envs/.env.docker.local and configure + - path: envs/.env.docker.local + required: true + + ensapi: + extends: + file: services/ensapi.yml + service: ensapi + environment: + ENSINDEXER_SCHEMA_NAME: docker_ensindexer_v1 + depends_on: + postgres: + condition: service_healthy + env_file: + - path: envs/.env.docker.common + required: true + - path: envs/.env.docker.local + required: true + + ensrainbow: + extends: + file: services/ensrainbow.yml + service: ensrainbow + env_file: + - path: envs/.env.docker.common + required: true + - path: envs/.env.docker.local + required: true + + ensadmin: + extends: + file: services/ensadmin.yml + service: ensadmin + depends_on: + ensapi: + condition: service_started + env_file: + - path: envs/.env.docker.common + required: true + - path: envs/.env.docker.local + required: true + + postgres: + extends: + file: services/postgres.yml + service: postgres + env_file: + - path: envs/.env.docker.common + required: true + +volumes: + # Docker Compose requires volumes used by services to be declared in each + # compose file that references them — they cannot be inherited via `extends`. + postgres_data: + driver: local + ensrainbow_data: + driver: local diff --git a/docker/envs/.env.docker.common b/docker/envs/.env.docker.common new file mode 100644 index 000000000..d8c682539 --- /dev/null +++ b/docker/envs/.env.docker.common @@ -0,0 +1,16 @@ +# Shared Docker Compose environment variables +# Used by docker/docker-compose.yml and its variants + + +# Postgres +POSTGRES_DB=postgres +POSTGRES_USER=postgres +POSTGRES_PASSWORD=password + +# Internal service URLs (container-to-container) +ENSDB_URL=postgresql://postgres:password@postgres:5432/postgres +ENSRAINBOW_URL=http://ensrainbow:3223 + +# ENS Admin +ENSADMIN_PUBLIC_URL=http://localhost:4173 +NEXT_PUBLIC_SERVER_CONNECTION_LIBRARY=http://localhost:4334 diff --git a/docker/envs/.env.docker.devnet b/docker/envs/.env.docker.devnet new file mode 100644 index 000000000..7c63beef8 --- /dev/null +++ b/docker/envs/.env.docker.devnet @@ -0,0 +1,6 @@ +# Default configuration for devnet docker-compose stack. +# These values work out of the box — override by creating .env.docker.local. + +PLUGINS=subgraph,ensv2 +LABEL_SET_VERSION=0 +DB_SCHEMA_VERSION=3 diff --git a/docker/envs/.env.docker.example b/docker/envs/.env.docker.example new file mode 100644 index 000000000..fb1b60416 --- /dev/null +++ b/docker/envs/.env.docker.example @@ -0,0 +1,41 @@ +# Docker environment configuration for ENSNode. +# Copy this file to .env.docker.local and fill in the values. +# +# For devnet: env.docker.local is not required — defaults are in .env.docker.devnet. +# Override by creating .env.docker.local with your custom values. +# For mainnet/sepolia: copy this file to .env.docker.local and configure below. + +# ENS Namespace +# Required. Must be: mainnet, sepolia, or ens-test-env. +NAMESPACE=mainnet + +# Plugin Configuration +# Required. Comma-separated list of plugins to activate. +# For subgraph-compatible indexing only: PLUGINS=subgraph +# For full indexing: PLUGINS=subgraph,basenames,lineanames,threedns,protocol-acceleration,registrars,tokenscope +PLUGINS=subgraph + +# ENSRainbow Label Set Configuration +# See https://ensnode.io/ensrainbow/usage/available-label-sets +LABEL_SET_ID=subgraph +LABEL_SET_VERSION=0 +DB_SCHEMA_VERSION=3 + +# RPC Configuration +# Required for mainnet/sepolia. Not needed for devnet. +# You must use private (paid) RPC endpoints — public endpoints are too slow. +# +# Option 1: Auto-generate RPC URLs via provider API keys +# ALCHEMY_API_KEY= +# QUICKNODE_API_KEY= +# QUICKNODE_ENDPOINT_NAME= +# DRPC_API_KEY= +# +# Option 2: Explicit per-chain RPC URLs (takes precedence over auto-generated) +# See apps/ensindexer/.env.local.example for the full list of chain IDs. +# RPC_URL_1=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY +# RPC_URL_10= +# RPC_URL_8453= +# RPC_URL_42161= +# RPC_URL_59144= +# RPC_URL_534352= diff --git a/docker/services/devnet.yml b/docker/services/devnet.yml new file mode 100644 index 000000000..ba16e19b4 --- /dev/null +++ b/docker/services/devnet.yml @@ -0,0 +1,17 @@ +services: + devnet: + container_name: devnet + image: ghcr.io/ensdomains/contracts-v2:main-e8696c6 + command: ./script/runDevnet.ts --testNames + pull_policy: always + ports: + - "8545:8545" + environment: + ANVIL_IP_ADDR: "0.0.0.0" + healthcheck: + test: ["CMD", "curl", "--fail", "-s", "http://localhost:8000/health"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + start_interval: 1s diff --git a/docker/services/ensadmin.yml b/docker/services/ensadmin.yml new file mode 100644 index 000000000..fbc0fd542 --- /dev/null +++ b/docker/services/ensadmin.yml @@ -0,0 +1,9 @@ +services: + ensadmin: + container_name: ensadmin + image: ghcr.io/namehash/ensnode/ensadmin:latest + build: + dockerfile: ./apps/ensadmin/Dockerfile + context: ../.. + ports: + - "4173:4173" diff --git a/docker/services/ensapi.yml b/docker/services/ensapi.yml new file mode 100644 index 000000000..71ce5c7d3 --- /dev/null +++ b/docker/services/ensapi.yml @@ -0,0 +1,16 @@ +services: + ensapi: + container_name: ensapi + image: ghcr.io/namehash/ensnode/ensapi:latest + build: + dockerfile: ./apps/ensapi/Dockerfile + context: ../.. + ports: + - "4334:4334" + healthcheck: + test: ["CMD", "curl", "--fail", "-s", "http://localhost:4334/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 1m + start_interval: 1s diff --git a/docker/services/ensindexer.yml b/docker/services/ensindexer.yml new file mode 100644 index 000000000..ac472ddaf --- /dev/null +++ b/docker/services/ensindexer.yml @@ -0,0 +1,16 @@ +services: + ensindexer: + container_name: ensindexer + image: ghcr.io/namehash/ensnode/ensindexer:latest + build: + dockerfile: ./apps/ensindexer/Dockerfile + context: ../.. + ports: + - "42069:42069" + healthcheck: + test: ["CMD", "curl", "--fail", "-s", "http://localhost:42069/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5m + start_interval: 1s diff --git a/docker/services/ensrainbow.yml b/docker/services/ensrainbow.yml new file mode 100644 index 000000000..5e1c3c726 --- /dev/null +++ b/docker/services/ensrainbow.yml @@ -0,0 +1,19 @@ +services: + ensrainbow: + container_name: ensrainbow + image: ghcr.io/namehash/ensnode/ensrainbow:latest + build: + dockerfile: ./apps/ensrainbow/Dockerfile + context: ../.. + ports: + - "3223:3223" + volumes: + - ensrainbow_data:/app/apps/ensrainbow/data + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "-q", "--spider", "http://localhost:3223/health"] + interval: 30s + timeout: 3s + retries: 3 + start_period: 35m + start_interval: 1s diff --git a/docker/services/postgres.yml b/docker/services/postgres.yml new file mode 100644 index 000000000..85f0f12b2 --- /dev/null +++ b/docker/services/postgres.yml @@ -0,0 +1,14 @@ +services: + postgres: + container_name: postgres + image: postgres:17 + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 5s + retries: 5 + start_period: 10s diff --git a/docs/ensnode.io/ensapi-openapi.json b/docs/ensnode.io/ensapi-openapi.json index e4496ea1a..2e27b8e27 100644 --- a/docs/ensnode.io/ensapi-openapi.json +++ b/docs/ensnode.io/ensapi-openapi.json @@ -2,7 +2,7 @@ "openapi": "3.1.0", "info": { "title": "ENSApi APIs", - "version": "1.9.0", + "version": "1.10.0", "description": "APIs for ENS resolution, navigating the ENS nameforest, and metadata about an ENSNode" }, "servers": [ diff --git a/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx b/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx index fce21e875..36f271bf2 100644 --- a/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx +++ b/docs/ensnode.io/src/content/docs/docs/contributing/index.mdx @@ -40,12 +40,12 @@ pnpm install ## Running ENSNode :::note -ENSNode is a suite of services, and some depend on others. Refer to the `docker-compose.yml` at the root of the monorepo for a full spec on the relationship between services. +ENSNode is a suite of services, and some depend on others. Refer to the `docker/docker-compose.yml` in the docker directory for a full spec on the relationship between services. ::: @@ -132,32 +132,46 @@ Before you can use Docker Compose, ensure you have the following installed on yo ### Building the Docker Images -Before running `docker compose` the images must be build with the latest changes: see the [Building Docker Images](/ensnode/contributing/building) guide. +Before running `docker compose` the images must be built with the latest changes: see the [Building Docker Images](/ensnode/contributing/building) guide. If you make changes in the application code and wish to run those updates, you must build the relevant Docker container again. ### Running the Applications -Run the built images with: +For local development, use the devnet stack — no environment setup required: ```bash -docker compose up -d +docker compose -f docker/docker-compose.devnet.yml up -d +``` + +For mainnet/sepolia, first configure your environment: + +```bash +cp docker/envs/.env.docker.example docker/envs/.env.docker.local +``` + +Edit `docker/envs/.env.docker.local` to set `NAMESPACE`, `PLUGINS`, and your RPC endpoints, then run: + +```bash +docker compose -f docker/docker-compose.yml up -d ``` - **ENSIndexer**: Available at [http://localhost:42069](http://localhost:42069) -- **ENSApi**: Available at [http://localhost:42069](http://localhost:4334) +- **ENSApi**: Available at [http://localhost:4334](http://localhost:4334) - **ENSRainbow**: Available at [http://localhost:3223](http://localhost:3223) - **ENSAdmin**: Available at [http://localhost:4173](http://localhost:4173) - **PostgreSQL**: Available on port `5432` +For all available commands and configuration options, see the [Deploying with Docker](/ensnode/deploying/docker) guide and [`docker/README.md`](https://github.com/namehash/ensnode/blob/main/docker/README.md). + ### Stopping the Applications -To stop the running applications, you can press `Ctrl + C` in the terminal where Docker Compose is running. If you want to remove the containers and networks created by Docker Compose, you can run: +To stop the running applications, you can press `Ctrl + C` in the terminal where Docker Compose is running. To remove the containers and networks: ```bash -docker compose down +docker compose -f docker/docker-compose.yml down ``` -:::note[Postgres Volume in this `docker-compose.yml`] -`docker compoe down` will _not_ delete the Postgres data volume defined here, as it is a **named** volume. To fully delete the Postgres data volume and start from scratch, use `docker compose down -v`. +:::note[Postgres Volume] +`docker compose down` will _not_ delete the Postgres data volume, as it is a **named** volume. To fully delete it and start from scratch, use `docker compose -f docker/docker-compose.yml down -v`. ::: diff --git a/docs/ensnode.io/src/content/docs/docs/deploying/docker.mdx b/docs/ensnode.io/src/content/docs/docs/deploying/docker.mdx index 88f159aa3..46196b1e2 100644 --- a/docs/ensnode.io/src/content/docs/docs/deploying/docker.mdx +++ b/docs/ensnode.io/src/content/docs/docs/deploying/docker.mdx @@ -6,8 +6,6 @@ sidebar: --- import { LinkCard } from '@astrojs/starlight/components'; -import { Code } from '@astrojs/starlight/components'; -import dockercompose from '@workspace/docker-compose.yml?raw'; The Docker images are the easiest way to run or deploy the ENSNode suite of services, both locally and in the cloud. @@ -20,16 +18,49 @@ ENSIndexer runs `CREATE EXTENSION IF NOT EXISTS pg_trgm` at startup to back part href="/ensindexer/usage/configuration" /> -Below is a sample [Docker Compose](https://docs.docker.com/compose/) file linking the various services together. +ENSNode provides several [Docker Compose](https://docs.docker.com/compose/) files for different use cases: - +- **`docker/docker-compose.yml`** — base stack for mainnet/sepolia: ensindexer, ensapi, ensrainbow, ensadmin, postgres +- **`docker/docker-compose.devnet.yml`** — full stack against local devnet (ens-test-env), works out of the box with no configuration required + +### Mainnet / Sepolia + +Copy the example env file and configure it: + +```bash +cp docker/envs/.env.docker.example docker/envs/.env.docker.local +``` + +Edit `docker/envs/.env.docker.local` to set your `NAMESPACE`, `PLUGINS`, and RPC endpoints (e.g. `ALCHEMY_API_KEY` or `RPC_URL_1`), then run: + +```bash +docker compose -f docker/docker-compose.yml up -d +``` + + +### Local devnet + +Configuration is optional. To customize defaults (e.g. change `PLUGINS`), copy the example as in previous step and edit it. + +Otherwise, skip setup and run directly: + +```bash +docker compose -f docker/docker-compose.devnet.yml up -d +``` + + + :::note[Port Mappings] -Note that while this example `docker-compose.yml` exposes each container's port to the host machine, useful for development, you may only wish to expose ENSApi's `4334` and avoid exposing services like ENSRainbow, ENSAdmin, and your Postgres to the wider internet. +Note that while the default `docker/docker-compose.yml` exposes each container's port to the host machine (useful for development), you may only wish to expose ENSApi's `4334` and avoid exposing services like ENSRainbow, ENSAdmin, and Postgres to the wider internet. ::: diff --git a/package.json b/package.json index bacf366d6..67fe706bc 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "changeset-publish": "changeset publish", "changeset-publish:next": "changeset publish --no-git-tag --snapshot --tag next", "packages:prepublish": "pnpm -r prepublish", - "devnet": "docker compose up devnet", + "devnet": "docker compose -f docker/docker-compose.devnet.yml up devnet", "docker:build:ensnode": "pnpm run -w --parallel \"/^docker:build:.*/\"", "docker:build:ensindexer": "docker build -f apps/ensindexer/Dockerfile -t ghcr.io/namehash/ensnode/ensindexer:latest .", "docker:build:ensadmin": "docker build -f apps/ensadmin/Dockerfile -t ghcr.io/namehash/ensnode/ensadmin:latest .", diff --git a/packages/integration-test-env/README.md b/packages/integration-test-env/README.md index 92de243d9..2d90daf5b 100644 --- a/packages/integration-test-env/README.md +++ b/packages/integration-test-env/README.md @@ -10,7 +10,7 @@ The current devnet image is pinned to: ghcr.io/ensdomains/contracts-v2:main-e8696c6 ``` -via the `docker-compose.yml` at the monorepo root. +via the `docker/docker-compose.orchestrator.yml` file. ## How It Works @@ -40,7 +40,7 @@ When developing, it's useful to run each service individually so you can restart #### 1. Start the devnet ```sh -docker compose up devnet +pnpm devnet ``` Runs the ENS contracts-v2 devnet on port 8545. @@ -56,7 +56,7 @@ brew services start postgresql@17 or with the local docker compose: ```sh -docker compose up postgres +docker compose -f docker/docker-compose.yml up postgres ``` #### 3. Start ENSRainbow @@ -64,7 +64,7 @@ docker compose up postgres Run via docker compose: ```sh -docker compose up ensrainbow +docker compose -f docker/docker-compose.yml up ensrainbow ``` Or run it on the host machine from the repo root: diff --git a/packages/integration-test-env/src/orchestrator.ts b/packages/integration-test-env/src/orchestrator.ts index 99df9f5f4..17e2a72d5 100644 --- a/packages/integration-test-env/src/orchestrator.ts +++ b/packages/integration-test-env/src/orchestrator.ts @@ -12,7 +12,7 @@ * 5. Run `pnpm test:integration` at the monorepo root * * Design decisions: - * - Postgres and devnet are started from the root docker-compose.yml via + * - Postgres and devnet are started from docker/docker-compose.orchestrator.yml via * testcontainers DockerComposeEnvironment, ensuring the orchestrator always * uses the same images and configuration defined there. * - execa for child process management — automatic cleanup on parent exit, @@ -42,6 +42,7 @@ import { ENSNamespaceIds } from "@ensnode/datasources"; import { OmnichainIndexingStatusIds } from "@ensnode/ensnode-sdk"; const MONOREPO_ROOT = resolve(import.meta.dirname, "../../.."); +const DOCKER_DIR = resolve(MONOREPO_ROOT, "docker"); const ENSRAINBOW_DIR = resolve(MONOREPO_ROOT, "apps/ensrainbow"); const ENSINDEXER_DIR = resolve(MONOREPO_ROOT, "apps/ensindexer"); const ENSAPI_DIR = resolve(MONOREPO_ROOT, "apps/ensapi"); @@ -238,7 +239,10 @@ async function main() { // Phase 1: Start Postgres + Devnet via docker-compose log("Starting Postgres and devnet..."); - composeEnvironment = await new DockerComposeEnvironment(MONOREPO_ROOT, "docker-compose.yml") + composeEnvironment = await new DockerComposeEnvironment( + DOCKER_DIR, + "docker-compose.orchestrator.yml", + ) .withWaitStrategy("devnet", Wait.forHealthCheck()) .withWaitStrategy("postgres", Wait.forListeningPorts()) .withStartupTimeout(120_000)