Skip to content

Cannot run Composer binaries without path anymore #363

Description

@mbrodala

Expected Behavior

Assuming a Compose service app using this Docker image and phpstan/phpstan is installed via Composer, running its binary vendor/bin/phpstan should work without the path prefix vendor/bin:

± docker compose exec app phpstan
Note: Using configuration file /var/www/html/phpstan.neon.
 453/453 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%


                                                                                                                        
 [OK] No errors                                                                                                         
                                                                                                                        

Current Behavior

Trying to run a Composer binary without path fails:

± docker compose exec app phpstan
OCI runtime exec failed: exec failed: unable to start container process: exec: "phpstan": cannot run executable found relative to current directory: unknown

This seems to be related to Go 1.19 which dropped support for executing commands from the current directory (a "dot path") as a security measurement. Obviously the Docker engine did upgrade to this Go version in the meantime.

This Docker image adds (among others) vendor/bin to the $PATH which did allow for running Composer binaries so far but this has stopped working now:

https://github.com/thecodingmachine/docker-images-php/blob/098c31b33f019fb69f45df85a14f507a4f300fb5/utils/Dockerfile.slim.blueprint#L255L262

Possible Solution

Use absolute paths in the $PATH, so /var/www/html/vendor/bin and /usr/src/app/vendor/bin instead of just vendor/bin depending on CLI/FPM/Apache variant.

Steps to Reproduce (for bugs)

  1. Have a recent Docker engine (23.0 or newer)
  2. Install a Composer package which provides a binary
  3. Use Docker Compose or Docker exec to run that binary just by its name
  4. See the error mentioned above

Context

Developing PHP-based apps. ;-)

Your Environment

  • Version used: 8.1-v4-fpm-node16
  • Operating System and version: Debian Sid
  • Link to your project: n/a

