Rails server is still running in a new opened docker container

Ruby on-RailsDockerDockerfileDocker Compose

Ruby on-Rails Problem Overview


I want to deploy my rails project using Docker. So I use Docker-Compose. But I get one weird error message. When run docker-compose up(this contains db-container with postgresql, redis and web container with rails) I get a

web_1 | => Booting Puma web_1 | => Rails 4.2.4 application starting in production on http://0.0.0.0:3000 web_1 | => Run rails server -hfor more startup options web_1 | => Ctrl-C to shutdown server web_1 | A server is already running. Check /usr/src/app/tmp/pids/server.pid. web_1 | Exiting So I cannot understand why do I get this message, because every time I run docker-compose up, new containers start, not the previous. Even if want to delete these server.pid I am not able to do that, because this container isn't running.

my docker-compose.yml file

web:
  dockerfile: Dockerfile-rails
  build: .
  command: bundle exec rails s -p 3000 -b '0.0.0.0'
  ports:
    - "80:3000"
  links:
    - redis
    - db
  environment:
    - REDISTOGO_URL=redis://user@redis:6379/

redis:
  image: redis

db:
  dockerfile: Dockerfile-db
  build: .
  env_file: .env_db

Dockerfile-rails

FROM rails:onbuild

ENV RAILS_ENV=production

I don't think I need to post all my Dockerfiles

UPD: I fixed it by myself: i just deleted all my containers and ran the docker-compose up once again

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

You are using an onbuild image, so your working direcotry is mounted in the container image. This is very good for developing, since your app is updated in realtime when you edit your code, and your host system gets updated for example when you run a migration.

This also means that your host system tmp directory will be written with the pid file every time a server is running and will remain there if the server is not shut down correctly.

Just run this command from your host system:

sudo rm tmp/pids/server.pid 

This can be a real pain when you are for example using foreman under docker-compose, since just pressing ctrl+c will not remove the pid file.

Solution 2 - Ruby on-Rails

I was stumped by the same problem for a bit until I figured out what was really going on. The real answer is further down... At first, you may want to try something like the following command in your docker-compose.yml file:

command: /bin/sh -c "rm -f /rails/tmp/pids/server.pid && rails server puma"

(I'm using Alpine and busybox to keep things tiny, so no bash! But the -c will work with bash too) This will delete the file if it exists so that you don't get stuck with the problem that the container keeps exiting and sitting there unable to run commands.

Unfortunately, that is NOT a good solution because you add an extra layer of /bin/sh ahead of the server and that prevents the server from getting the stop command. The result is that the docker stop commands won't give a graceful exit and the problem will always happen.

You could just run the rm command using docker-compose up to remove the file and then change the command back to the server and carry on.

However, the real answer is the create a simple docker-entry.sh file and make sure you call it using the exec form Entrypoint Documentation so that signals (like stop) get to the server process.

#!/bin/sh
set -e

if [ -f tmp/pids/server.pid ]; then
  rm tmp/pids/server.pid
fi

exec bundle exec "$@"

NOTE: we use exec on the last line to make sure that rails will be run as pid 1 (i.e. no extra shell) and thus get the signals to stop. And then in the Dockerfile (or the compose.yml) file add the entrypoint and command

# Get stuff running
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["rails", "server", "puma"]

And again, you MUST use the [] format so that it is exec'd instead of run as sh -c ""

Solution 3 - Ruby on-Rails

This is an adapted version of Brendon Whateleys ļ‘ answer for

Docker Compose Solution

1. Create docker-entrypoint.sh

#!/bin/bash
set -e

if [ -f tmp/pids/server.pid ]; then
  rm tmp/pids/server.pid
fi

exec bundle exec "$@"

2. Adapt your docker-compose.yml

services:
  web:
    build: .
    entrypoint: /myapp/docker-entrypoint.sh
    command: ["rails", "server", "-b", "0.0.0.0"]
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"

Notice that you will have to provide the path to where you mounted your app, iE: /myapp

2.5 If you encounter a permission error

Run this in your terminal before running docker-compose up or building your image. Thanks sajadghawami.

chmod +x docker-entrypoint.sh

3. Enjoy never having to remove server.pid manually again

ļŽ‰

Solution 4 - Ruby on-Rails

for my work:

docker-compose run web bash

and then go folder by folder with the command cd (i am using win 7 toolbox) so in the end i use in the bash :

rm tmp/pids/server.pid

Solution 5 - Ruby on-Rails

What I have done, Is to go on the bash shell of docker:

docker-compose run web /bin/bash

then remove the following file

rm tmp/pids/server.pid

Hope that it help!

Solution 6 - Ruby on-Rails

If your solution is using rm to delete the pid file on an entry point, I think a better solution is to tell rails to write the pid file to an ephemeral path, like:

web:
   command: bundle exec rails server -b '0.0.0.0' -p 3000 -P /tmp/rails.pid 

However, most of the time it's caused because a docker container is still running, what I use to do is:

$ docker stop $(docker ps -aq)

That will stop all running containers. This -a for all -q for quiet (only) container ids

Solution 7 - Ruby on-Rails

For ones, who have problem when there is no tmp/pids/server.pid actually exists:

(Docker version 1.11.2, build b9f10c9)

  1. Solution, which worked for me is to add exact command to docker-compose.yml, for example:

    command:
       rails s -b0
    

Having this command, which in fact may simply duplicate Dockerfile's CMD - issue with stale .pid do not appear.

  1. Other option, when you need to use Dockerfile's CMD, is to run with option --build to rebuild image:

    docker-compose up --build
    

Though it takes time, so first solution is more convenient

Solution 8 - Ruby on-Rails

If you are feeling adventurous feel free to search for server.pid in the codebase and check where the pid is getting written into. That way you can check if not allowing it to write fixes the root problem for you. Because seemingly the pid creation helps prevent you from running duplicate services in two different docker containers. But that should be taken care of in docker as it is. If for some reason, it does not, the port collision methodology should definitely take care of that and alert you. Note: I have not tried this approach as yet as that is moving the system in general:)

