Part of being a software developer trainee is to be baffled by facts that are obvious in hindsight. Have you ever said or done any of the following things:
“Things are not working as they are supposed to be”,
“The exact same solution works for my colleague but not me”,
or spent hours to find a simple solution?
If you have at least one out of three points, then you should continue reading, because today I’m writing about some reasons and mechanism to tackle such situations in the future without wasting too much time.
I’m a software developer trainee at BetterDoc for 4 months now and one of my exercises includes setting up a process for one of my Ruby applications where CircleCI fetches the most recent commit from GitHub, builds the Docker image, runs unit tests and if successful, deploys the image to Heroku.
I already managed to have CircleCI build the Docker image. Its configuration was based on a tutorial (this will become important later on). Units tests were finally running smoothly and checking the PostgreSQL statements successfully. So the container was deployed to Heroku without a hitch.
Only every time I opened the app’s URL in a browser, Heroku showed me an “Application Error” and referred me to its logs. There I saw that Sinatra kept changing ports instead of using 80
as I wanted it to.
In addition, there was this message: heroku[router]: at=error code=H14 desc="No web processes running"
Of course there’s no web process running on port 80, because it’s ignoring the setting, so the browser can’t access it, I thought…
Changing the number of dynos didn’t help. Heroku’s FAQ read "Application Error" or similar is always caused by your own application code
, so I spent the next few hours trying different settings in my Sinatra’s Ruby script, the Dockerfile, CircleCI’s config.yml, and altering environment variables. Every time I changed something I had to push a commit with a release
tag so it gets deployed and waiting for CircleCI to finish its magic…
Rather frustrated I went home for the evening. Next morning I mentioned the problem to a colleague and he explained how Heroku worked, in good explain it like I’m 9 manner. Though I’ve read introductions on Heroku before, it clarified the process quite somewhat - especially the fact that Heroku intentionally sets random ports every time the container is started. But still I could not see the reason for the problem’s.
So I checked Heroku’s error message again - and suddenly remembered that CircleCI’s config.yml (which I had copied from the earlier mentioned tutorial) had these lines:
- run:
name: Deploy Heroku Docker Container
command: |
heroku container:push worker -a excercise-appointment-mgmt
heroku container:release worker -a excercise-appointment-mgmt
This basically tells Heroku to push the built Docker image into its registry, create a release, and start a container with the app’s source code and the language runtime in it. But the type of the container is worker
. Worker dynos are not accessible by a web browser. That was the problem’s cause.
After I reverted all the trial and error settings I made the previous day and changed worker
to web
, the error message was gone and the first view of Sinatra read, as intended: Hello world.
Alright, so what am I taking away from this for the future?
- Read the error message thoroughly!
- Always read the code/config you copy.
- After you learned something new, read the code/config again - especially while trying to figure out a bug: you might just have learned the solution to your problem.
- And don’t be too embarrassed to ask for help when you realise you’re wasting too much time to figure it out yourself.
Further reading: Heroku’s article on Container Registry & Runtime (Docker Deploys)