When using Docker to run your Rails apps in development, you might come across a leftover
server.pid file in your app’s
This file is created when you run
rails server to start your app. If your container is not shut down properly, this
server.pid file is not removed.
This prevents you from starting a new container; as the file is copied into the new container, you will be confronted with the following message when you try to run your app:
web_1 | A server is already running. Check /usr/src/app/tmp/pids/server.pid. ... web_1 | Exiting
Of course, the simple way to resolve this is to remove the offending file (
$ rm tmp/pids/server.pid) and restart your container.
This can quickly become annoying, though, and won’t help if (for example) you are trying to scale the number of containers in your development environment. Every new container will inherit the
tmp/pids/server.pid file, and so exit immediately.
Using an Entrypoint File
To properly handle this situation is to use a docker entrypoint file. This is a simple shell script that becomes the command that is called when your container starts.
Entrypoint files are commonly used to set up or configure a container at runtime. For example, when you run the
mariadb containers, their entrypoint files create and configure a default database.
An example entrypoint file for our Rails app to resolve the problem above might be:
#!/bin/sh rm -f tmp/pids/server.pid bin/rails server -b 0.0.0.0 -p $PORT
Save this file as
docker-entrypoint.sh in your app’s folder (in the same location as
Dockerfile). You’ll also need to make sure it is executable by modifying its permissions:
$ chmod u+x ./docker-entrypoint.sh
Next, in your app’s
Dockerfile, set the
CMD line to run your new entrypoint file:
# Dockerfile FROM ruby:2.5 # ... EXPOSE $PORT CMD ./docker-entrypoint.sh
Note that you could use the
_ENTRYPOINT_ command in this instance, but as we’re supplying default arguments (
_-p_) to the
_bin/rails_ command, I prefer to use
_CMD_ in line with the Docker documentation.
Alternatively, if you only want to use your entrypoint file for local development, you could simply override the container’s default command in your
# docker-compose.yml # ... web: build: . command: ./docker-entrypoint.sh # ...
Now you can spin up your container(s) in the normal way using Docker compose:
$ docker-compose up -d --scale web=2
In this simple example, you’ve seen how to use an entrypoint file to initialise the state of a container at runtime. You can also use entrypoint files to perform much more complicated setup, such as creating runtime files and databases, configuring local services, and more.