Cannot get response from Rails app on defined Port

I’ve tried to hit my rails app after starting with docker with no success. The app runs fine if I start with docker compose but when I run using a straight docker command I can’t access it.

Running with

docker build -t my-app .
docker run --env-file=.env.staging --publish 80:3000 my-app

entrypoint.sh

#!/usr/bin/env bash
bundle install
yarn install
yarn build
yarn build:css
bin/rails assets:precompile
bin/rails server -b 0.0.0.0

Dockerfile

FROM ruby:3.0.3
RUN apt-get update -qq && apt-get install -y nodejs npm postgresql-client
RUN npm install -g yarn
RUN gem update --system

# use a global path instead of vendor
ENV GEM_HOME="/usr/local/bundle"
ENV BUNDLE_PATH="$GEM_HOME"
ENV BUNDLE_SILENCE_ROOT_WARNING=1
ENV BUNDLE_APP_CONFIG="$GEM_HOME"
ENV PATH="$GEM_HOME/bin:$BUNDLE_PATH/gems/bin:${PATH}"

# make 'docker logs' work
ENV RAILS_LOG_TO_STDOUT=true

# copy the source
WORKDIR /app
COPY . /app
RUN rm -f tmp/pids/server.pid
RUN bundle install

# build and start
ENTRYPOINT ["./entrypoint.sh"]

docker-compose.yml

version: '3'
services:
  backend:
    container_name: rails-app
    build :
      context: ..
      dockerfile: ./Dockerfile
    working_dir: /home/app
    env_file:
      - ../.env
    volumes:
      - ..:/home/app
    ports:
      - "3001:3000"
    stdin_open: true
    tty: true
volumes:
  gems:
    driver: local

Project file structure:

app
bin
...
Dockerfile
entrypoint.sh
docker/docker-compose.yml

Can you show the compose file and how you tried to access the app so we can compare the working and the non-working solutions?

Check your filewalls too in your network and on the Docker host like ufw which can restrict access to some Docker network. If you find any firewall on your machine you can temporarily turned them off to see if that helps.

I"ve updated. When running docker-compose we use a different .env and the port is 3001 instead of 80 and it works fine.

I’m on a mac and shouldn’t think I have any firewalls running. One thing to note when I hit the expected port number it says forbidden so I want to feel something is happening but the end result is I can’t access the app.

Have you tried port 3001 or any other port (not 80) with the docker command?

Yes, I tried ports 80, 3000, and 3001. I also tried using the -p instead of --published, not even sure what the published does but saw it somewhere. None of these solved the problem. I also can’t stop the process with a Ctrl-C afterward. I have to run docker kill to stop it. I feel so close. The fact it works with docker-compose makes this very confusing for me. I guess docker-compose is doing something extra that I’m not doing.

Tried

docker run --env-file=.env.staging -p 3001:3000 my-app

Does your app depend on a /home/app folder? I don’t see you define that same bind mount when not using Compose?

Aside, why are you (re-)creating the app in the entrypoint.sh? That basically rebuilds the app whenever starting the container. I’d do that only once, when creating the image (that you’ll use later when starting it as a container.)

That’s also related to your entrypoint. See the note about “Configure app as PID 1” in Best practices for writing Dockerfiles | Docker Documentation.

1 Like

@rimelek and @avbentem thanks for the tips. I did update the docker-compose so the paths are consistent and I removed the extra create and now my entrypoint.sh looks like the following.

#!/usr/bin/env bash

bin/rails assets:precompile
bin/rails server -b 0.0.0.0

So… I actually fixed the issue but realized a new one. I started the app with RAILS_ENV=development and it ran and I could hit the app on the expected port! However, when I set it back to RAILS_ENV=staging, it does not work. I’ve been testing staging all this time then I thought to try setting the environment to development and it works. Now I’m trying to understand why it won’t work when set to staging. Almost there. Ran without docker and app starts in staging environment but start with docker run and it doesn’t work when set to staging.

Not when using using docker run, or also not when using Compose? And what does “does not work” mean exactly? What error do you see? Anything in the output that tells you things have even started?

If it doesn’t work regardless using Compose or docker run: given the -b 0.0.0.0 I’d think the server would listen to any client’s IP address, but maybe that’s not the case for your RAILS_ENV=staging.

It may help to show what is different in the configurations for both environments. Could it be listening to a different internal port? Are you sure both environments even exist?

Aside, unrelated to your issues: why do you need this in the entrypoint? Can’t you move it to a RUN command in the Dockerfile?