Failing to deploy after generating new Dockerfile for upgraded Rails 7.1.2 app

Some history:
I first deployed my Rails 7.0 app in January, with Sqlite.
In July I manually did the migration to the V2 Platform.
In August the App started running out of memory and crashed, so I increased the system memory.
I’ve deployed the app succesfully having upgraded to Rails 7.0.7.2

My Sqlite database is mounted in fly.tom like so:

[[mounts]]
  source = "recipe_data"
  destination = "/mnt/recipe_data"

About a week ago I added Litestack to the Rails app. The App deployed to fly.

Failing to redeploy app
Today I’ve upgraded the app to Rails 7.1.2 and everything works locally. When I run fly deploy I get the follwoing error.

“Error: timeout reached waiting for health checks to pass for machine 148…”

And a WARNING The app is not listening on the expected address

Running fly machine status 148..... and fly doctor are all good.

I’ve added bundle add dockerfile-rails to the project and generated a new Dockerfile.

When I try to deploy with the new Dockerfile it fails with:

Errno::EACCES: Permission denied @ dir_s_mkdir - /mnt/recipe_data

When I try giving permissions to /mnt/recipe_data in the Dockerfile build process, I get an error that the file doesn’t exist.

Lastly I tried updating fly.toml, all to no avail

[[mounts]]
  source = "recipe_data"
  destination = "/data"

The article by Brad Gessler Sqlite & Rails in Production · The Ruby Dispatch suggests states that fly adds this volume configuration to the fly.toml file.

[[mounts]]
  source = "data"
  destination = "/data"

However, I had already have my Sqlite databse at /mnt/recipe_data

Help: How can I deploy the Rails 7.1.2 version. How do I have to update the Dockerfile to keep using my exisiting Database?

Try:

  destination = "/mnt/recipe_data"

I’m assuming by this you mean that you had your database inside that directory. If this assumption is incorrect, can you describe where your databse is?

Update
After runing Rails.gem_version in the Rails console I’ve just realised that the Rails 7.1.2 version did deploy (with my “old” Dockerfile). When is it necessary to create a new Dockerfile?
So it seems I should address the WARNING and the health check timout. Any help with that appreciated =o)

--> Pushing image done
image: registry.fly.io/rezeptbuch:deployment-01HF3...
image size: 547 MB

Watch your deployment at https://fly.io/apps/rezeptbuch/monitoring

Running rezeptbuch release_command: bin/rails fly:release

-------
 ✔ release_command 6e82573f067118 completed successfully
-------
-------
Updating existing machines in 'rezeptbuch' with rolling strategy

WARNING The app is not listening on the expected address and will not be reachable by fly-proxy.
You can fix this by configuring your app to listen on the following addresses:
  - 0.0.0.0:0
Found these processes inside the machine with open listening sockets:
  PROCESS              | ADDRESSES
