Skip to content

fix(docker): make healthcheck role-aware for Sidekiq#20

Open
andersonlemesc wants to merge 1 commit into
evolution-foundation:developfrom
andersonlemesc:fix/sidekiq-healthcheck
Open

fix(docker): make healthcheck role-aware for Sidekiq#20
andersonlemesc wants to merge 1 commit into
evolution-foundation:developfrom
andersonlemesc:fix/sidekiq-healthcheck

Conversation

@andersonlemesc
Copy link
Copy Markdown

@andersonlemesc andersonlemesc commented May 9, 2026

Problem

The auth Docker image is reused by two different runtime roles:

  • the Rails web service, which serves HTTP on port 3001
  • the Sidekiq worker, which does not serve HTTP

Today the image-level Docker HEALTHCHECK always runs:

curl -f http://localhost:3001/health || exit 1

That is correct for the web container, but it is not valid for the Sidekiq container. When the same image is used to start Sidekiq, the worker can boot successfully while Docker still marks it as unhealthy because nothing is listening on /health inside that container.

This is especially problematic on deployment platforms that do not expose Docker Compose's healthcheck.disable: true override in their UI/schema. Easypanel is one concrete example: operators can configure environment variables and commands, but cannot reliably disable the inherited image healthcheck for only the worker service. The result is a healthy Sidekiq process reported as an unhealthy container.

Why not remove the healthcheck?

Removing the image healthcheck would avoid the Sidekiq false negative, but it would also remove a useful default for the Rails web service. Since this image intentionally supports multiple roles, the image healthcheck should understand the active role instead of assuming every container is an HTTP server.

This follows the common split used by containerized applications:

  • web process health: probe an HTTP health endpoint
  • worker process health: verify the worker process is running / monitor worker-specific signals
  • platform escape hatch: allow operators to opt out when their platform has limited healthcheck controls

Changes

  • Add bin/healthcheck as the image healthcheck entrypoint.
  • Update Dockerfile so Docker HEALTHCHECK invokes /usr/local/bin/evo-auth-healthcheck.
  • Keep the default web behavior unchanged: SERVICE_ROLE=web probes http://127.0.0.1:${PORT:-3001}/health.
  • Add SERVICE_ROLE=sidekiq support, which validates that a Sidekiq process is running instead of probing HTTP.
  • Add DISABLE_HEALTHCHECK=true as an explicit bypass for constrained platforms.
  • Document SERVICE_ROLE and DISABLE_HEALTHCHECK in .env.example.

Operational usage

For the Rails web container, no change is required. The default remains:

SERVICE_ROLE=web

For the Sidekiq container, set:

SERVICE_ROLE=sidekiq

If a deployment platform needs to bypass the image healthcheck entirely, set:

DISABLE_HEALTHCHECK=true

References / rationale

  • Docker images can define only one image-level HEALTHCHECK; when the same image runs multiple roles, that command must be role-aware or overridden by the runtime.
  • Rails health endpoints such as /health or /up are intended for HTTP-serving app processes.
  • Sidekiq workers are background processes and do not expose the Rails HTTP health endpoint from the worker container, so checking the Sidekiq process is a more accurate container-level health signal than curling /health.

Validation

Built and tested the image locally:

docker build -t evo-auth-healthcheck-test ./evo-auth-service-community

Verified Docker image healthcheck config:

docker inspect evo-auth-healthcheck-test --format "{{json .Config.Healthcheck}}"

Verified bypass mode:

docker run --rm -e DISABLE_HEALTHCHECK=true evo-auth-healthcheck-test /usr/local/bin/evo-auth-healthcheck

Verified Sidekiq role mode:

