Skip to content

Extract entrypoint script to file for Apptainer compatibility#386

Merged
t0mdavid-m merged 2 commits into
mainfrom
claude/fix-opendiakiosk-apptainer-dHZXJ
May 15, 2026
Merged

Extract entrypoint script to file for Apptainer compatibility#386
t0mdavid-m merged 2 commits into
mainfrom
claude/fix-opendiakiosk-apptainer-dHZXJ

Conversation

@t0mdavid-m
Copy link
Copy Markdown
Member

@t0mdavid-m t0mdavid-m commented May 13, 2026

Summary

Refactors the container entrypoint from an inline shell script in the Dockerfile to a separate entrypoint.sh file. This improves maintainability and adds support for running under Apptainer/Singularity containers, which mount the filesystem as read-only by default.

Key Changes

  • New file: entrypoint.sh — Extracted entrypoint script with improved Apptainer compatibility:

    • Introduces RUNTIME_DIR environment variable (defaults to /tmp/opendiakiosk) to route all runtime state (Redis dumps, pidfiles, nginx temp dirs) to a writable location
    • Makes cron startup non-fatal so the app continues if the filesystem is read-only
    • Generates Redis and nginx configs at runtime pointing to $RUNTIME_DIR instead of system paths like /var/lib/redis and /var/run
    • Adds comprehensive comments explaining the read-only filesystem handling
  • Modified: Dockerfile — Simplified entrypoint setup:

    • Removed inline RUN echo script that generated the entrypoint
    • Changed to COPY entrypoint.sh /app/entrypoint.sh for clarity and maintainability
    • Removed RUN mkdir -p /var/lib/redis && chown redis:redis /var/lib/redis since Redis now uses $RUNTIME_DIR
    • Updated comments to reference the new entrypoint file and explain the Apptainer compatibility approach

Implementation Details

The key innovation is the RUNTIME_DIR pattern: by defaulting to /tmp (which is bind-mounted as tmpfs in both Docker and Apptainer) and allowing override via environment variable, the container works seamlessly in both environments:

  • Docker: Uses default /tmp/opendiakiosk, which is writable
  • Apptainer: Same default works because /tmp is writable; users can override RUNTIME_DIR to a persistent path if they want Redis dumps to survive container restarts

This approach eliminates the need for separate Dockerfile variants or complex conditional logic in the entrypoint itself.

https://claude.ai/code/session_01NF5Z6z8JjpuknFcDKki5KQ

Summary by CodeRabbit

  • Chores
    • Improved container initialization with enhanced startup sequence for services and background processes
    • Added multi-instance deployment support with automatic load balancing for application scaling
    • Refactored entrypoint provisioning for enhanced maintainability and configuration flexibility

Review Change Stack

Apptainer mounts the container filesystem read-only by default, so the
existing entrypoint failed in two places:
  * cron could not write /var/run/crond.pid
  * redis-server could not access /var/lib/redis (and on Ubuntu it loads
    the system /etc/redis/redis.conf which points there)

Refactor the inline-heredoc entrypoint into entrypoint.sh and redirect
all runtime state (Redis data + pidfile, generated nginx config, nginx
pidfile + temp dirs) to RUNTIME_DIR (default /tmp/opendiakiosk), which
is writable as tmpfs under Apptainer and as overlay under Docker. cron
failure is now non-fatal so the rest of the app still starts when
scheduled cleanup is unavailable.

Docker behavior is unchanged - the queue is already configured with
appendonly=no so moving the Redis dir to a tmpfs path costs nothing.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Warning

Rate limit exceeded

@t0mdavid-m has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 59 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3d387e93-b267-45d7-9662-9c7ce90c4cae

📥 Commits

Reviewing files that changed from the base of the PR and between e8c630a and d85c6d8.

📒 Files selected for processing (1)
  • Dockerfile
📝 Walkthrough

Walkthrough

The PR moves container entrypoint initialization from inline Dockerfile generation to an external entrypoint.sh script. The Dockerfile simplifies package installation and uses COPY to provision the entrypoint. The script implements runtime setup (cron, Redis, RQ workers) and orchestrates Streamlit in single-instance or multi-instance Nginx load-balanced mode.

Changes

Container Entrypoint and Runtime Orchestration

Layer / File(s) Summary
Docker image and entrypoint provisioning
Dockerfile
The run-app stage package install is simplified by removing build-time Redis directory creation; /app/entrypoint.sh is now copied from the build context instead of generated inline.
Runtime environment and dependency initialization
entrypoint.sh
Entrypoint activates the conda environment, creates/selects a writable $RUNTIME_DIR, conditionally starts cron, generates a Redis config at runtime, and waits for Redis readiness via redis-cli ping.
Background workers and Streamlit execution modes
entrypoint.sh
RQ workers are launched in the background. Streamlit runs directly in single-instance mode, or in multi-instance mode behind a dynamically generated Nginx config that load-balances multiple Streamlit processes on internal ports.

🐰 A hop, a skip, and a load-balanced way,
Entrypoint goes external today!
Redis and Nginx join the show,
While workers and Streamlit steal the flow.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: extracting the entrypoint script from the Dockerfile into a dedicated file to enable Apptainer compatibility.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/fix-opendiakiosk-apptainer-dHZXJ

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
entrypoint.sh (1)

128-141: ⚡ Quick win

Use absolute paths or ensure working directory context for consistency and robustness.

While the Dockerfile sets WORKDIR /app, using relative paths like app.py creates an implicit dependency on the working directory. Using /app/app.py directly would make the intent explicit and avoid subtle failures if the directory context changes later.

Suggested fix
-        streamlit run app.py --server.port "$PORT" --server.address 0.0.0.0 &
+        streamlit run /app/app.py --server.port "$PORT" --server.address 0.0.0.0 &
...
-    exec streamlit run app.py --server.address 0.0.0.0
+    exec streamlit run /app/app.py --server.address 0.0.0.0
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@entrypoint.sh` around lines 128 - 141, The start-up commands use a relative
path "app.py" which relies on WORKDIR; update the streamlit invocation(s) in the
multi-instance loop (the lines running streamlit run app.py --server.port ...
and the single-instance exec streamlit run app.py --server.address ...) to use
the absolute path /app/app.py, and also ensure the nginx exec uses an absolute
nginx config path (NGINX_CONF should be an absolute path or resolved before use)
so both streamlit launches and nginx launch do not depend on the current working
directory.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@entrypoint.sh`:
- Around line 128-141: The start-up commands use a relative path "app.py" which
relies on WORKDIR; update the streamlit invocation(s) in the multi-instance loop
(the lines running streamlit run app.py --server.port ... and the
single-instance exec streamlit run app.py --server.address ...) to use the
absolute path /app/app.py, and also ensure the nginx exec uses an absolute nginx
config path (NGINX_CONF should be an absolute path or resolved before use) so
both streamlit launches and nginx launch do not depend on the current working
directory.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d503cf70-bab9-48f9-b2c6-b5f0a8779a94

📥 Commits

Reviewing files that changed from the base of the PR and between 3c59a2f and e8c630a.

📒 Files selected for processing (2)
  • Dockerfile
  • entrypoint.sh

@t0mdavid-m t0mdavid-m merged commit 9128698 into main May 15, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant