Rails 8 app successful deploy but container stops

3 months ago

Hi all – I’m tearing my hair out and would love a fresh set of eyes.

What I’m deploying

  • Rails 8 / Ruby 3.2.2 app (Hotwire, PostgreSQL)

  • Using Railway’s “Rails on PostgreSQL” guide for reference

Railway setup

  • One GitHub service + one PostgreSQL service

  • Environment variables (all in Railway → Variables):

    RAILS_ENV=production 
    DATABASE_URL=<railway Postgres URL> 
    RAILS_MASTER_KEY=<key from config/master.key> 
  • Custom start command bin/rails db:prepare && bin/rails server -b :: (from the guide) and also tried bin/rails db:prepare && bin/rails server -b :: --port $PORT

  • Build detects my Dockerfile

  • Shows successful deploy status

  • Runtime logs show nothing but "Starting Container" and sometimes "Stopping Container"

Am I missing something?

Solved$10 Bounty

15 Replies

johntad110
FREE

3 months ago

Hey ... so railway is detecting ur Dockerfile and completes the build. Right?
If so, Does ur Dockerfile actually run your app?
Have you set the correct ENTERYPOINT or CMD ?
something like CMD ["bin/rails", "server", "-b", "::", "-p", "3000"]


3 months ago

in order to start the server you need a foreman command or rails server

ENTRYPOINT ["/rails/bin/docker-entrypoint"]

CMD ["bundle", "exec", "foreman", "start", "-f", "Procfile"] 

inside docker-entrypoint

#!/bin/bash -e

echo "prepare db"
# If running the rails server then create or migrate existing database
if [ "$1" == "bundle" ] && [ "$2" == "exec" ] && [ "$3" == "foreman" ] && [ "$4" == "start" ]; then
  ./bin/rails db:prepare
  echo "prepared db"
fi

exec "${@}"

with rails server

ENTRYPOINT ["/rails/bin/docker-entrypoint"]

CMD ["bin/rails", "server"]
if [ "${@: -2:1}" == "bin/rails" ] && [ "${@: -1:1}" == "server" ]; then
  ./bin/rails db:prepare
fi

make sure to adjust the path to the `docker-entrypoint`


johntad110

Hey ... so railway is detecting ur Dockerfile and completes the build. Right?If so, Does ur Dockerfile actually run your app?Have you set the correct ENTERYPOINT or CMD ?something like CMD ["bin/rails", "server", "-b", "::", "-p", "3000"]

3 months ago

At the end of the file is

# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]

# Start server via Thruster by default, this can be overwritten at runtime
EXPOSE 80
CMD ["./bin/thrust", "./bin/rails", "server"]

That came by default when I started the Rails 8 app.


alexwebgr

in order to start the server you need a foreman command or rails serverENTRYPOINT ["/rails/bin/docker-entrypoint"] CMD ["bundle", "exec", "foreman", "start", "-f", "Procfile"]inside docker-entrypoint#!/bin/bash -e echo "prepare db" # If running the rails server then create or migrate existing database if [ "$1" == "bundle" ] && [ "$2" == "exec" ] && [ "$3" == "foreman" ] && [ "$4" == "start" ]; then ./bin/rails db:prepare echo "prepared db" fi exec "${@}"with rails serverENTRYPOINT ["/rails/bin/docker-entrypoint"] CMD ["bin/rails", "server"]if [ "${@: -2:1}" == "bin/rails" ] && [ "${@: -1:1}" == "server" ]; then ./bin/rails db:prepare fimake sure to adjust the path to the `docker-entrypoint`

3 months ago

Yeah same as above. docker-entrypoint has this:

#!/bin/bash -e

# Enable jemalloc for reduced memory usage and latency.
if [ -z "${LD_PRELOAD+x}" ]; then
    LD_PRELOAD=$(find /usr/lib -name libjemalloc.so.2 -print -quit)
    export LD_PRELOAD
fi

# If running the rails server then create or migrate existing database
if [ "${@: -2:1}" == "./bin/rails" ] && [ "${@: -1:1}" == "server" ]; then
  ./bin/rails db:prepare
fi

exec "${@}"

Again, all by default with Rails 8, I didn't change anything


adhdcoder

