Docker restart stuck in loop for rails application

Viewed 418

I have a containerized rails app running in a VPS.

After building the image, my deploy script does something like the following to run the container:

docker run \
    -v /home/user/my-app/public:/home/rails/my-app/public \
    -v /home/user/my-app/log:/home/rails/my-app/log \
    -p 1337:1337 \
    --restart=always \
    -d \
    my-image

It just mounts some volumes and sets the restart policy to always. Up to here everything works fine.

However sometimes my rails app runs out of memory (can't fix this in the short-term) and as a result docker kills the container. When this happens, I expect the rails app to be restarted automatically.

However sometimes docker gets stuck in a loop restarting the container, because as soon as it is restarted, rails says that a server is already running and exits. This is the result of running docker logs

=> Booting Puma
=> Rails 6.1.3.1 application starting in production 
=> Run `bin/rails server --help` for more startup options
A server is already running. Check /home/rails/my-app/tmp/pids/server.pid.
Exiting

I'm not totally sure why that file remains there after the container is stopped and restarted. Shouldn't this file be ephemeral? Also I'm not sure how to go and fix this. The documentation on docker restart policy doesn't go in depth on what restarting actually does. Maybe I have to add a docker-entrypoint.sh and manually remove the file there? And if so, maybe there is a recommended setup for a production rails app running on a VPS?

1 Answers

Turns out restart doesn't rm the container and so data written in the container is persisted across restarts including tmp/pids/server.pid.

Looking for more info I found these two options:

  • Remove the server.pid file in a docker-entrypoint.sh file. Maybe using rake tmp:pids:clear as per the rails documentation.
  • Mount tmp/pids to a tmpfs. --mount type=tmpfs,destination=/home/rails/my-app/tmp/pids

Also there is a sample in the docker documentation for a rails app and it goes for the first option: https://docs.docker.com/samples/rails/

Related