Issues deploying our first Rails & React app

Hi! Deploying is new to me and my group and we’re hitting some issues getting through the errors along the way.

We’re now getting blocked in the build stage with the npm install command and I’m not sure why. Ours is a Rails React app and our client is in a separate directory and my hunch is that there are some issues between the dockerfile and package.json files (of which there are two, one in the root, and one in the client).

Here is our package.json in the root

And here is the terminal error output (I’ve removed yarn because we’re set up with npm so that should be resolved as a concern in the output afaik)

Also as a note, our early errors were about using an earlier node version so I’ve updated to 20.1.0 which removed those issues- just in case that’s helpful context at all!

Thanks for any help!

What I see is WORKDIR /rails/client, and from there you are trying to do cd client. That would only work if there was a /rails/client/client directory.

What you probably want to do is remove the WORKDIR statement and change ./ to client/ in the next COPY line. I’ll go further and guess that you need to copy the entire client directory at this point as there are undoubtedly files in that directory that you will want to build.

The goal of dockerfile-rails is to generate correct and complete Dockerfiles based on inspecting the application and (when necessary) flags are specified. I’d be very interested in your feedback on what changes you needed to make and how better to detect when to apply those changes.

Thanks! I’ve tried that out but no luck so far. It looks like docker is using the scripts from the root package.json instead of the client package.json so it’s breaking. I’ve added my dockerfile below in case that helps pinpoint any other issues that I’m missing! I could totally be missing something really obvious though!

# syntax = docker/dockerfile:1

# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile

FROM node:$NODE_VERSION-slim as client

# WORKDIR /client

ENV NODE_ENV=production

# Install node modules
# COPY --link client/package.json client/package-lock.json client/
COPY client .
RUN npm install

# build client application
# COPY --link client client/
COPY client .
RUN npm run build

FROM ruby:$RUBY_VERSION-slim as base

LABEL fly_launch_runtime="rails"

# Rails app lives here
WORKDIR /rails

# Set production environment
ENV RAILS_ENV="production" \
    BUNDLE_WITHOUT="development:test" \

# Update gems and bundler
RUN gem update --system --no-document && \
    gem install -N bundler

# Throw-away build stage to reduce size of final image
FROM base as build

# Install packages needed to build gems and node modules
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential curl libpq-dev node-gyp pkg-config python-is-python3

# Install Node.js
ENV PATH=/usr/local/node/bin:$PATH
RUN curl -sL | tar xz -C /tmp/ && \
    /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
    rm -rf /tmp/node-build-master

# Install application gems
COPY --link Gemfile Gemfile.lock ./
RUN bundle install && \
    bundle exec bootsnap precompile --gemfile && \
    rm -rf ~/.bundle/ $BUNDLE_PATH/ruby/*/cache $BUNDLE_PATH/ruby/*/bundler/gems/*/.git

# Install node modules
COPY --link package.json package-lock.json ./
RUN npm install

# Copy application code
COPY --link . .

# Precompile bootsnap code for faster boot times
RUN bundle exec bootsnap precompile app/ lib/

# Final stage for app image
FROM base

# Install packages needed for deployment
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y postgresql-client && \
    rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Run and own the application files as a non-root user for security
RUN useradd rails --home /rails --shell /bin/bash
USER rails:rails

# Copy built artifacts: gems, application
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build --chown=rails:rails /rails /rails

# Copy built client
COPY --from=client --chown=rails:rails /rails/client/build /rails/public

# Deployment options

# Entrypoint prepares the database.
ENTRYPOINT ["/rails/bin/docker-entrypoint"]

# Start the server by default, this can be overwritten at runtime
CMD ["./bin/rails", "server"]

I believe the commented out lines in the above are the ones you want.

You can control which script is run by setting the WORKDIR. Alternately, you can add a clientinstall script to the package.json in the root directory that matches the current build script minus the build step.