Deployment Error for Elixir Phoenix App on Fly.io: '/app/bin/migrate' Not Found

I am attempting to deploy an Elixir Phoenix application on Fly.io, but I am encountering a recurring issue during the deployment process. The release command specified in my fly.toml file, /app/bin/migrate , seems not to be found, resulting in deployment failures.

the error in console:

--> Pushing image done
image: registry.fly.io/appname:deployment-01HP64XXXXXXPQ2QE0FEK1QAMP
image size: 139 MB

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

Running projeto-tea release_command: /app/bin/migrate

-------
 ✖ Failed: error finding the release_command machine e286776cd71d86 exit event: timeout reached waiting for health checks to pass for machine e286…  
-------
Checking DNS configuration for appname.fly.dev
Error: release command failed - aborting deployment. error finding the release_command machine e286776cd71d86 exit event: timeout reached waiting for
 health checks to pass for machine e286776cd71d86: failed to get VM e286776cd71d86: Get "https://api.machines.dev/v1/apps/appname/machines/e286776cd71d86": net/http: request canceled`Preformatted text


flyctl logs :

2024-02-09T05:19:58Z runner[e286776cd71d86] gru [info]Configuring firecracker
2024-02-09T05:19:58Z app[e286776cd71d86] gru [info][    0.036194] PCI: Fatal: No config space access function found
2024-02-09T05:19:58Z app[e286776cd71d86] gru [info] INFO Starting init (commit: bfa79be)...
2024-02-09T05:19:59Z app[e286776cd71d86] gru [info] INFO Preparing to run: `/app/bin/migrate` as nobody
2024-02-09T05:19:59Z app[e286776cd71d86] gru [info]ERROR Error: failed to spawn command: /app/bin/migrate: No such file or directory (os error 2)    
2024-02-09T05:19:59Z app[e286776cd71d86] gru [info]    does `/app/bin/migrate` exist and is it executable?
2024-02-09T05:19:59Z app[e286776cd71d86] gru [info][    0.296469] reboot: Restarting system


Dockerfile :

ARG ELIXIR_VERSION=1.16.1
ARG OTP_VERSION=25.3.2.8
ARG DEBIAN_VERSION=bullseye-20231009-slim

ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"

FROM ${BUILDER_IMAGE} as builder

# install build dependencies
RUN apt-get update -y && apt-get install -y build-essential git \
    && apt-get clean && rm -f /var/lib/apt/lists/*_*

# prepare build dir
WORKDIR /app

# install hex + rebar
RUN mix local.hex --force && \
    mix local.rebar --force

# set build ENV
ENV MIX_ENV="prod"

# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mix tailwind.install

RUN mkdir config

# copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies
# to be re-compiled.
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile

COPY priv priv

COPY lib lib

COPY assets assets

# compile assets
RUN mix assets.deploy

# Compile the release
RUN mix compile

# Changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/

COPY rel rel
RUN mix release

# start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM ${RUNNER_IMAGE}

RUN apt-get update -y && apt-get install -y libstdc++6 openssl libncurses5 locales \
  && apt-get clean && rm -f /var/lib/apt/lists/*_*

# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

WORKDIR "/app"
RUN chown nobody /app

# set runner ENV
ENV MIX_ENV="prod"

# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/auth ./

USER nobody

CMD ["/app/bin/server"]

ENV ECTO_IPV6 true
ENV ERL_AFLAGS "-proto_dist inet6_tcp"


fly.toml :

app = 'appname'
primary_region = 'gru'
kill_signal = 'SIGTERM'

[build]

[deploy]
  release_command = '/app/bin/migrate'

[env]
  PHX_HOST = 'appname.fly.dev'
  PORT = '8080'

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

  [http_service.concurrency]
    type = 'connections'
    hard_limit = 1000
    soft_limit = 1000

[[vm]]
  cpu_kind = 'shared'
  cpus = 1
  memory_mb = 1024


According to the logs, the system is unable to find the command /app/bin/migrate, indicating “No such file or directory (os error 2)”. I’ve checked both the Dockerfile and the Fly.io configuration file but can’t seem to identify the cause of the issue.

Any suggestions on what might be causing this problem and how I can resolve it? Am I missing some configuration or step in the build or deploy process?

Thanks

Hey @samuel06santos ,

What is in your rel directory? Is there a bin/migrate file there?

@somt0xhi,
Yes, there is a bin/migrate file within my rel directory.

Here’s the structure:

image

Are you customizing the release in anyway in mix.exs and is auth the name of your application? Can you build and run the docker container locally? so you can exec and check if /app/bin/migrate is actually present?

@somt0xhi,
Yes, auth is the name of my application, and I have not made any custom changes to the release process in mix.exs

mix.exs:

defmodule Auth.MixProject do
  use Mix.Project

  def project do
    [
      app: :auth,
      version: "0.1.2",
      elixir: "~> 1.12",
      elixirc_paths: elixirc_paths(Mix.env()),
      start_permanent: Mix.env() == :prod,
      aliases: aliases(),
      deps: deps()
    ]
  end

  def application do
    [
      mod: {Auth.Application, []},
      extra_applications: [:logger, :runtime_tools]
    ]
  end


  defp deps do
    [
       ...
    ]
  end

  defp aliases do
    [
      setup: ["deps.get", "ecto.setup"],
      "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
      "ecto.reset": ["ecto.drop", "ecto.setup"],
      test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
      "assets.deploy": ["tailwind default --minify", "esbuild default --minify", "phx.digest"]
    ]
  end
end


With docker run --entrypoint /bin/bash auth -c "ls /app/bin":

auth
auth.bat
migrate
migrate.bat
server
server.bat

and the directory /app/run/ not exist.

Can you pull the image built by fly.io and also check if /app/bin/migrate is present

fly auth docker
docker pull registry.fly.io/<image>

You can get the image from the output when you run fly deploy

@somt0xhi,
I was able to pull the image built by Fly.io and run it locally, as you described with docker pull registry.fly.io/<image>

docker run --entrypoint /bin/bash -it registry.fly.io/<image>

The /app/bin/migrate script is indeed present in the /app/bin directory as confirmed by the ls command.
However, when I attempt to execute /app/bin/migrate, I receive the following error:

nobody@7e3fe23e6e92:/app$ ls /app/bin
auth  auth.bat  migrate  migrate.bat  server  server.bat
nobody@7e3fe23e6e92:/app$ /app/bin/migrate
bash: /app/bin/migrate: /bin/sh^M: bad interpreter: No such file or directory

When I run the same image (registry.fly.io/<image>) in the Docker Desktop program, I get the same error:
2024-02-12 09:34:41 exec /app/bin/server: no such file or directory

Versions in Dockerfile:
ELIXIR VERSION: 1.16.1
OTP VERSION: 25.3.2.8
DEBIAN VERSION: bullseye-20240130-slim

I tried deploying hello_elixir/README.md at main · fly-apps/hello_elixir · GitHub with the your Dockerfile version and everything worked okay

Did you by any chance edit the file on windows? what’s the content of /app/bin/migrate file?
I came across newline - Bash script – "/bin/bash^M: bad interpreter: No such file or directory" - Stack Overflow