[Request] Readest (Docker Image + unRAID Template)

Service Description
Readest is a modern, open-source ebook reader for immersive reading. Seamlessly sync your progress, notes, highlights, and library across macOS, Windows, Linux, Android, iOS, and the Web. The service is well maintained with regular feature updates and has native Apps as well :tada:

Dockerfile

Repository


I would love to see the Service running on a server.
It’s an awesome alternative to Calibre and Komga in terms of UI and UX without the need of clutter configurations in terms of connecting devices/configuring the service :slight_smile:

What’s wrong with their container?

Ahh I see, they have the dockerfile but don’t publish a container

1 Like

That’s the point :sweat_smile:

Don’t know if this helps but I asked ChatGPT with Deepresarch for the CD/CI Pipeline.

Summary
name: Build and Publish Docker Image (LinuxServer.io Standards)

# Permission needed to push to GHCR (GitHub Container Registry)
permissions:
  contents: read
  packages: write

# Trigger on pushes to main (for stable builds) and maybe tags for releases.
on:
  push:
    branches: [ "main" ]
  # Optionally, trigger on git tags (e.g., when Readest creates a release tag)
  tags:
    - "v*"          # e.g., if upstream uses tags like v1.2.3
  schedule:
    - cron: "0 3 * * 1"  # Weekly build (Mon 03:00 UTC) for base image updates

jobs:
  build-and-push:
    name: Build and Push Multi-Arch Docker Image
    runs-on: ubuntu-latest

    # We will build images for amd64 and arm64 (multi-arch)
    strategy:
      matrix:
        arch: [amd64, arm64]   # Use matrix if doing arch-specific steps (optional)

    steps:
      # Checkout the repository to get Dockerfile and source
      - name: Checkout source
        uses: actions/checkout@v3

      # (Optional) Dockerfile linting with Hadolint to ensure best practices
      - name: Lint Dockerfile
        uses: hadolint/hadolint-action@v2
        with:
          dockerfile: Dockerfile

      # Setup QEMU for building non-native architectures (required for multi-arch build on x86 runner)
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2
        with:
          platforms: linux/arm64

      # Setup Docker Buildx (builder) for multi-arch
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      # Log in to Docker registries (GHCR and Docker Hub in this example)
      - name: Log in to GHCR (GitHub Container Registry)
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ secrets.GHCR_USERNAME }}        # e.g. a service account (like "linuxserver-ci") or GitHub username
          password: ${{ secrets.GHCR_TOKEN }}           # Personal access token with write:packages scope
      - name: Log in to Docker Hub
        if: secrets.DOCKERHUB_USERNAME != ''           # Only if secrets are set (optional)
        uses: docker/login-action@v2
        with:
          registry: docker.io
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      # Build and push multi-arch image using Buildx
      - name: Build and Push Docker image
        uses: docker/build-push-action@v3
        with:
          context: .
          file: ./Dockerfile
          push: true
          platforms: linux/amd64,linux/arm64    # target architectures for multi-arch manifest
          # Define tags for the image:
          tags: |
            ghcr.io/linuxserver/readest:latest
            ghcr.io/linuxserver/readest:${{ steps.meta.outputs.version_tag }}
            ghcr.io/linuxserver/readest:${{ steps.meta.outputs.static_tag }}
          labels: |
            org.opencontainers.image.source=${{ github.repository }}
            org.opencontainers.image.revision=${{ github.sha }}
          # Build args or other options can be set here if needed (e.g., app version ARG)

      # Before building, use docker/metadata-action to compute dynamic tags (version and build tags)
      - id: meta
        name: Extract version info
        uses: docker/metadata-action@v4
        with:
          images: ghcr.io/linuxserver/readest
          tags: |
            type=semver,pattern={{version}}-ls{{sha}},latest=true
            type=ref,event=tag         # use git tag if present
            type=ref,event=branch      # use branch name (like "main" -> "latest")
          # The metadata-action will detect the version from tags or files.
          # If the Readest repo has version info (e.g., package.json, Cargo.toml, etc.), it can be configured to pick that up.
          # For simplicity, assume it can derive a version (or one could set it manually via an environment variable or file.)

      # **Optional**: Build and test the image on the current platform before pushing (smoke test)
      - name: Build image (single-arch test build)
        env:
          IMAGE_NAME: test-readest:ci
        run: |
          docker build -t $IMAGE_NAME .
          echo "Running a quick smoke test of the container..."
          docker run --rm $IMAGE_NAME --help || echo "Container help/usage command failed (check entrypoint)"
      - name: Run container smoke test
        if: ${{ success() }}
        run: |
          # Example test: print application version from the container
          docker run --rm ghcr.io/linuxserver/readest:latest --version || true
          # In a real scenario, replace the above with appropriate test commands.
          # E.g., start the container in detached mode and probe its health or version:
          # docker run -d --name readest-test ghcr.io/linuxserver/readest:latest
          # sleep 10
          # docker logs readest-test | grep "Listening on" || (echo "App failed to start" && exit 1)
          # docker rm -f readest-test

      # If tests passed, the multi-arch build step above already pushed images.
      # Next, we can create a GitHub release or tag for this build (with LSIO versioning).
      - name: Create GitHub Release (tag image version)
        if: ${{ github.ref == 'refs/heads/main' }}
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ steps.meta.outputs.static_tag }}   # e.g. "1.0.0-ls1"
          release_name: ${{ steps.meta.outputs.static_tag }} 
          draft: false
          prerelease: false
          body: "Automated release for Readest container image version ${{ steps.meta.outputs.static_tag }}."