Yeah same as above. docker-entrypoint has this:#!/bin/bash -e # Enable jemalloc for reduced memory usage and latency. if [ -z "${LD_PRELOAD+x}" ]; then LD_PRELOAD=$(find /usr/lib -name libjemalloc.so.2 -print -quit) export LD_PRELOAD fi # If running the rails server then create or migrate existing database if [ "${@: -2:1}" == "./bin/rails" ] && [ "${@: -1:1}" == "server" ]; then ./bin/rails db:prepare fi exec "${@}"Again, all by default with Rails 8, I didn't change anything

brandon
HOBBY

3 months ago

I’ve seen that exact entrypoint logic before with new Rails apps.

But I think the main issue is with the CMD using ./bin/thrust, which might not behave the way Railway expects. Since Railway looks for a process listening on $PORT, and that might not be happening here, it shuts things down thinking the container failed.

Try replacing the CMD entirely with this in your Dockerfile:

```dockerfile

CMD ["bin/rails", "server", "-b", "0.0.0.0", "-p", "${PORT}"]

Or just override it in the Railway dashboard with:

bin/rails db:prepare && bin/rails server -b 0.0.0.0 -p $PORT


brandon

I’ve seen that exact entrypoint logic before with new Rails apps.But I think the main issue is with the CMD using ./bin/thrust, which might not behave the way Railway expects. Since Railway looks for a process listening on $PORT, and that might not be happening here, it shuts things down thinking the container failed.Try replacing the CMD entirely with this in your Dockerfile:```dockerfileCMD ["bin/rails", "server", "-b", "0.0.0.0", "-p", "${PORT}"]Or just override it in the Railway dashboard with:bin/rails db:prepare && bin/rails server -b 0.0.0.0 -p $PORT

3 months ago

I've overwritten it in the Railway dashboard exactly like that and that didn't work. Let me try changing the dockerfile when I'm back on my computer and see.


adhdcoder

I've overwritten it in the Railway dashboard exactly like that and that didn't work. Let me try changing the dockerfile when I'm back on my computer and see.

brandon
HOBBY

3 months ago

Yeah makes sense from what I’ve seen, overriding the command in the dashboard doesn’t always fully bypass what’s defined in the Dockerfile, especially if the image has its own ENTRYPOINT logic baked in.

Once you swap the CMD in the Dockerfile directly, that should give you a clean slate. Definitely let us know how it goes. I'm curious if removing thrust from the chain finally gets it working.


3 months ago

you don't need to / probably shouldn't be overriding this from the railway dashboard. maybe just remove the "./bin/thrust" and make sure the port in the Dockerfile matches the one on the Generated domain


3 months ago

Changed

CMD ["./bin/thrust", "./bin/rails", "server"]

to

CMD ["bin/rails", "server", "-b", "0.0.0.0", "-p", "${PORT}"]

and also tried

CMD ["./bin/rails", "server"]

And still same issue it's so weird, it just does nothing after the container starts. It was at least doing some type of error in the deploy logs before when I didn't have postgresql connected but now it's just "successful" with nothing going on


Anonymous
FREE

3 months ago

Hey! Here’s a few things that might help you fix the container shutdown issue:

What you’re doing right

  • Dockerfile is detected

  • Environment variables are correctly set :

RAILS_ENV=production

DATABASE_URL=<your PostgreSQL URL>

RAILS_MASTER_KEY=<your master key>

  • Deploy status shows as successful

Likely issue

Your container is likely exiting because the Rails server process doesn’t stay alive — this is often due to incorrect binding address or port configuration.

Fix suggestion

  1. Use 0.0.0.0 instead of :: for binding.
    Railway expects an IPv4 address.

bin/rails db:prepare && bin/rails server -b 0.0.0.0 -p $PORT

  1. Make sure you’re using $PORT.
    Railway injects this variable — your app must bind to it.

  2. Optional: Add a Procfile if you’re not already using one:

web: bin/rails server -b 0.0.0.0 -p $PORT

  1. If logs only show “Starting/Stopping Container”, try adding logging inside your Dockerfile or entrypoint to verify the server process is starting and staying alive.


Hey! Here’s a few things that might help you fix the container shutdown issue:What you’re doing rightDockerfile is detectedEnvironment variables are correctly set :RAILS_ENV=productionDATABASE_URL=<your PostgreSQL URL>RAILS_MASTER_KEY=<your master key>Deploy status shows as successfulLikely issueYour container is likely exiting because the Rails server process doesn’t stay alive — this is often due to incorrect binding address or port configuration.Fix suggestionUse 0.0.0.0 instead of :: for binding.Railway expects an IPv4 address.bin/rails db:prepare && bin/rails server -b 0.0.0.0 -p $PORTMake sure you’re using $PORT.Railway injects this variable — your app must bind to it.Optional: Add a Procfile if you’re not already using one:web: bin/rails server -b 0.0.0.0 -p $PORTIf logs only show “Starting/Stopping Container”, try adding logging inside your Dockerfile or entrypoint to verify the server process is starting and staying alive.