Activity

  1. mistraloz commented on Apr 4, 2023

    @mistraloz
    Collaborator

    May you run docker compose exec app composer phpstan instead ?

  2. mbrodala commented on Apr 11, 2023

    @mbrodala
    ContributorAuthor

    Sure this works but you can imagine that this a huge hassle and slows down daily development. ;-)

  3. stale commented on Jun 10, 2023

    @stale

    This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Please update it if any action still required.

  4. added
    staleIssues inactives for a while (automatically)
    on Jun 10, 2023
  5. mbrodala commented on Jun 12, 2023

    @mbrodala
    ContributorAuthor

    Still my suggestion stands.

  6. added and removed
    staleIssues inactives for a while (automatically)
    bugSomething isn't working
    on Jun 14, 2023
  7. mistraloz commented on Jun 14, 2023

    @mistraloz
    Collaborator

    I mark as request but i don't have any idea about how to manage it. If we add /var/www/html/vendor/bin and /usr/src/app/vendor/bin to the PATH, it's will depend about where the composer.json will be located. Usage of composer phpstan allow more flexibility.

  8. mbrodala commented on Oct 9, 2023

    @mbrodala
    ContributorAuthor

    Fix in an unrelated project: syncthing/syncthing#8499

  9. mbrodala commented on Oct 9, 2023

    @mbrodala
    ContributorAuthor

    @mistraloz Not sure what you mean, Composer won't magically allow running package binaries as subcommands. So installing phpstan will not allow for composer phpstan. Instead you will need to run composer exec phpstan instead and keep in mind that this command is run by Composer. So e.g. use composer exec phpstan -- --args --for --phpstan. Not really nice IMO.

  10. mistraloz commented on Oct 10, 2023

    @mistraloz
    Collaborator

    e.g. use composer exec phpstan -- --args --for --phpstan. Not really nice IMO.

    Not perfect but defined to resolve this issue with the path. And you can define your phpstan command as script part of composer.json.

    The alternative is to design a feature to define the PATH with an environment variable (like a PATH_EXT env who will complete the default path with a custom one). It's not a priority because it's exist another way to do it (and IMHO it's a better way).

    PS: I understand that is not perfect for your specific case but we try to resolve requirements for all cases. If you use multiple compose.json or if it's at another path than WORK_DIR/vendor/bin (you can customise it in composer.json), it's will not resolve anything. The feature with PATH_EXT (or another smart way) can be implemented, i'm will not work on it (at least in v4, maybe for v5) but i will merge a PR who do that.

  11. mbrodala commented on Oct 10, 2023

    @mbrodala
    ContributorAuthor

    Well, even multiple composer.json are affected, it doesn't matter how many there are. You cannot invoke any package binary without full path anywhere anymore. So the best we can do for now is to at least restore this for the default working directory. This is better than not have this restored anywhere IMO. Or do I miss something?

  12. mbrodala commented on Jul 18, 2024

    @mbrodala
    ContributorAuthor

    @mistraloz Can you have another look at this? Since this behavior will likely not be reverted in Go, the PATH updating in the Dockerfiles here should be adjusted like this:

    Dockerfile.slim.apache, Dockerfile.slim.fpm
    -ENV PATH="$PATH:./vendor/bin:~/.composer/vendor/bin"
    -RUN sed -i 's#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:./vendor/bin:~/.composer/vendor/bin#g' /etc/sudoers
    +ENV PATH="$PATH:/var/www/html/vendor/bin:~/.composer/vendor/bin"
    +RUN sed -i 's#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/var/www/html/vendor/bin:~/.composer/vendor/bin#g' /etc/sudoers
    Dockerfile.slim.cli
    -ENV PATH="$PATH:./vendor/bin:~/.composer/vendor/bin"
    -RUN sed -i 's#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:./vendor/bin:~/.composer/vendor/bin#g' /etc/sudoers
    +ENV PATH="$PATH:/usr/src/app/vendor/bin:~/.composer/vendor/bin"
    +RUN sed -i 's#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/src/app/vendor/bin:~/.composer/vendor/bin#g' /etc/sudoers

    (Finally Dockerfile.slim.blueprint too but this needs a decision first.)

  13. mistraloz commented on Jul 19, 2024

    @mistraloz
    Collaborator

    Hi @mbrodala I am sorry because i do not like said "no" but here, honestly, i cannot accept to add /var/www/html to the path, there is not very good reason to do that. I spoke with my teammate and I suggest two options that can match for you :
    1/ Use $APACHE_DOCUMENT_ROOT and add it to the PATH. Per example the parent directory of it (the most of the time the framework place the public dir at the same level of the vendor so it's can match for many users (not all but not only you).
    2/ Create an optionnal variable ADDITIONAL_PATH and if it's setted, that will be just be added to the path. That can be helpful for many others cases.

    If you do a PR to manage that in one of this way, i will review and merge it. To allow that you can change utils/docker-entrypoint-as-root.sh or utils/Dockerfile.slim.blueprint (line 285) to change the .bashrc file.

    PS: And instead of APACHE_DOCUMENT_ROOT play with the workdir (defined at docker level) can be a good option too, or something like that.

  14. mbrodala commented on Jul 26, 2024

    @mbrodala
    ContributorAuthor

    Still thinking about this. But do you agree that the following section is pointless like this since it does not work anymore?

    # |--------------------------------------------------------------------------
    # | PATH updating
    # |--------------------------------------------------------------------------
    # |
    # | Let's add ./vendor/bin to the PATH (utility function to use Composer bin easily)
    # |
    ENV PATH="$PATH:./vendor/bin:~/.composer/vendor/bin"
    RUN sed -i 's#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin#/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:./vendor/bin:~/.composer/vendor/bin#g' /etc/sudoers

    This is the location where an absolute path must be specified instead of a relative one.

  15. mistraloz commented on Jul 26, 2024

    @mistraloz
    Collaborator

    Yes i confirm.

  16. added a commit that references this issue on Oct 9, 2026
    9455666
  17. mbrodala commented on Oct 9, 2026

    @mbrodala
    ContributorAuthor

    👍

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions