herokuish icon indicating copy to clipboard operation
herokuish copied to clipboard

Cannot execute any Procfile commands

Open ViViDboarder opened this issue 6 years ago • 15 comments

For some reason I can run herokuish test just fine, however herokuish procfile start web is failing and not printing any kind of message. It just exits with code 8. I also tried playing around interactively and didn't have any luck. herokuish procfile exec echo test or any other command will exit with code 8 as well.

docker-compose.yml

version: '2'
services:
  web:
    image: gliderlabs/herokuish
    volumes:
      - .:/tmp/app
    ports:
      - 3000:3000
    entrypoint: ["/bin/herokuish"]
    # command: ["test"]
    # command: ["procfile", "start", "web"]

Procfile

web: bin/rails server -p $PORT

ViViDboarder avatar Jan 28 '18 04:01 ViViDboarder

The readme doesn't say it, but you are supposed to specify $USER environment variable. That variable controls the non-privileged user that will run your app.

If you don't set it, herokuish tries to set root's home directory to /app and then fails for valid reasons. I've learned it by doing strace -s 50 -f /start web

Anyway, even if I export USER=herokuishuser and then run my app, I still get a cryptic message:

setuidgid: fatal: unable to run gunicorn: file does not exist

Which doesn't happen when I run herokuish test

knazarov avatar Mar 31 '18 18:03 knazarov

@racktear do you have an example repository - with instructions - we can use to verify that behavior?

josegonzalez avatar Mar 31 '18 18:03 josegonzalez

@josegonzalez sure. Here you go:

git clone https://github.com/racktear/herokuish-flask.git
cd herokuish-flask/
docker run --rm -t -i --env USER=herokuishuser -v $(pwd):/tmp/app gliderlabs/herokuish /bin/bash
# then in docker:
/build
/start web

The last command fails with:

setuidgid: fatal: unable to run gunicorn: file does not exist

While herokuish test works fine.

knazarov avatar Mar 31 '18 18:03 knazarov

@josegonzalez Did you ever try this scenario yourselves? Maybe I'm doing something obviously wrong. I was unable to find any advice on how to run Herokuish apps in plain Docker, but looks like Dokku is doing something very similar.

If you find that there is really a problem somewhere, please let me know. I'd really like to try out Herokuish on a side-project.

knazarov avatar Apr 02 '18 17:04 knazarov

I haven't had a chance to verify this, but generally I see this happen when either the app wasn't built properly or the dependency you want isnt actually installed.

josegonzalez avatar Apr 02 '18 18:04 josegonzalez

So, I've been digging a bit further. Here's what I've found:

  • To run any command, herokuish first cleans up the /app directory: ( see here )
  • When building (/build) it creates profile.d and other stuff, and moves it from build directory (/tmp/app) to /app ( see here )
  • When I do /start web, the entry point cleans up the profile set up on the build step, and profile.d is erased.

To illustrate, here's what /app looks like after /build:

root@8e69bb4d074a:~# find /app -maxdepth 2 -ls | grep -v .git
    57813      4 drwxr-xr-x   5 herokuishuser herokuishuser     4096 Apr  3 19:48 /app
  3417104      4 -rw-r--r--   1 herokuishuser herokuishuser       12 Apr  3 19:48 /app/runtime.txt
  3417101      4 -rw-r--r--   1 herokuishuser herokuishuser       34 Apr  3 19:48 /app/Procfile
    67526      4 drwxr-xr-x   2 herokuishuser herokuishuser     4096 Apr  3 19:48 /app/.profile.d
  3670908      4 -rw-r--r--   1 herokuishuser herokuishuser      575 Apr  3 19:48 /app/.profile.d/python.sh
  3670909      4 -rwxr-xr-x   1 herokuishuser herokuishuser      511 Apr  3 19:48 /app/.profile.d/WEB_CONCURRENCY.sh
  3670910      4 -rwxr-xr-x   1 herokuishuser herokuishuser      236 Apr  3 19:48 /app/.profile.d/python.gunicorn.sh
  3417102      4 -rw-r--r--   1 herokuishuser herokuishuser      423 Apr  3 19:48 /app/app.py
    57953      4 drwxr-xr-x   4 herokuishuser herokuishuser     4096 Apr  3 19:48 /app/.heroku
  3417633      4 -rw-r--r--   1 herokuishuser herokuishuser       10 Apr  3 19:48 /app/.heroku/python-stack
    57954      4 drwxr-xr-x   6 herokuishuser herokuishuser     4096 Apr  3 19:48 /app/.heroku/python
    63380      4 drwxr-xr-x   2 herokuishuser herokuishuser     4096 Apr  3 19:48 /app/.heroku/src
  3417634      4 -rw-r--r--   1 herokuishuser herokuishuser       13 Apr  3 19:48 /app/.heroku/python-version
  3417635      4 -rw-r--r--   1 root          root                18 Apr  3 19:48 /app/.release
  3417103      4 -rw-r--r--   1 herokuishuser herokuishuser       15 Apr  3 19:48 /app/requirements.txt

And here's the same after running /start web:

root@8e69bb4d074a:~# find /app -maxdepth 2 -ls | grep -v .git
    73139      4 drwxr-xr-x   4 herokuishuser herokuishuser     4096 Apr  3 19:51 /app
  3157201      4 -rw-r--r--   1 herokuishuser herokuishuser       13 Apr  3 19:51 /app/runtime.txt
  3157198      4 -rw-r--r--   1 herokuishuser herokuishuser       34 Apr  3 19:51 /app/Procfile
    68024      4 drwxr-xr-x   2 root          root              4096 Apr  3 19:51 /app/.profile.d
  3157199      4 -rw-r--r--   1 herokuishuser herokuishuser      423 Apr  3 19:51 /app/app.py
  3157200      4 -rw-r--r--   1 herokuishuser herokuishuser       15 Apr  3 19:51 /app/requirements.txt

Notice the missing files from profile.d.

knazarov avatar Apr 03 '18 19:04 knazarov

So, now I'm even more puzzled. How is it supposed to be used?

It is clear now why herokuish test works fine for me: because during test, both build and start are executed from the same entry point, and the /app directory is not cleaned in between.

knazarov avatar Apr 03 '18 19:04 knazarov

I've finally found the incantation that did it for me:

docker run --rm -t -i -e CACHE_PATH=/cache -e USER=herokuishuser -e PORT=5000 -e DYNO=web.1  -v $(pwd):/app gliderlabs/herokuish /bin/bash

This was reverse engineered from dokku. Mounting the app to /tmp/app does not work.

@josegonzalez please fix the README

knazarov avatar Apr 07 '18 16:04 knazarov

Mind making a pull request with the requisite changes?

josegonzalez avatar Apr 07 '18 17:04 josegonzalez

@josegonzalez to be honest, I don't have an idea why my method worked. And what's the difference between /app and /tmp/app. I'm glad it worked, but I doubt this should be put to README without further considerations.

It would be great if you or someone else familiar with the codebase shed some light on the problem.

knazarov avatar Apr 08 '18 20:04 knazarov

@michaelshobbs this is your baby ;)

josegonzalez avatar Apr 08 '18 21:04 josegonzalez

The readme doesn't say it, but you are supposed to specify $USER environment variable. That variable controls the non-privileged user that will run your app.

This is optional and not required ☝️

This is the normal usage of herokuish to build and run an app 👇

$ docker run -ti -v ${PWD}/buildpacks/buildpack-nodejs/tests/nodejs-express:/tmp/app gliderlabs/herokuish:latest /build

-----> Node.js app detected

-----> Creating runtime environment

       NPM_CONFIG_LOGLEVEL=error
       NODE_VERBOSE=false
       NODE_ENV=production
       NODE_MODULES_CACHE=true

-----> Installing binaries
       engines.node (package.json):  0.10.x
       engines.npm (package.json):   1.2.x
....
$  docker ps -a | grep herokuish
8dd7fe05d726    gliderlabs/herokuish:latest    "/build"    44 seconds ago    Exited (0) 25 seconds ago 
   optimistic_kare
$ docker commit 8dd7fe05d726 nodeapp:latest
$ docker run -ti -p5000:5000 nodeapp:latest /start web
Could not determine a reasonable value for WEB_CONCURRENCY.
This is likely due to running the Heroku NodeJS buildpack on a non-Heroku
platform.

WEB_CONCURRENCY has been set to 1. Please review whether this value is
appropriate for your application.

Server listening on port 5000 in production mode

The build command will take your app repo from the /tmp/app mount and move the built product to /app in the resulting container image. You must then commit that to a local tag and run /start web (replacing web with whatever the appropriate Procfile key you've defined)

The mistake in your flow was that you were attempting to run your app from the gliderlabs/herokuish image instead of the output of the /build container.

We would definitely accept a PR that made this flow more clear in the README.

michaelshobbs avatar Apr 09 '18 21:04 michaelshobbs

Last looked at this quite a while ago, but I've updated my configuration to align with what is being described.

I'm doing all the building within a Dockerfile so I can use Docker Compose.

FROM gliderlabs/herokuish:latest
ADD . /tmp/app
RUN /build
ENV PORT=3000
EXPOSE 3000

Building seems to work fine and I get an image out.

When I try to execute that image with /start, I see some weird behavior. Basically, it's running with the wrong ruby.

It seems like the correct env should be set by procfile-load-profile, where it loops through and sources $app_path/.profile.d/*.sh. However when I start my container with TRACE=true, I see the following:

web_1  | + for file in '/etc/profile.d/*.sh'
web_1  | + source /etc/profile.d/01-locale-fix.sh
web_1  | +++ /usr/bin/locale-check C.UTF-8
web_1  | ++ eval
web_1  | + mkdir -p /app/.profile.d
web_1  | + shopt -u nullglob
web_1  | + hash -r
web_1  | + cd /app
web_1  | + [[ '' == \f\a\l\s\e ]]
web_1  | ++ eval echo ' bin/rails server -p $PORT'
web_1  | +++ echo bin/rails server -p 3000
web_1  | + exec setuidgid herokuishuser bin/rails server -p 3000
web_1  | /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require': cannot load such file -- bundler (LoadError)
web_1  | 	from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
web_1  | 	from /app/bin/spring:5:in `<top (required)>'
web_1  | 	from bin/rails:3:in `load'
web_1  | 	from bin/rails:3:in `<main>'

It appears to source the files within /etc/profile.d/ just fine, but finds nothing within /app/.profile.d. However the output of docker-compose run web ls /app/.profile.d is 00_config_vars.sh ruby.sh, so the files definitely exist.

I'm not super familiar with Heroku. Now that they support running containers, it may just be easier to switch to that method.

ViViDboarder avatar Jun 11 '19 22:06 ViViDboarder

I'm having the same problem. It seems the Python's bin path is not on $PATH so it won't find the gunicorn executable (which was installed via requirements.txt). After running the commands @knazarov suggested:

git clone https://github.com/racktear/herokuish-flask.git
cd herokuish-flask/
docker run --rm -t -i --env USER=herokuishuser -v $(pwd):/tmp/app gliderlabs/herokuish /bin/bash

# then in docker:
/build
/start web

I've found gunicorn executable inside /tmp/cache/.heroku/python/bin but I don't know how to make it available for the application. I've tried running it:

root@14eb38b60c2a:/# /tmp/cache/.heroku/python/bin/gunicorn
bash: /tmp/cache/.heroku/python/bin/gunicorn: /app/.heroku/python/bin/python: bad interpreter: No such file or directory

The reason:

root@14eb38b60c2a:/# head -1 /tmp/cache/.heroku/python/bin/gunicorn
#!/app/.heroku/python/bin/python
root@14eb38b60c2a:/# ls /app/.heroku/python/bin/python
ls: cannot access '/app/.heroku/python/bin/python': No such file or directory

After creating a symlink, it works:

root@14eb38b60c2a:/# ln -s /tmp/cache/.heroku/ /app/.heroku
root@14eb38b60c2a:/# /tmp/cache/.heroku/python/bin/gunicorn
usage: gunicorn [OPTIONS] [APP_MODULE]
gunicorn: error: No application module specified.

But it's still not available on $PATH:

root@14eb38b60c2a:/# gunicorn
bash: gunicorn: command not found

I'm not sure if it's a herokuish $PATH-related issue or if something changed on Python's buildpack which changed the expected behavior.

turicas avatar Jan 14 '20 09:01 turicas

  • dokku relys on buildpacks to build as a specific App (ex: python Django app).

If it show gunicorn not found means this app is not detected as a Python app. For my case, I also encountered this error since I installed npm . Because it is detected as a node.js. Thus, it installed heroku-nodejs-plugin and node instead of python under path: /app/.heroku.

  • To solve this problem: specify the buildpack using dokku command: dokku buildpacks:set <app name> https://github.com/heroku/heroku-buildpack-python.git And then push code again, it will get fix. Check documentation for setting buildpacks if needed.

kant-chen avatar Feb 10 '20 09:02 kant-chen

Closed by #467

josegonzalez avatar Mar 28 '24 23:03 josegonzalez