3 months ago

  1. Changed to 0.0.0.0

  1. Using $PORT

  1. Added a Procfile for production

Still same issues

  1. I've tried logging a lot and all seems like it should be working fine, but I don't get far when all it says is "Starting Container" and that's it on that end.


3 months ago

So... I rage deleted the Dockerfile... and it worked lol

Build timed out the first time, but redeployed with these changes:

Custom Start Command is bin/rails db:prepare && bin/rails server -b 0.0.0.0 -p $PORT

Procfile I changed to web: bin/rails server -b 0.0.0.0 -p ${PORT:-3000} taking from the Rails 7 template that railway has.

Generated a domain listening on Port 8080

And yeah, it works, but that's not the fix I wanted. I wanted to use Docker if I could. I still don't get why it's not working and stalling out after starting the container. All local tests with Docker work fine too.


emifunes91
FREE

3 months ago

Hey! I dug into the full thread and I believe the issue is related to a mismatch between how Railway expects containers to behave and how bin/thrust is handling the Rails server.

---

Root cause:

Your Dockerfile defines:

```dockerfile

CMD ["./bin/thrust", "./bin/rails", "server"]

But thrust likely forks or delegates the Rails process in a way that Railway can’t track — so Railway shuts down the container assuming it crashed, since it sees no active foreground process.

Verified fix (keeping Docker):

  1. Replace the CMD in the Dockerfile with: CMD ["bin/rails", "server", "-b", "0.0.0.0", "-p", "${PORT}"]

  2. Ensure you don’t override this in the Railway dashboard — Railway will use the CMD from your Dockerfile if a valid ENTRYPOINT exists.

  3. Optional: add ENTRYPOINT ["./docker-entrypoint.sh"] that logs before calling exec "$@".

  4. Confirm the app listens on $PORT — Railway requires this to detect success.

    If you still want to use thrust, you’d have to ensure it:

    • runs Rails as PID 1

    • doesn't fork in background

    • or wrap it in exec to promote the child to PID 1.

    But best practice: remove thrust, use rails server directly in Docker.

    Let me know if you want a working Dockerfile template! Happy to help

---


3 months ago

yes exactly! the server never starts so the container stops

if you added a Procfile then i would like to refer you to my original answer https://station.railway.com/questions/rails-8-app-successful-deploy-but-contai-28123617#qkwz

if want to generate a new Dockerfile you can add this gem. it will scan your setup and create a Dockerfile and related files, you might need to revert some changes it makes.

bundle add dockerfile-rails --optimistic --group development
bin/rails generate dockerfile

emifunes91

Hey! I dug into the full thread and I believe the issue is related to a mismatch between how Railway expects containers to behave and how bin/thrust is handling the Rails server.---Root cause:Your Dockerfile defines:```dockerfileCMD ["./bin/thrust", "./bin/rails", "server"]But thrust likely forks or delegates the Rails process in a way that Railway can’t track — so Railway shuts down the container assuming it crashed, since it sees no active foreground process. Verified fix (keeping Docker):Replace the CMD in the Dockerfile with: CMD ["bin/rails", "server", "-b", "0.0.0.0", "-p", "${PORT}"]Ensure you don’t override this in the Railway dashboard — Railway will use the CMD from your Dockerfile if a valid ENTRYPOINT exists.Optional: add ENTRYPOINT ["./docker-entrypoint.sh"] that logs before calling exec "$@".Confirm the app listens on $PORT — Railway requires this to detect success.If you still want to use thrust, you’d have to ensure it:runs Rails as PID 1doesn't fork in backgroundor wrap it in exec to promote the child to PID 1.But best practice: remove thrust, use rails server directly in Docker.Let me know if you want a working Dockerfile template! Happy to help---

2 months ago

Did this but without strings, so CMD bin/rails server -b 0.0.0.0 -p ${PORT} and it worked. I think the override in the Railway dashboard is what was messing me up.


Status changed to Solved chandrika about 2 months ago