Deploying with Docker
Relevant source files
The following files were used as context for generating this wiki page:gr8hopper provides a lightweight and portable deployment option using Docker, making it easy to run the service on any Virtual Private Server (VPS) or machine with Docker installed. This method is presented as an alternative to the edge deployment on Cloudflare Workers and is ideal for self-hosted environments. The Docker image is built on a minimal node:20-alpine base to ensure a small footprint.
This document covers the architecture of the Docker container, configuration via environment variables, data persistence strategies, and recommended deployment patterns using both docker run and docker-compose.
Sources: README.md:20-22, README.md:329-331, README.md:364-366
Deployment Methods
There are two primary ways to deploy gr8hopper using Docker: a quick-start docker run command for simple setups, and a more robust docker-compose method for production environments.
Sources: README.md:83, README.md:370
Quick Start with docker run
The easiest way to get gr8hopper running is with a single docker run command. This pulls the latest pre-built image from ghcr.io, sets the required environment variables, maps the port, and configures a named volume for data persistence.
docker run -d --restart unless-stopped \
-p 3000:3000 \
-e ADMIN_USERNAME=your-username \
-e ADMIN_PASSWORD=your-secure-password \
-v gr8hopper-data:/app/data \
--name gr8hopper \
ghcr.io/dima6312/gr8hopper:latest
Sources: README.md:84-91
This command performs the following actions:
-d: Runs the container in detached mode.--restart unless-stopped: Ensures the container restarts automatically unless manually stopped.-p 3000:3000: Maps port 3000 on the host to port 3000 in the container.-e ...: Sets the mandatory admin credentials.-v gr8hopper-data:/app/data: Creates a named volumegr8hopper-dataand mounts it to/app/datainside the container, where theroutes.jsonfile is stored.
Sources: README.md:84-91, examples/docker-compose.yml:12-13, examples/docker-compose.yml:18-20
Recommended: docker-compose
For a more declarative and manageable setup, using docker-compose is recommended. The project provides an example docker-compose.yml file that defines the service, environment, volumes, and a healthcheck.
Sources: README.md:370-372, examples/docker-compose.yml
The following diagram illustrates the components managed by Docker Compose.
This diagram shows a user request hitting the host, which forwards it to the container. The Node.js server inside reads and writes its configuration to a file that is persisted on the host via a named Docker volume.
Sources: examples/docker-compose.yml:6-7, examples/docker-compose.yml:12, examples/docker-compose.yml:18-20
Service Definition
The docker-compose.yml file defines the gr8hopper service with key configurations:
services:
gr8hopper:
build:
context: ..
dockerfile: examples/Dockerfile
container_name: gr8hopper
ports:
- "3000:3000"
environment:
- ADMIN_USERNAME=${ADMIN_USERNAME:?ADMIN_USERNAME is required}
- ADMIN_PASSWORD=${ADMIN_PASSWORD:?ADMIN_PASSWORD is required}
- CONFIG_FILE=/app/data/routes.json
- ADMIN_PATH=${ADMIN_PATH:-admin}
- PORT=3000
volumes:
- gr8hopper-data:/app/data
restart: unless-stopped
healthcheck:
test: [ "CMD", "node", "-e", "fetch('http://localhost:3000/health').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))" ]
interval: 30s
timeout: 10s
retries: 3
volumes:
gr8hopper-data:
Note: The healthcheck in README.md differs slightly from examples/docker-compose.yml, checking / instead of /health because the /health endpoint was removed.
Sources: examples/docker-compose.yml:1-26, README.md:393-398
Container Architecture
The gr8hopper Docker image is constructed using a multi-stage build to create a minimal and secure production artifact.
Sources: README.md:332-362
Multi-Stage Dockerfile
The build process is split into two stages: builder and runner.
builderStage: This stage uses a fullnode:20-alpineimage to install all dependencies (includingdevDependencies) and build the TypeScript source code into JavaScript.runnerStage: This stage starts from a freshnode:20-alpineimage, installs only production dependencies (--omit=dev), and copies the builtdistdirectory from thebuilderstage. It also creates a non-root usergr8hopperto run the application, enhancing security.
Sources: README.md:333-362
The following diagram visualizes the multi-stage build process.
This flow shows the builder stage preparing the application build, and the runner stage creating a lean, production-ready image by copying only the necessary artifacts and setting up a secure runtime environment.
Sources: README.md:333-362, package.json:13
Server Entrypoint
The container's final command is CMD ["node", "dist/server.js"]. This executes the Node.js server entrypoint, which is compiled from src/server.ts.
This server script is responsible for:
- Reading environment variables.
- Initializing the
JsonFileAdapterfor storage. - Creating and configuring a
Honoweb server instance. - Setting up authentication middleware for the admin panel.
- Serving the admin UI and API endpoints.
- Handling public redirect requests.
Sources: README.md:361, src/server.ts, package.json:13
The server startup sequence within the container is as follows:
This sequence shows how the server.ts script orchestrates the application startup, from configuration validation to starting the web server.
Sources: src/server.ts:8-193
Configuration
Configuration for the Docker deployment is managed exclusively through environment variables.
Sources: README.md:215-223, examples/docker-compose.yml:8-14
Environment Variables
The following variables are used to configure the gr8hopper container.
| Variable | Required | Default | Description | Source Files |
|---|---|---|---|---|
ADMIN_USERNAME | Yes | - | The username for the admin panel. Cannot be 'admin'. | src/server.ts:98-106, src/server.ts:119-128 |
ADMIN_PASSWORD | Yes | - | The password for the admin panel. | src/server.ts:107-117 |
PORT | No | 3000 | The port the internal Node.js server listens on. | src/server.ts:89, examples/docker-compose.yml:14 |
CONFIG_FILE | No | ./routes.json | Path inside the container to the routes JSON file. | src/server.ts:90, examples/docker-compose.yml:12 |
ADMIN_PATH | No | admin | The URL path for the admin panel (e.g., /admin). | src/server.ts:91, examples/docker-compose.yml:13 |
Sources: README.md:215-223, src/server.ts:89-128, examples/docker-compose.yml:8-14
Data Persistence
In a Docker deployment, routes and settings are stored in a local JSON file specified by the CONFIG_FILE environment variable. To prevent data loss when the container is removed or recreated, this file must be stored on a persistent volume.
The recommended approach is to use a named Docker volume (gr8hopper-data), which is mounted into the container at /app/data. The CONFIG_FILE variable is then set to /app/data/routes.json.
This diagram shows the application inside the container writing to a file path, which is actually a mount point for a persistent volume on the host, ensuring data survives container restarts.
Sources: README.md:88, README.md:318-322, examples/docker-compose.yml:12, examples/docker-compose.yml:18-20
Security
When deploying with Docker, several security measures are crucial:
- Mandatory Credentials: The server will fail to start if
ADMIN_USERNAMEorADMIN_PASSWORDare not provided. - Non-Root User: The container runs the application as the
gr8hopperuser, notroot, reducing the potential impact of a container compromise. - HTTPS: The Node.js server does not handle HTTPS. It is strongly recommended to place the container behind a reverse proxy like Nginx or Caddy to terminate SSL/TLS and add security headers.
- Admin Path: Change the
ADMIN_PATHto a non-standard value to make the admin panel harder to find for automated scanners.
Sources: src/server.ts:98-117, README.md:351-354, README.md:430-432, SECURITY.md:21-24