Rails server is still running in a new opened docker container
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
If a Rails server seems to be "still running" when you start what you think is a new Docker container, the cause is usually one of three things: you are not actually in a new container, an older container is still bound to the port, or a shared file such as tmp/pids/server.pid is making Rails think the old server is still alive. Containers feel isolated, but bind mounts, volumes, and Docker Compose service reuse can preserve state in ways that surprise people.
First confirm what is actually running
The first mistake is often assuming a new shell means a new container. In Docker, docker exec opens a shell inside an existing running container, while docker run creates a new one.
Check the active containers first.
If the Rails service is already running, opening another shell with docker exec -it web bash does not create a fresh environment. It just joins the existing one where the server process may still be PID 1 or another live process.
Port binding can make the old server look like the new one
If an older container is still publishing port 3000, requests to localhost:3000 will keep hitting that old container even after you start another one.
If two containers try to use the same host port, Docker usually rejects the second bind. More often, the real confusion is that the old container never stopped, so the browser is still reaching it.
Rails often leaves a PID file in a shared mount
In development, a common Compose setup mounts the app directory from the host into the container. That means files under tmp can persist across container lifecycles. If tmp/pids/server.pid survives, Rails may refuse to start and report that a server is already running.
A typical fix is to remove the PID file before booting.
Many teams make this part of the container startup command.
That does not fix every container problem, but it does solve one of the most common Rails-in-Docker startup issues.
Named volumes and bind mounts preserve state on purpose
Docker containers are disposable, but mounted storage is not. If your Compose file mounts the project directory or a named volume, files created by the previous container can appear in the next one.
That is why a "new container" can still see:
- old PID files
- cached gems
- socket files
- development logs
- temporary state under the mounted app directory
This is normal Docker behavior, not a leak between unrelated containers.
Rebuild versus recreate are different operations
Another source of confusion is the difference between rebuilding an image and recreating a container. docker compose build creates a new image layer set. It does not automatically remove old containers, volumes, or mounted files.
If you need a cleaner restart path, use commands that stop and recreate the service intentionally.
If you also need to remove anonymous volumes, add the appropriate cleanup flags carefully. Do not remove volumes casually if they hold important data.
Logs tell you whether Rails is actually running
When the situation is unclear, inspect logs instead of guessing.
If Rails failed on a PID file, port bind, or boot error, the logs will usually say so directly. That is faster than treating the problem as a Docker mystery.
Common Pitfalls
- Using
docker execand assuming it created a new container. - Forgetting that an older container may still be serving the same host port.
- Leaving
tmp/pids/server.pidin a bind-mounted project directory. - Rebuilding the image without actually recreating the container.
- Ignoring logs and trying to diagnose the issue only from browser behavior.
Summary
- A truly new container can still see old state if files come from a bind mount or volume.
- '
docker execenters an existing container; it does not create a fresh one.' - Old containers bound to port
3000can make it look like the new container is serving traffic. - Rails PID files under
tmp/pidsare a frequent cause of false "server already running" errors. - Use
docker ps, Compose logs, and an explicit startup command that removes stale PID files.
Related reading
- Rancher with cattle vs Rancher with Kubernetes vs Standalone Kubernetes
- Re-using environment variables in docker-compose.yml
- Re-using existing volume with docker compose
- Read-only filesystem pod with Spring Boot application on Kubernetes
- Raise an event whenever a property's value changed?
- RDS with Cloud Formation and AZ issues
- Readiness probe for statefulset, not individual pod/container
- Recommended GCE service account authentication inside Docker container?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.