Dockerfile for Rails issue with

Hi Fly-ers!

Copied the Dockerfile from Ruby on Rails Deployments - #18 by kurt

I’m currently on an Apple Silicon M1 Macbook. I’m wondering if running fly deploy executes the Docker build step locally on my mac. If so, could it be possible that’s why I’m getting the following error?

Here’s the error i’m getting when running fly deploy

$ fly deploy
$ fly deploy
Deploying random-app-name
==> Validating app configuration
--> Validating app configuration done
Services
TCP 80/443 ⇢ 8080
==> Creating build context
--> Creating build context done
==> Building image with Docker
[+] Building 4.3s (10/15)
 => CACHED [internal] load remote build context                                                                                                                                                                    0.0s
 => CACHED copy /context /                                                                                                                                                                                         0.0s
 => [internal] load metadata for docker.io/library/ruby:3.0.1                                                                                                                                                      1.1s
 => CACHED [builder 1/5] FROM docker.io/library/ruby:3.0.1@sha256:091ee4779c0d90155b6d1a317855ce64714e6485f9db4413c812ddd112df7dc7                                                                                 0.0s
 => CACHED [builder 2/5] RUN apt-get update && apt-get install -y   build-essential   postgresql-client   git   npm   tzdata   brotli   && rm -rf /var/lib/apt/lists/*                                             0.0s
 => CACHED [builder 3/5] WORKDIR /app                                                                                                                                                                              0.0s
 => CACHED copy /context /                                                                                                                                                                                         0.0s
 => CACHED [builder 4/5] ADD Gemfile* /app/                                                                                                                                                                        0.0s
 => ERROR [builder 5/5] RUN bundle config --global frozen 1   && bundle install -j4 --retry 3   && rm -rf /usr/local/bundle/cache/*.gem   && find /usr/local/bundle/gems/ -name "*.c" -delete   && find /usr/loca  2.9s
 => CANCELED [stage-1 2/7] RUN apt-get update && apt-get install -y   file   postgresql-client   tzdata   && rm -rf /var/lib/apt/lists/*                                                                           2.9s
------
 > [builder 5/5] RUN bundle config --global frozen 1   && bundle install -j4 --retry 3   && rm -rf /usr/local/bundle/cache/*.gem   && find /usr/local/bundle/gems/ -name "*.c" -delete   && find /usr/local/bundle/gems/ -name "*.o" -delete:
#11 2.801 Your bundle only supports platforms ["x86_64-darwin-20"] but your local platform
#11 2.801 is x86_64-linux. Add the current platform to the lockfile with `bundle lock
#11 2.801 --add-platform x86_64-linux` and try again.
------
Error error building: executor failed running [/bin/sh -c bundle config --global frozen 1   && bundle install -j4 --retry 3   && rm -rf /usr/local/bundle/cache/*.gem   && find /usr/local/bundle/gems/ -name "*.c" -delete   && find /usr/local/bundle/gems/ -name "*.o" -delete]: exit code: 16

Here’s the Dockerfile:

######################
# Stage: Gem Builder
FROM ruby:3.0.1 as Builder

ARG BUNDLE_WITHOUT="development test" 
ARG RAILS_ENV="production"

ENV BUNDLE_WITHOUT=${BUNDLE_WITHOUT}

RUN apt-get update && apt-get install -y \
  build-essential \
  postgresql-client \
  git \
  npm \
  tzdata \
  brotli \
  && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Install gems
ADD Gemfile* /app/
RUN bundle config --global frozen 1 \
  && bundle install -j4 --retry 3 \
  # Remove unneeded files (cached *.gem, *.o, *.c)
  && rm -rf /usr/local/bundle/cache/*.gem \
  && find /usr/local/bundle/gems/ -name "*.c" -delete \
  && find /usr/local/bundle/gems/ -name "*.o" -delete

###############################
# Stage Final
FROM ruby:3.0.1

RUN apt-get update && apt-get install -y \
  file \
  postgresql-client \
  tzdata \
  && rm -rf /var/lib/apt/lists/*

# Add user
RUN groupadd -r app && useradd -r -g app app

USER app

# Copy app with gems from former build stage
COPY --from=Builder /usr/local/bundle/ /usr/local/bundle/

USER root
RUN mkdir -p /app/tmp/pids && chown -R app:app /app/tmp
ADD --chown=app:app . /app

# Set Rails env
ENV RAILS_LOG_TO_STDOUT true
ENV RAILS_ENV production

USER app
WORKDIR /app

# Start up
CMD ["bundle", "exec", "rails", "db:migrate", "&&", "bundle", "exec", "puma", "-C", "config/puma.rb"]

Note: I’m trying to run rails db:migrate as well to setup the schema and load some data.

Appreciate any help I can get as there’s very little guides on deploying Rails apps with Fly.

This is using your local docker, can you try running fly deploy --remote-only and see if you get better results? Docker on an m1 mac should work fine, so there’s a possibility something else is up.

Ahh, that’s interesting.

Tried your suggestion but got the same issue.

$ fly deploy --remote-only -v
Deploying xxxxxxxxx
==> Validating app configuration
--> Validating app configuration done
Services
TCP 80/443 ⇢ 8080
Remote builder fly-builder-wandering-tree-4482 ready
==> Creating build context
--> Creating build context done
==> Building image with Docker
Step 1/21 : FROM ruby:3.0.1 as Builder
3.0.1: Pulling from library/ruby
Digest: sha256:091ee4779c0d90155b6d1a317855ce64714e6485f9db4413c812ddd112df7dc7
Status: Downloaded newer image for ruby:3.0.1
 ---> 343efcc83bc0
Step 2/21 : ARG BUNDLE_WITHOUT="development test"
 ---> Running in f66e493e02c4
 ---> c0bc69e18441
Step 3/21 : ARG RAILS_ENV="production"
 ---> Running in 9569f3ab7092
 ---> 0e4e75ac8e4c
Step 4/21 : ENV BUNDLE_WITHOUT=${BUNDLE_WITHOU
..
..
..
Setting up npm (5.8.0+ds6-4+deb10u2) ...
Processing triggers for libc-bin (2.28-10) ...
 ---> aac28f88bbd2
Step 6/21 : WORKDIR /app
 ---> Running in 66b3b070b4a5
 ---> 52f5cd71f55a
Step 7/21 : ADD Gemfile* /app/
 ---> 6c64a39d0227
Step 8/21 : RUN bundle config --global frozen 1   && bundle install -j4 --retry 3   && rm -rf /usr/local/bundle/cache/*.gem   && find /usr/local/bundle/gems/ -name "*.c" -delete   && find /usr/local/bundle/gems/ -name "*.o" -delete
 ---> Running in 44b9f6cd515a
Your bundle only supports platforms ["x86_64-darwin-20"] but your local platform
is x86_64-linux. Add the current platform to the lockfile with `bundle lock
--add-platform x86_64-linux` and try again.
Error error building: error rendering build status stream: The command '/bin/sh -c bundle config --global frozen 1   && bundle install -j4 --retry 3   && rm -rf /usr/local/bundle/cache/*.gem   && find /usr/local/bundle/gems/ -name "*.c" -delete   && find /usr/local/bundle/gems/ -name "*.o" -delete' returned a non-zero code: 16

Oh it would help if I read the error. This seems like a Gemfile.lock problem. You probably have to run this in your app directory to update the bundle lock file:

Add the current platform to the lockfile with bundle lock --add-platform x86_64-linux and try again.

1 Like

Got it to work, thanks Kurt! Here’s what I used!

######################
# Stage: Gem Builder
FROM ruby:3.0.1 as Builder

ARG BUNDLE_WITHOUT="development test" 
ARG RAILS_ENV="production"

ENV BUNDLE_WITHOUT=${BUNDLE_WITHOUT}

RUN apt-get update && apt-get install -y \
  build-essential \
  postgresql-client \
  git \
  npm \
  tzdata \
  brotli \
  && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Install gems
ADD Gemfile* /app/
RUN bundle lock --add-platform x86_64-linux
RUN bundle config --global frozen 1 \
  && bundle install -j4 --retry 3 \
  # Remove unneeded files (cached *.gem, *.o, *.c)
  && rm -rf /usr/local/bundle/cache/*.gem \
  && find /usr/local/bundle/gems/ -name "*.c" -delete \
  && find /usr/local/bundle/gems/ -name "*.o" -delete

###############################
# Stage Final
FROM ruby:3.0.1

RUN apt-get update && apt-get install -y \
  file \
  postgresql-client \
  tzdata \
  && rm -rf /var/lib/apt/lists/*

# Add user
RUN groupadd -r app && useradd -r -g app app

USER app

# Copy app with gems from former build stage
COPY --from=Builder /usr/local/bundle/ /usr/local/bundle/

USER root
RUN mkdir -p /app/tmp/pids && chown -R app:app /app/tmp
ADD --chown=app:app . /app

# Set Rails env
ENV RAILS_LOG_TO_STDOUT true
ENV RAILS_ENV production

USER app
WORKDIR /app

# Start up
CMD ["bundle", "exec", "rails", "db:migrate", "&&", "bundle", "exec", "puma", "-C", "config/puma.rb"]

In the logs however, I think some things still aren’t working, but the rails app runs the migrations now.

2021-04-19T07:06:25.062Z 33aa9340 sin [info] Starting instance
2021-04-19T07:06:25.086Z 33aa9340 sin [info] Configuring virtual machine
2021-04-19T07:06:25.087Z 33aa9340 sin [info] Pulling container image
2021-04-19T07:06:32.731Z 33aa9340 sin [info] Unpacking image
2021-04-19T07:06:32.739Z 33aa9340 sin [info] Preparing kernel init
2021-04-19T07:06:33.053Z 33aa9340 sin [info] Configuring firecracker
2021-04-19T07:06:33.323Z 33aa9340 sin [info] Starting virtual machine
2021-04-19T07:06:33.429Z 33aa9340 sin [info] Starting init (commit: 0512da4)...
2021-04-19T07:06:33.447Z 33aa9340 sin [info] Running: `bundle exec rails db:migrate && bundle exec puma -C config/puma.rb` as app
2021-04-19T07:06:33.463Z 33aa9340 sin [info] 2021/04/19 07:06:33 listening on [fdaa:0:21ca:a7b:f0f:33aa:9340:2]:22 (DNS: [fdaa::3]:53)
2021-04-19T07:06:33.671Z 33aa9340 sin [info] `/home/app` is not a directory.
2021-04-19T07:06:33.672Z 33aa9340 sin [info] Bundler will use `/tmp/bundler20210419-503-mi0le5503' as your home directory temporarily.
2021-04-19T07:06:34.625Z 33aa9340 sin [info] invalid option: -C
2021-04-19T07:06:35.459Z 33aa9340 sin [info] Starting clean up.
2021-04-19T07:06:35.459Z 33aa9340 sin [info] Main child exited normally with code: 1
2021-04-19T07:06:38.484Z 33aa9340 sin [info] Starting instance
2021-04-19T07:06:38.509Z 33aa9340 sin [info] Configuring virtual machine
2021-04-19T07:06:38.510Z 33aa9340 sin [info] Pulling container image
2021-04-19T07:06:46.171Z 33aa9340 sin [info] Unpacking image
2021-04-19T07:06:46.178Z 33aa9340 sin [info] Preparing kernel init
2021-04-19T07:06:46.511Z 33aa9340 sin [info] Configuring firecracker
2021-04-19T07:06:46.791Z 33aa9340 sin [info] Starting virtual machine
2021-04-19T07:06:46.903Z 33aa9340 sin [info] Starting init (commit: 0512da4)...
2021-04-19T07:06:46.922Z 33aa9340 sin [info] Running: `bundle exec rails db:migrate && bundle exec puma -C config/puma.rb` as app
2021-04-19T07:06:46.959Z 33aa9340 sin [info] 2021/04/19 07:06:46 listening on [fdaa:0:21ca:a7b:f0f:33aa:9340:2]:22 (DNS: [fdaa::3]:53)
2021-04-19T07:06:47.175Z 33aa9340 sin [info] `/home/app` is not a directory.
2021-04-19T07:06:47.176Z 33aa9340 sin [info] Bundler will use `/tmp/bundler20210419-503-u7uhrc503' as your home directory temporarily.
2021-04-19T07:06:48.142Z 33aa9340 sin [info] invalid option: -C
2021-04-19T07:06:48.933Z 33aa9340 sin [info] Main child exited normally with code: 1
2021-04-19T07:06:48.934Z 33aa9340 sin [info] Starting clean up.
2021-04-19T07:06:58.093Z 33aa9340 sin [info] Health check status changed to 'passing'

Wondering why that’s the case though.

It’s painful to set up Dockerfile to work with Rails Webpacker though haha.

Dockerfiles are pretty painful all around. You might have better luck with a buildpack. Add this to your fly.toml:

[build]
builder = "heroku/buildpacks:20"

[env]
RAILS_ENV="production"

We also have very experimental support for running migrations separately. If you add this to your config file you can simplify things a bit:

[deploy]
release_command = "rake db:migrate"

Do release commands run before the release is made live? What are the consequences of a failed release command? Will a rollback to a previous release occur?

1 Like

Correct, the release command runs before we create a “deployment” of new VMs.

If the release command fails, we don’t run the deployment. It’s not even a rollback, it’s more like a pre-condition in a pipeline.

Perfect! Is the only condition for failure a non-zero exit status?

Yep. If the command exits with a 0 it continues the release.