9ad43aa8b2
* Add GHCR and Docker Hub image publishing with fully runtime-configurable pull-first Docker setup (#1) * feat: add container image publishing workflow and pull-based compose setup Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/23c31167-9e15-4d44-ab89-f267b8cd6304 * refine docker publishing workflow and pull-first compose docs Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/23c31167-9e15-4d44-ab89-f267b8cd6304 * chore: temporarily expose docker publish run results for pr branch Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/c946a2f2-2219-4dea-a829-61b287bc4859 * fix: update pinned SHAs for setup-qemu-action and setup-buildx-action to v3 heads Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/0db6957e-476b-48e0-acf3-bee6964c3b32 Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> * chore: switch all workflow action refs from SHA pins to stable version tags Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/19334b37-9b4c-45df-9c3c-81a497cef8e8 Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> * fix: restore missing `with:` blocks lost during SHA-to-tag substitution Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/f204f742-5b7d-4f05-9647-03b9db86ea3d Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> * fix(ci): checkout submodules for docker image workflow Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/72309e8a-6c7c-4004-902a-565f67e5c15f Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * feat(docker): support runtime client env for pulled web image * refactor(web): serve runtime config via script endpoint * fix(web): escape runtime config script payload * fix: align docker runtime config with internal/public backend urls Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/3bbcb608-6202-4f9e-b288-5c95a259da93 Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> * chore: align published workflow tags with docs * docs: clarify runtime config precedence and linux host mapping Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/3bbcb608-6202-4f9e-b288-5c95a259da93 * refactor: move storage/quota config from build args to runtime env Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/da9b749e-0b1c-47b9-b474-5009765b6ea6 Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> * fix: load runtime config in pages router app shell Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/b375132c-8317-4c98-b437-ae48c0153e3d Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> * fix: apply biome formatting for runtime config quota helpers Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/778f5d75-884e-401b-b7cb-4ab40bc64a11 Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> Co-authored-by: Amir Pourmand <pourmand1376@gmail.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: S3_PUBLIC_ENDPOINT, _document.tsx for beforeInteractive, runtimeConfig fallbacks, README port (#2) Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/4f92f818-c008-4caa-9684-d530500b5fb2 Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> * fix: reformat runtimeConfig.ts to satisfy biome formatter (#3) Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/4eea77f4-67ab-4428-b59e-0b21be988037 Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: pourmand1376 <32064808+pourmand1376@users.noreply.github.com> --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
149 lines
4.9 KiB
Markdown
149 lines
4.9 KiB
Markdown
# Self-Hosting with Docker/Podman with Compose
|
|
|
|
## Stack
|
|
|
|
| service | Image | Description |
|
|
| --------------- | --------------------------- | ------------------------------------------------- |
|
|
| **client** | `ghcr.io/readest/readest` | readest frontend |
|
|
| **db** | `supabase/postgres` | psql db with supabase extensions |
|
|
| **kong** | `kong:2.8.1` | api gateway routing requests to supabase services |
|
|
| **auth** | `supabase/gotrue:v2.185.0` | auth service (email, JWT) |
|
|
| **rest** | `postgrest/postgrest:v14.3` | psql rest api |
|
|
| **minio** | `minio/minio` | s3 storage |
|
|
| **minio-setup** | `minio/mc` | helper container to create s3 buckets |
|
|
|
|
### Exposed ports
|
|
|
|
| Port | Service |
|
|
| ------ | ---------------- |
|
|
| `3000` | readest |
|
|
| `8000` | kong API gateway |
|
|
| `9000` | MinIO S3 API |
|
|
| `9001` | MinIO console UI |
|
|
|
|
---
|
|
|
|
## Running with Docker/Podman Compose
|
|
|
|
### 1. setup .env
|
|
|
|
```bash
|
|
cp docker/.env.example docker/.env
|
|
```
|
|
|
|
update `docker/.env`:
|
|
|
|
- update `POSTGRES_PASSWORD` to a strong password (32+ chars)
|
|
- update `JWT_SECRET` to a random secret (32+ chars)
|
|
- regenerate `ANON_KEY` and `SERVICE_ROLE_KEY` as HS256 JWTs signed with your `JWT_SECRET` (use [jwt.io](https://jwt.io/) or a similar tool):
|
|
- `ANON_KEY` payload: `{"role": "anon"}`
|
|
- `SERVICE_ROLE_KEY` payload: `{"role": "service_role"}`
|
|
- set `MINIO_ROOT_PASSWORD` to a strong password
|
|
|
|
### 2. Start the Stack (pull prebuilt client image)
|
|
|
|
run from the `docker/` directory:
|
|
|
|
```bash
|
|
cd docker
|
|
docker compose up -d
|
|
```
|
|
|
|
this pulls `${READEST_IMAGE}` (default: `ghcr.io/readest/readest:latest`) instead of building the client locally.
|
|
the web client now reads `SUPABASE_PUBLIC_URL`, `SUPABASE_ANON_KEY`, `API_BASE_URL`, `OBJECT_STORAGE_TYPE`, `STORAGE_FIXED_QUOTA`, and `TRANSLATION_FIXED_QUOTA` from runtime
|
|
container env, so custom self-hosted values work with pulled images.
|
|
|
|
if you prefer Docker Hub, set `READEST_IMAGE` in `docker/.env`, for example:
|
|
|
|
```env
|
|
READEST_IMAGE=docker.io/your-dockerhub-username/readest:latest
|
|
```
|
|
|
|
replace `your-dockerhub-username` with the Docker Hub namespace that publishes your `readest` image.
|
|
for official images, use the namespace configured for this repository's Docker Hub publishing secrets.
|
|
|
|
published tags:
|
|
- `latest`: published from release events
|
|
- `<release-tag>` (for example `v1.2.3`): published from release events
|
|
- `main`: rolling image from the default branch
|
|
- `sha-<commit>`: immutable commit tag
|
|
|
|
### Build locally instead of pulling
|
|
|
|
```bash
|
|
cd docker
|
|
docker compose -f compose.yaml -f compose.build.yaml up --build -d
|
|
```
|
|
|
|
### 3. Access
|
|
|
|
- Readest app: `http://localhost:3000`
|
|
- MinIO console: `http://localhost:9001` (login with `MINIO_ROOT_USER` / `MINIO_ROOT_PASSWORD`)
|
|
|
|
### Hot Reload (development)
|
|
|
|
to develop using the compose stack, use local builds (`compose.yaml` + `compose.build.yaml`) and set the build target on `client` to `development-stage` in `compose.build.yaml`, which runs the next.js dev server. to enable hot reload, uncomment the `volumes` block in the `client` service in `compose.yaml`:
|
|
|
|
```yaml
|
|
volumes:
|
|
- ../:/app
|
|
- /app/node_modules
|
|
- /app/apps/readest-app/node_modules
|
|
- /app/apps/readest-app/public/vendor
|
|
- /app/apps/readest-app/.next
|
|
- /app/packages/foliate-js/node_modules
|
|
```
|
|
|
|
the first mount overlays your local repo into the container. the remaining anonymous volumes shadow the directories that were pre-built inside the image, so the container's installed deps and vendor assets are used instead of what's on your host.
|
|
|
|
### Stop the Stack
|
|
|
|
```bash
|
|
cd docker
|
|
docker compose down
|
|
```
|
|
|
|
to also remove volumes (database and storage data):
|
|
|
|
```bash
|
|
cd docker
|
|
docker compose down -v
|
|
```
|
|
|
|
---
|
|
|
|
## Building the Dockerfile standalone
|
|
|
|
```bash
|
|
docker build \
|
|
--target production-stage \
|
|
--build-arg NEXT_PUBLIC_APP_PLATFORM=web \
|
|
-t readest-client \
|
|
.
|
|
```
|
|
|
|
run the built image:
|
|
|
|
```bash
|
|
docker run -p 3000:3000 \
|
|
-e SUPABASE_URL=http://host.docker.internal:8000 \
|
|
-e SUPABASE_PUBLIC_URL=http://localhost:8000 \
|
|
-e SUPABASE_ANON_KEY=<anon-key> \
|
|
-e SUPABASE_ADMIN_KEY=<service-role-key> \
|
|
-e API_BASE_URL=http://localhost:3000 \
|
|
-e OBJECT_STORAGE_TYPE=s3 \
|
|
-e S3_ENDPOINT=http://host.docker.internal:9000 \
|
|
-e S3_PUBLIC_ENDPOINT=http://localhost:9000 \
|
|
-e S3_REGION=us-east-1 \
|
|
-e S3_BUCKET_NAME=readest-files \
|
|
-e S3_ACCESS_KEY_ID=<minio-user> \
|
|
-e S3_SECRET_ACCESS_KEY=<minio-password> \
|
|
-e STORAGE_FIXED_QUOTA=1073741824 \
|
|
-e TRANSLATION_FIXED_QUOTA=50000 \
|
|
readest-client
|
|
```
|
|
|
|
on Linux, some Docker setups do not resolve `host.docker.internal` by default.
|
|
in that case, either replace it with your host IP or run with:
|
|
`--add-host=host.docker.internal:host-gateway`.
|