mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-07-04 02:21:56 +00:00
resolver: dockerize
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
# ---------- builder ----------
|
||||
# Use the official uv image (Astral) on top of a slim Python base.
|
||||
# uv resolves and installs the lockfile-free pyproject.toml in seconds and
|
||||
# produces a portable .venv we can copy into the runtime stage.
|
||||
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS builder
|
||||
|
||||
ENV UV_LINK_MODE=copy \
|
||||
UV_COMPILE_BYTECODE=1 \
|
||||
UV_PYTHON_DOWNLOADS=never \
|
||||
UV_NO_PROGRESS=1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install deps first (separate layer) — script edits won't bust this cache.
|
||||
COPY pyproject.toml ./
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --no-dev --no-install-project
|
||||
|
||||
# Script is added after the dep layer for cache friendliness.
|
||||
COPY snrc-resolve.py ./
|
||||
|
||||
# ---------- runtime ----------
|
||||
# Slim runtime — only the venv + script. No uv, no apt.
|
||||
FROM python:3.13-slim AS runtime
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
PATH="/app/.venv/bin:$PATH"
|
||||
|
||||
# Non-root user (matches resolver privacy posture: it has no need for root).
|
||||
RUN groupadd --system --gid 10001 snrc && \
|
||||
useradd --system --uid 10001 --gid snrc --no-create-home --shell /usr/sbin/nologin snrc
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder --chown=snrc:snrc /app /app
|
||||
|
||||
USER snrc:snrc
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
# Liveness check hits the script's own /health route. ThreadingHTTPServer is
|
||||
# fast enough that 3s is generous for a localhost probe; restart if it stops
|
||||
# responding entirely.
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD ["python", "-c", "import urllib.request, sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=3).status == 200 else 1)"]
|
||||
|
||||
ENTRYPOINT ["python", "snrc-resolve.py"]
|
||||
@@ -52,10 +52,21 @@ Registry (SNRC) over a small JSON HTTP API. It talks to the same local
|
||||
Reth + Nimbus stack described above (set `NETWORK=mainnet` in `.env`),
|
||||
reading the SNRC contracts directly on Ethereum mainnet.
|
||||
|
||||
Install the only runtime dependency (same as `ens-lookup.py`):
|
||||
Dependencies are declared inline (PEP 723) at the top of `snrc-resolve.py`
|
||||
and in a sibling `pyproject.toml`. The simplest local run uses
|
||||
[`uv`](https://docs.astral.sh/uv/):
|
||||
|
||||
```sh
|
||||
pip install --break-system-packages 'eth-hash[pycryptodome]'
|
||||
uv run scripts/resolver/snrc-resolve.py
|
||||
```
|
||||
|
||||
`uv` resolves and caches `eth-hash[pycryptodome]` on first run. No
|
||||
virtualenv juggling, no `--break-system-packages`. If you'd rather
|
||||
manage Python deps yourself:
|
||||
|
||||
```sh
|
||||
pip install 'eth-hash[pycryptodome]>=0.7'
|
||||
python scripts/resolver/snrc-resolve.py
|
||||
```
|
||||
|
||||
### Deployed registries
|
||||
@@ -93,6 +104,38 @@ snrc-resolve listening on 0.0.0.0:8000
|
||||
|
||||
Override the listen port or bind address with `SNRC_PORT` / `SNRC_BIND`.
|
||||
|
||||
### Running in Docker
|
||||
|
||||
The compose file ships a `resolver` service alongside reth and nimbus.
|
||||
`docker compose up -d` builds the image from `Dockerfile` (multi-stage,
|
||||
non-root, `uv`-based) and exposes the API on `127.0.0.1:8000`:
|
||||
|
||||
```sh
|
||||
docker compose up -d resolver
|
||||
docker compose logs -f resolver
|
||||
curl -s http://127.0.0.1:8000/health
|
||||
```
|
||||
|
||||
The container points `SNRC_RPC` at `http://reth:8545` (the compose-internal
|
||||
DNS name) so the resolver and reth share the bridge network without
|
||||
exposing reth's RPC to the host beyond loopback.
|
||||
|
||||
To change the host-side port, edit the LEFT side of the port mapping in
|
||||
`docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
resolver:
|
||||
ports:
|
||||
- "127.0.0.1:8000:8000" # host:container
|
||||
```
|
||||
|
||||
The registry address defaults to mainnet `.testing` — to override (Holesky,
|
||||
a private deployment, or future `.simplex`), uncomment and set the values
|
||||
in `docker-compose.yml` under the resolver service's `environment:` block.
|
||||
|
||||
The image declares a `HEALTHCHECK` against `/health`; `docker compose ps`
|
||||
will mark the service `(healthy)` once reth is queryable.
|
||||
|
||||
### Resolving a name
|
||||
|
||||
`foobar.testing` is registered on mainnet with every text and
|
||||
|
||||
@@ -127,6 +127,34 @@ services:
|
||||
--nat=${NAT:-any}
|
||||
restart: unless-stopped
|
||||
|
||||
# SNRC REST resolver. Talks to reth on the compose-internal network,
|
||||
# exposes /resolve and /health on 127.0.0.1:8000 by default. The
|
||||
# smp-server points its [NAMES] resolver_endpoint at this URL.
|
||||
# To change the host port, edit the LEFT side of the port mapping below.
|
||||
resolver:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
depends_on:
|
||||
# reth's `service_started` is sufficient — the resolver tolerates
|
||||
# eth_call failures gracefully (returns 502 with the error body), so
|
||||
# starting before reth has finished snapshot replay just yields a few
|
||||
# 502s until the chain is queryable. The upstream reth image doesn't
|
||||
# ship a HEALTHCHECK, so we can't gate on healthy.
|
||||
reth:
|
||||
condition: service_started
|
||||
environment:
|
||||
SNRC_RPC: http://reth:8545
|
||||
SNRC_BIND: 0.0.0.0
|
||||
# Registry addresses cascade through the script's own defaults
|
||||
# (mainnet `.testing`; `.simplex` unconfigured). Set explicitly here
|
||||
# only if you're deploying against a different network or contract.
|
||||
# SNRC_REGISTRY_TESTING: 0x...
|
||||
# SNRC_REGISTRY_SIMPLEX: 0x...
|
||||
ports:
|
||||
- "127.0.0.1:8000:8000"
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
reth-data:
|
||||
nimbus-data:
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[project]
|
||||
name = "snrc-resolve"
|
||||
version = "0.1.0"
|
||||
description = "SimpleX Namespace (SNRC) resolver — REST API over ENS-shaped Ethereum registries"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
license = "AGPL-3.0-only"
|
||||
dependencies = [
|
||||
"eth-hash[pycryptodome]>=0.7",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
package = false
|
||||
@@ -1,4 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
# /// script
|
||||
# requires-python = ">=3.11"
|
||||
# dependencies = [
|
||||
# "eth-hash[pycryptodome]>=0.7",
|
||||
# ]
|
||||
# ///
|
||||
"""SimpleX Namespace (SNRC) resolver — REST API.
|
||||
|
||||
Resolves names like `alice.testing` / `bob.simplex` against the SNRC
|
||||
@@ -33,8 +39,9 @@ Environment:
|
||||
Each TLD is a separate SNRC deployment with its own ENSRegistry; the
|
||||
resolver dispatches by the queried name's rightmost label.
|
||||
|
||||
Same dependency surface as ens-lookup.py:
|
||||
pip install --break-system-packages 'eth-hash[pycryptodome]'
|
||||
Dependencies are declared inline (PEP 723) at the top of this file. Run with:
|
||||
uv run snrc-resolve.py # uv resolves & caches deps; one-line setup
|
||||
python snrc-resolve.py # if eth-hash[pycryptodome] is already installed
|
||||
|
||||
Addresses are returned in each chain's canonical presentation:
|
||||
eth EIP-55 mixed-case checksummed hex (e.g. 0xEa65A0…1572)
|
||||
@@ -62,11 +69,13 @@ PORT = int(os.environ.get("SNRC_PORT", "8000"))
|
||||
# Each TLD is its own SNRC deployment with its own ENSRegistry. Dispatch
|
||||
# happens on the rightmost label of the queried name. Empty / unset means
|
||||
# "not deployed" — requests for that TLD return 400 with a clear error.
|
||||
# `... or "..."` makes the script's defaults the single source of truth:
|
||||
# unset AND empty-string both fall through to the literal. docker-compose
|
||||
# can therefore pass `SNRC_REGISTRY_TESTING=${SNRC_REGISTRY_TESTING:-}`
|
||||
# without duplicating the registry address.
|
||||
REGISTRIES = {
|
||||
"testing": os.environ.get(
|
||||
"SNRC_REGISTRY_TESTING",
|
||||
"0x03f438da0bd44da3c6c1d0392f8ba183b8b3a7a6", # mainnet .testing
|
||||
),
|
||||
"testing": os.environ.get("SNRC_REGISTRY_TESTING", "")
|
||||
or "0x03f438da0bd44da3c6c1d0392f8ba183b8b3a7a6", # mainnet .testing
|
||||
"simplex": os.environ.get("SNRC_REGISTRY_SIMPLEX", ""), # not deployed yet
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user