Alternatively, you could have commands in your Makefile. Where the task does this:

task:
docker-compose stop service_name
docker-compose rm service_name
rm -f ./tmp/pids/server.pid (or relative pathname of your pid file)
docker-compose up service_name

And then vrooom make task in terminal and hit enter. The above task commands assume the service you want to run are in a file named docker-compose.yml

If the name is different then the command

docker-compose stop service_name --> docker-compose -f your-compose-filename.yml stop service_name

so on and so forth.

==================== Came back to update this. So, I did try commenting out my write_pid method functionality. Basically keep the method definition, but not have it do anything. It is working well so far. It does not write the pid at all. If you are running your services in docker, I believe this is completely safe.

Solution 9 - Ruby on-Rails

In your docker-compose.yml file, under the application container itself, you can either use:

> command: ["rm /your-app-path/tmp/pids/server.pid && bundle exec bin/rails s -p 3000 -b '0.0.0.0'"]

or

> command: ["rm /your-app-path/tmp/pids/server.pid; foreman start"]

the reason for either ";" or "&&" is that the latter will send an exit signal if rm fails to find the file, forcing your container to prematurely stop. the prior will continue to execute.

why is this caused in the first place? the rational is that if the server (puma/thin/whatever) does not cleanly exit, it will leave a pid in the host machine causing an exit error.

Solution 10 - Ruby on-Rails

I had this problem when trying to run docker on a group of containers.

The problem was the directory from which I was deploying the container had had a server running that was killed but which didn't remove the tmp/pids/server.pid file at the time it was killed. So every time I deployed, it was there.

So, if that's not your problem, @Brendon Whatley's and @davegson's answers might be necessary. But you may be able to save yourself some pain if it is.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhandkockView Question on Stackoverflow
Solution 1 - Ruby on-RailsTopperHView Answer on Stackoverflow
Solution 2 - Ruby on-RailsBrendon WhateleyView Answer on Stackoverflow
Solution 3 - Ruby on-RailsdavegsonView Answer on Stackoverflow
Solution 4 - Ruby on-Railsmrpepo877View Answer on Stackoverflow
Solution 5 - Ruby on-RailscharlesdgView Answer on Stackoverflow
Solution 6 - Ruby on-RailsArnold RoaView Answer on Stackoverflow
Solution 7 - Ruby on-RailsDaniel GarmoshkaView Answer on Stackoverflow
Solution 8 - Ruby on-RailsSheetal KaulView Answer on Stackoverflow
Solution 9 - Ruby on-RailsmirageglobeView Answer on Stackoverflow
Solution 10 - Ruby on-RailsDerrell DurrettView Answer on Stackoverflow