-----------------------*----------------------------------------
  /.fly/hallpass       | [fdaa:1:2bb2:a7b:c555:ae25:e105:2]:22
  puma 5.6.7 (tcp://0. | 0.0.0.0:8080


-------
 ✖ Machine 148e46XXXXXXXX [app] update failed: timeout reached waiting for health checks to pass for machine 148e46XXXXXXXX: failed to get VM 148e46…
-------
Error: timeout reached waiting for health checks to pass for machine 148e46XXXXXXXX: failed to get VM 148e460b79e698: Get "https://api.machines.dev/v1/apps/rezeptbuch/machines/148e46XXXXXXXX": net/http: request canceled
You can increase the timeout with the --wait-timeout flag

Hello rubys
When I have the correct database destination in fly.toml

[[mounts]]
  source = "recipe_data"
  destination = "/mnt/recipe_data"

and when I generate a new Dockerfile,
that’s when I get the error >Errno::EACCES: Permission denied @ dir_s_mkdir - /mnt/recipe_data

How do I correctly add the destination in the Dockerfile?

I’ve reverted back to using my old Dockerfile. I’ve realised that it did not fail to deploy. I just have a Warning and a health check timeout.

For the warning I think I need to add the follwoing to my fly.toml

[[services]]
  protocol = "tcp"
  internal_port = 3000
  processes = ["app"]

My fly.toml

# fly.toml app configuration file generated for rezeptbuch on 2023-08-04T10:15:22+02:00
#

...

console_command = "/rails/bin/rails console"

[experimental]
  auto_rollback = true

[build]
  [build.args]
    BUILD_COMMAND = "bin/rails fly:build"
    SERVER_COMMAND = "bin/rails fly:server"

[deploy]
  release_command = "bin/rails fly:release"

[env]
  PORT = "8080"

[[mounts]]
  source = "recipe_data"
  destination = "/mnt/recipe_data"

[[services]]
  protocol = "tcp"
  internal_port = 3000
  processes = ["app"]

  [[services.ports]]
    port = 80
    handlers = ["http"]
    force_https = true

  [[services.ports]]
    port = 443
    handlers = ["tls", "http"]
  [services.concurrency]
    type = "connections"
    hard_limit = 25
    soft_limit = 20

  [[services.tcp_checks]]
    interval = "15s"
    timeout = "2s"
    grace_period = "1s"

[http_service]
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ["app"]

[[statics]]
  guest_path = "/app/public"
  url_prefix = "/"

My (hacked together) “old” Dockerfile

# syntax = docker/dockerfile:1

# Dockerfile used to build a deployable image for a Rails application.
# Adjust as required.
#
# Common adjustments you may need to make over time:
#  * Modify version numbers for Ruby, Bundler, and other products.
#  * Add library packages needed at build time for your gems, node modules.
#  * Add deployment packages needed by your application
#  * Add (often fake) secrets needed to compile your assets

#######################################################################

# Learn more about the chosen Ruby stack, Fullstaq Ruby, here:
#   https://github.com/evilmartians/fullstaq-ruby-docker.
#
# We recommend using the highest patch level for better security and
# performance.

ARG RUBY_VERSION=3.2.2
ARG VARIANT=jemalloc-slim
FROM quay.io/evl.ms/fullstaq-ruby:${RUBY_VERSION}-${VARIANT} as base

LABEL fly_launch_runtime="rails"

ARG NODE_VERSION=16.15.1
ARG YARN_VERSION=1.22.19
ARG BUNDLER_VERSION=2.3.17

ARG RAILS_ENV=production
ENV RAILS_ENV=${RAILS_ENV}

ENV RAILS_SERVE_STATIC_FILES true
ENV RAILS_LOG_TO_STDOUT true

ARG BUNDLE_WITHOUT=development:test
ARG BUNDLE_PATH=vendor/bundle
ENV BUNDLE_PATH ${BUNDLE_PATH}
ENV BUNDLE_WITHOUT ${BUNDLE_WITHOUT}

RUN mkdir /app
WORKDIR /app
RUN mkdir -p tmp/pids

RUN curl https://get.volta.sh | bash
ENV VOLTA_HOME /root/.volta
ENV PATH $VOLTA_HOME/bin:/usr/local/bin:$PATH
RUN volta install node@${NODE_VERSION} yarn@${YARN_VERSION} && \
    gem update --system --no-document && \
    gem install -N bundler -v ${BUNDLER_VERSION}

#######################################################################

# install packages only needed at build time

FROM base as build_deps

ARG BUILD_PACKAGES="git build-essential libpq-dev wget vim curl gzip xz-utils libsqlite3-dev"
ENV BUILD_PACKAGES ${BUILD_PACKAGES}

RUN --mount=type=cache,id=dev-apt-cache,sharing=locked,target=/var/cache/apt \
    --mount=type=cache,id=dev-apt-lib,sharing=locked,target=/var/lib/apt \
    apt-get update -qq && \
    apt-get install --no-install-recommends -y ${BUILD_PACKAGES} \
    && rm -rf /var/lib/apt/lists /var/cache/apt/archives

#######################################################################

# install gems

FROM build_deps as gems

COPY Gemfile* ./
RUN bundle install && rm -rf vendor/bundle/ruby/*/cache

#######################################################################

# install node modules

FROM build_deps as node_modules

COPY package*json ./
COPY yarn.* ./
RUN yarn install

#######################################################################

# install deployment packages

FROM base

ARG DEPLOY_PACKAGES="postgresql-client file vim curl gzip libsqlite3-0"
ENV DEPLOY_PACKAGES=${DEPLOY_PACKAGES}

RUN --mount=type=cache,id=prod-apt-cache,sharing=locked,target=/var/cache/apt \
    --mount=type=cache,id=prod-apt-lib,sharing=locked,target=/var/lib/apt \
    apt-get update -qq && \
    apt-get install --no-install-recommends -y \
    ${DEPLOY_PACKAGES} \
    && rm -rf /var/lib/apt/lists /var/cache/apt/archives

# copy installed gems
COPY --from=gems /app /app
COPY --from=gems /usr/lib/fullstaq-ruby/versions /usr/lib/fullstaq-ruby/versions
COPY --from=gems /usr/local/bundle /usr/local/bundle

# copy installed node modules
COPY --from=node_modules /app/node_modules /app/node_modules

#######################################################################

# Deploy your application
COPY . .

# Adjust binstubs to run on Linux and set current working directory
RUN chmod +x /app/bin/* && \
    sed -i 's/ruby.exe\r*/ruby/' /app/bin/* && \
    sed -i 's/ruby\r*/ruby/' /app/bin/* && \
    sed -i '/^#!/aDir.chdir File.expand_path("..", __dir__)' /app/bin/*

# The following enable assets to precompile on the build server.  Adjust
# as necessary.  If no combination works for you, see:
# https://fly.io/docs/rails/getting-started/existing/#access-to-environment-variables-at-build-time
ENV SECRET_KEY_BASE 1
# ENV AWS_ACCESS_KEY_ID=1
# ENV AWS_SECRET_ACCESS_KEY=1

# Run build task defined in lib/tasks/fly.rake
ARG BUILD_COMMAND="bin/rails fly:build"
RUN ${BUILD_COMMAND}

# Default server start instructions.  Generally Overridden by fly.toml.
EXPOSE 3000
VOLUME /data
ENV PORT 8080
ARG SERVER_COMMAND="bin/rails fly:server"
ENV SERVER_COMMAND ${SERVER_COMMAND}
CMD ${SERVER_COMMAND}

Do you mean I should try

[[mounts]]
  source = "data"
  destination = "/mnt/recipe_data"

I’ve tried that now with a dockerfile-rails generated Dockerfile. Now I get:

Error: machine 148e46XXXXXXXX [app] can’t update the attached volume data with name ‘vol_ez1nvxwnd3jrmxl7’ by ‘recipe_data’

If I run fly sftp get /mnt/rezept_data/production.sqlite3
I get Error: get: remote file /mnt/rezept_data/production.sqlite3: file does not exist

When I ssh onto the system fly ssh console --pty I’ll be in the the app/ folder,
from there my database is in ../mnt/rezept_data/production.sqlite3

I don’t remember how I added the Sqlite volume in January =oP

My app is deployed and using the database. But it seems that my setup is not ideal. (Warnings and errors when I deploy)

Rails 7.1 introduced health checks. Since you migrated your app, you may not have this endpoint set up. You can remove the check by removing the [[services.tcp_checks]] section in your fly.toml, or you can add a healthcheck endpoint: Health Checks · The Ruby Dispatch

You can find out where your database is by running the following command:

fly ssh console -C "printenv DATABASE_URL"
1 Like

Thanks Sam

You’re right, I’m missing the health checks due to upgrading my app. I’ve removed the checks form fly.toml. You’ve given me the info I needed.

I’d like to look into setting up a new Dockerfile correctly with Litestack and my Sqlite database in future. For now I’ll just keep using my old Dockerfile.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.