docker run --rm -e SERVICE_ROLE=sidekiq evo-auth-healthcheck-test sh -c 'ruby -e "$0=\\"sidekiq\\"; sleep 30" & /usr/local/bin/evo-auth-healthcheck'\n```\n\nAlso tested the resulting image in a real deployment flow and confirmed the Sidekiq worker no longer fails healthcheck because of the inherited web `/health` probe.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 9, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Makes the container healthcheck script role-aware by introducing a dedicated healthcheck executable and wiring Docker’s HEALTHCHECK to use it instead of a hardcoded HTTP probe, preparing support for non-web roles like Sidekiq.

Sequence diagram for Docker healthcheck using role-aware script

sequenceDiagram
    participant DockerEngine
    participant Container
    participant HealthcheckScript as evo_auth_healthcheck
    participant WebProcess
    participant SidekiqProcess

    DockerEngine->>Container: Execute HEALTHCHECK
    Container->>HealthcheckScript: /usr/local/bin/evo-auth-healthcheck
    HealthcheckScript->>Container: Read ROLE env
    alt ROLE = web
        HealthcheckScript->>WebProcess: HTTP GET /health on port 3001
        WebProcess-->>HealthcheckScript: 200 OK or error
        alt status OK
            HealthcheckScript-->>DockerEngine: exit 0 (healthy)
        else status not OK
            HealthcheckScript-->>DockerEngine: exit 1 (unhealthy)
        end
    else ROLE = sidekiq
        HealthcheckScript->>SidekiqProcess: Perform sidekiq-specific checks
        SidekiqProcess-->>HealthcheckScript: status result
        alt status OK
            HealthcheckScript-->>DockerEngine: exit 0 (healthy)
        else status not OK
            HealthcheckScript-->>DockerEngine: exit 1 (unhealthy)
        end
    end
Loading

File-Level Changes

Change Details Files
Introduce a dedicated, role-aware healthcheck script and wire Docker HEALTHCHECK to use it instead of curl-ing the web health endpoint.
  • Copy bin/healthcheck into the image as /usr/local/bin/evo-auth-healthcheck before switching to the non-root user
  • Ensure the healthcheck script is executable via chmod
  • Update Docker HEALTHCHECK CMD to invoke the evo-auth-healthcheck script rather than curl http://localhost:3001/health
Dockerfile
bin/healthcheck
Adjust environment configuration to support the new healthcheck behavior.
  • Update example environment configuration to reflect any new variables or semantics required by the healthcheck script
.env.example

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • Relying on --chown=1000:1000 for the healthcheck script couples it to a hard-coded UID/GID; consider either copying as root and leaving it world-readable/executable or referencing the rails user/group symbols to avoid breakage if these IDs change.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Relying on `--chown=1000:1000` for the healthcheck script couples it to a hard-coded UID/GID; consider either copying as root and leaving it world-readable/executable or referencing the `rails` user/group symbols to avoid breakage if these IDs change.

## Individual Comments

### Comment 1
<location path="Dockerfile" line_range="55-56" />
<code_context>
 EXPOSE 3001

-# Health check
 HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
-    CMD curl -f http://localhost:3001/health || exit 1
+    CMD /usr/local/bin/evo-auth-healthcheck
</code_context>
<issue_to_address>
**suggestion:** Prefer exec-form HEALTHCHECK CMD to avoid an extra shell and improve signal handling.

In this case you can write it as `CMD ["/usr/local/bin/evo-auth-healthcheck"]`. This removes the implicit `/bin/sh -c` wrapper, keeps argument handling explicit, and aligns with Docker’s guidance for CMD/ENTRYPOINT.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread Dockerfile Outdated
@andersonlemesc andersonlemesc force-pushed the fix/sidekiq-healthcheck branch from 2c30bc8 to c6be346 Compare May 9, 2026 17:32
@andersonlemesc
Copy link
Copy Markdown
Author

andersonlemesc commented May 9, 2026

Applied the suggestion and updated the Dockerfile to use the exec form for the healthcheck:

HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD ["/usr/local/bin/evo-auth-healthcheck"]

This avoids Docker running the healthcheck through an implicit /bin/sh -c wrapper. Since the healthcheck target is an executable script with a shebang, the exec form is a better fit and should inspect as CMD
instead of CMD-SHELL.

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