Here’s an example Unraid Template I’ve created

<?xml version="1.0"?>
<Container version="2">
  <Name>Readest</Name>
  <Repository>lscr.io/linuxserver/readest</Repository>
  <Registry>https://github.com/orgs/linuxserver/packages/container/package/readest</Registry>
  <DonateText>Donations</DonateText>
  <DonateLink>https://www.linuxserver.io/donate</DonateLink>
  <DonateImg>https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/donate.png</DonateImg>
  <Network>bridge</Network>
  <Privileged>false</Privileged>
  <Support>https://github.com/linuxserver/docker-readest/issues/new/choose</Support>
  <Shell>bash</Shell>
  <GitHub>https://github.com/linuxserver/docker-readest#application-setup</GitHub>
  <ReadMe>https://github.com/linuxserver/docker-readest#readme</ReadMe>
  <Project>https://github.com/readest/readest</Project>
  <Overview>Readest is a modern, open-source ebook reader for immersive reading. Seamlessly sync your progress, notes, highlights, and library across macOS, Windows, Linux, Android, iOS, and the Web.</Overview>
  <WebUI>http://[IP]:[PORT:3000]</WebUI>
  <Category>Network:Web MediaServer:Books Tools:Utilities</Category>
  <TemplateURL>https://raw.githubusercontent.com/linuxserver/templates/master/unraid/readest.xml</TemplateURL>
  <Icon>https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/readest-logo.png</Icon>
  <Date>2025-06-08</Date>
  <Changes>
### 2025-06-08
- Initial template creation

  </Changes>
  <Config Name="TZ" Target="TZ" Default="Etc/UTC" Mode="" Description="Timezone" Type="Variable" Display="advanced" Required="false" Mask="false">Etc/UTC</Config>
  <Config Name="WebUI" Target="3000" Default="3000" Mode="tcp" Description="Port for Readest web interface" Type="Port" Display="always" Required="true" Mask="false">3000</Config>
  <Config Name="Path: /books" Target="/books" Default="" Mode="rw" Description="Books location" Type="Path" Display="always" Required="false" Mask="false">/mnt/user/data/media/books</Config>
  <Config Name="DOCKER_MODS" Target="DOCKER_MODS" Default="" Mode="" Description="Allows additional functionality to be added" Type="Variable" Display="always" Required="false" Mask="false"></Config>
  <Config Name="AppData Config" Target="/config" Default="/mnt/user/appdata/readest" Mode="rw" Description="Container config directory for Readest" Type="Path" Display="advanced" Required="true" Mask="false">/mnt/user/appdata/readest</Config>
  <Config Name="PUID" Target="PUID" Default="99" Description="Container Variable: PUID" Type="Variable" Display="advanced" Required="true" Mask="false"/>
  <Config Name="PGID" Target="PGID" Default="100" Description="Container Variable: PGID" Type="Variable" Display="advanced" Required="true" Mask="false"/>
  <Config Name="UMASK" Target="UMASK" Default="022" Description="Container Variable: UMASK" Type="Variable" Display="advanced" Required="false" Mask="false"/>
</Container>

PATH and PORT should be replaced with real values :slight_smile: