herokuish
herokuish copied to clipboard
Cannot execute any Procfile commands
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
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
@racktear do you have an example repository - with instructions - we can use to verify that behavior?
@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.
@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.
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.
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 createsprofile.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, andprofile.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
.
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.
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
Mind making a pull request with the requisite changes?
@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.
@michaelshobbs this is your baby ;)
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
.
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.
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.
- 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.
Closed by #467