fix(docker): fix Docker image latest tag and production runtime errors; add dev compose file, Codespace support, and semver release tagging (#7) (#4277)

* fix: also tag Docker image as latest on main branch push

Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/bbc0f66e-7488-4d9d-976b-434588b3faa8



* fix: production Dockerfile missing patches/.env.web; add compose.dev.yaml for dev hot-reload

Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/e27bba4e-b8ea-4694-b44d-6308aa778d41



* fix: add devcontainer to init submodules; add clear Dockerfile error when submodules missing

Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/16d24ae0-d2e8-4523-b47e-4969dd587c50



* simplify production-stage: COPY --from=build /app /app instead of selective copies

Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/356fabe4-f944-48b6-a409-41640480d52f



* fix: add CI=true to dev compose to prevent pnpm no-TTY abort

Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/ddc30fef-2c76-452d-aad6-d688ca912a1a



* fix: add semver Docker image version tags on release

Agent-Logs-Url: https://github.com/pourmand1376/readest/sessions/18cbc3c6-ba92-4e63-bef9-93dcf6698c21



---------

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
Amir Pourmand
2026-05-23 06:09:15 +03:30
committed by GitHub
parent 66c198e575
commit b8d986cbd6
6 changed files with 53 additions and 29 deletions
+6
View File
@@ -0,0 +1,6 @@
{
"name": "Readest",
// Initialize only the submodules required for Docker builds.
// tauri/tauri-plugins are skipped here since they're only needed for desktop builds.
"postCreateCommand": "git submodule update --init packages/foliate-js packages/simplecc-wasm"
}
+6 -2
View File
@@ -135,8 +135,10 @@ jobs:
images: ghcr.io/${{ github.repository_owner }}/readest
tags: |
type=raw,value=main,enable={{is_default_branch}}
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
type=raw,value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' }}
type=semver,pattern={{version}},enable=${{ github.event_name == 'release' }}
type=semver,pattern={{major}}.{{minor}},enable=${{ github.event_name == 'release' }}
type=sha,prefix=sha-
- name: Extract image metadata (GHCR + Docker Hub)
@@ -149,8 +151,10 @@ jobs:
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/readest
tags: |
type=raw,value=main,enable={{is_default_branch}}
type=raw,value=latest,enable={{is_default_branch}}
type=raw,value=latest,enable=${{ github.event_name == 'release' }}
type=raw,value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' }}
type=semver,pattern={{version}},enable=${{ github.event_name == 'release' }}
type=semver,pattern={{major}}.{{minor}},enable=${{ github.event_name == 'release' }}
type=sha,prefix=sha-
- name: Create manifest list and push (GHCR only)
+4 -9
View File
@@ -9,6 +9,9 @@ COPY apps/readest-app/package.json ./apps/readest-app/
COPY patches/ ./patches/
COPY packages/ ./packages/
RUN --mount=type=cache,id=pnpm,sharing=locked,target=/pnpm/store pnpm install --frozen-lockfile
RUN test -f packages/foliate-js/vendor/pdfjs/annotation_layer_builder.css \
&& test -d packages/simplecc-wasm/dist/web \
|| { printf '\nERROR: Required git submodules are not initialized in the source directory.\nEnsure submodules are initialized before running docker build.\nRun: git submodule update --init packages/foliate-js packages/simplecc-wasm\n\n'; exit 1; }
RUN pnpm --filter @readest/readest-app setup-vendors
FROM docker.io/library/node:24-slim@sha256:24dc26ef1e3c3690f27ebc4136c9c186c3133b25563ae4d7f0692e4d1fe5db0e AS development-stage
@@ -50,15 +53,7 @@ ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
RUN corepack prepare pnpm@11.1.1 --activate
WORKDIR /app
# Only copy what next start needs — omit source, Rust, tests, patches, etc.
COPY --from=build /app/package.json /app/package.json
COPY --from=build /app/pnpm-workspace.yaml /app/pnpm-workspace.yaml
COPY --from=build /app/node_modules /app/node_modules
COPY --from=build /app/apps/readest-app/package.json /app/apps/readest-app/package.json
COPY --from=build /app/apps/readest-app/next.config.mjs /app/apps/readest-app/next.config.mjs
COPY --from=build /app/apps/readest-app/node_modules /app/apps/readest-app/node_modules
COPY --from=build /app/apps/readest-app/.next /app/apps/readest-app/.next
COPY --from=build /app/apps/readest-app/public /app/apps/readest-app/public
COPY --from=build /app /app
WORKDIR /app/apps/readest-app
ENTRYPOINT ["pnpm", "start-web", "-H", "0.0.0.0"]
EXPOSE 3000
+13 -10
View File
@@ -63,13 +63,19 @@ replace `your-dockerhub-username` with the Docker Hub namespace that publishes y
for official images, use the namespace configured for this repository's Docker Hub publishing secrets.
published tags:
- `latest`: published from release events
- `latest`: rolling image from the default branch and 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
> **Prerequisites for local builds**: the `packages/foliate-js` and `packages/simplecc-wasm` git submodules must be initialized before building:
> ```bash
> git submodule update --init packages/foliate-js packages/simplecc-wasm
> ```
> In GitHub Codespaces this is done automatically via `.devcontainer/devcontainer.json`.
```bash
cd docker
docker compose -f compose.yaml -f compose.build.yaml up --build -d
@@ -82,16 +88,13 @@ docker compose -f compose.yaml -f compose.build.yaml up --build -d
### 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`:
> **Prerequisites**: submodules must be initialized (see above).
```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
to develop using the compose stack, use `compose.dev.yaml` which sets the build target to `development-stage` (Next.js dev server) and mounts your local repo for hot reload:
```bash
cd docker
docker compose -f compose.yaml -f compose.dev.yaml up --build -d
```
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.
+24
View File
@@ -0,0 +1,24 @@
# Overlay on top of compose.yaml.
# Usage (from the docker/ directory):
# docker compose -f compose.yaml -f compose.dev.yaml up --build -d
services:
client:
build:
context: ..
target: development-stage
args:
NEXT_PUBLIC_APP_PLATFORM: web
environment:
# Required so pnpm does not abort when purging node_modules without a TTY
CI: "true"
# Mount the source code for hot reload.
# Anonymous volumes shadow pre-built dirs inside the image so the
# container's installed deps and vendor assets are used instead of
# what's on the host.
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
-8
View File
@@ -124,14 +124,6 @@ services:
restart: unless-stopped
ports:
- "3000:3000"
# to enable hot reload, mount the source code as a volume, and artifacts as anon volumes
# 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
environment:
SUPABASE_URL: http://kong:8000
SUPABASE_PUBLIC_URL: http://${HOST_IP}:${KONG_HTTP_PORT:-8000}