Skip to content

openemr-cmd: container auto-detection picks wrong container when multiple stacks run #688

Open

Description

@kojiromike

Problem

openemr-cmd's automatic container detection picks the wrong container when multiple development stacks are running side-by-side (e.g. one per git worktree).

The two filters in utilities/openemr-cmd/openemr-cmd:

INSANE_DEV_DOCKER="openemr-8-4[_\-]1"
EASY_DEV_DOCKER="openemr[_\-]1"

are passed to docker ps --filter "name=...", which Docker treats as a regex anywhere in the name, not anchored to the end. With several worktree stacks running, that regex matches every auxiliary container whose name happens to end in -1 — openemr-<wt>-phpmyadmin-1, openemr-<wt>-mysql-1, openemr-<wt>-selenium-1, etc. — in addition to the real openemr-<wt>-openemr-1. The script then takes head -n 1, so the chosen container is essentially arbitrary (in practice, often phpmyadmin or another helper).

Symptom

Running any devtools-backed subcommand (e.g. openemr-cmd drid) bombs out with:

OCI runtime exec failed: exec failed: unable to start container process:
exec: "/root/devtools": stat /root/devtools: no such file or directory

That's the chosen container reporting that /root/devtools doesn't live there — it's not the openemr container, it's an auxiliary one. The -d <container> flag works around it, but the auto-detection should be reliable.

Reproduction

  1. Bring up the easy dev stack in two or more worktrees (different COMPOSE_PROJECT_NAME).
  2. From any shell, run openemr-cmd drid (or openemr-cmd shell, openemr-cmd php-log, etc. — anything that uses run_devtools_in_docker).
  3. Observe the exec failure above when the regex picks a non-openemr container.

Why now

This used to be a non-issue because most setups had at most one easy-dev stack running. Worktree-based workflows (one stack per branch under review) make the collision routine — every additional stack contributes ~6 more containers ending in -1, and the auxiliary ones sort first under common naming.

Activity

  1. added theissue type on May 4, 2026
  2. bradymiller commented on May 4, 2026

    @bradymiller
    SponsorMember
  3. bradymiller commented on May 5, 2026

    @bradymiller
    SponsorMember

    hi @kojiromike ,

    Feel free to nor read my post above since doesn't make much sense.

    1. It would be neat if you could automatically pick it by the context (ie. if shell is in one of the worktree dir/repos, then do that).
    2. Also would be neat to have a command like openemr-cmd worktree exec <worktree-name> <a-standard-openemr-cmd-command-such-as-drid> for folks whom run their commands for everything all from the base worktree branch (akin to the other worktree commands) (another wish item: also would be nice to have a stop/start command akin to docker compose stop/start)
  4. bradymiller commented on May 5, 2026

    @bradymiller
    SponsorMember

    hi @kojiromike ,
    Put in pieces for exec/stop/start at this PR:
    #691
    (note it didn't do any auto-detection stuff via figuring out context, so this issue still is not resolved)

  5. kojiromike commented on Jun 11, 2026

    @kojiromike
    MemberAuthor

    Adding a concrete fix suggestion for the auto-detection part still open after #691 (per @bradymiller's note that PR didn't add context-based detection).

    The cleanest source of truth is Docker Compose itself, from the cwd. Note that up/down/start/stop already do this implicitly — they go through run_docker_compose, which is a bare docker compose "$@" run from the working directory, so they resolve the correct project with no name-regex at all. The exec-style dispatch (which sets CONTAINER_ID via the name=openemr[_-]1 | head -1 scan) is the only path that throws that cwd context away.

    So before falling back to the name regex, resolve from the cwd's compose project:

    cwd_id=$(docker compose ps -q openemr 2>/dev/null | head -n 1)
    [[ -n "${cwd_id}" ]] && CONTAINER_ID="${cwd_id}"

    docker compose ps -q openemr derives the project from the current directory's compose file (or honors -p / COMPOSE_PROJECT_NAME), so it is:

    • cwd-aware — picks the stack for the worktree you're actually in (covers Brady's wish Need to pin docker image to a Release Version of OpenEMR #1);
    • service-targeted — asks for the openemr service specifically, so it can't grab an auxiliary *-phpmyadmin-1 / *-mysql-1 container (the unanchored-regex symptom in the OP);
    • convention-agnostic — works whether the project is named openemr-<slug> or derived from the directory name, with no .worktrees.json dependency.

    This makes the exec path consistent with the already-correct up/down behavior. (Filed #794 with the same analysis before finding this issue — closing that as a dup of this one.)

  6. bradymiller commented on Jun 11, 2026

    @bradymiller
    SponsorMember

    @kojiromike ,
    In my workflow, I don't run the commands from within the actual worktree. I basically run them all from the master/base worktree (thus rely on providing the name of the worktree that the command is geared towards). Will these changes break that workflow?

  7. kojiromike commented on Jun 11, 2026

    @kojiromike
    MemberAuthor

    @kojiromike , In my workflow, I don't run the commands from within the actual worktree. I basically run them all from the master/base worktree (thus rely on providing the name of the worktree that the command is geared towards). Will these changes break that workflow?

    If you're providing the name explicitly, definitely not. It'd be the equivalent of passing --project-directory or --file to docker compose.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions