Permission denied writing compile.elixir

I’m trying to deploy to fly.io for the first time. The ‘flyctl deploy’ command succeeds, but the app status is stopped and ‘flyctl logs’ shows the following error over and over:

[info]** (File.Error) could not write to file "/workspace/_build/prod/lib/XXXXXXX/.mix/compile.elixir": permission denied
[info]    (elixir 1.16.1) lib/file.ex:1143: File.write!/3
[info]    (mix 1.16.1) lib/mix/compilers/elixir.ex:905: Mix.Compilers.Elixir.write_manifest/8
[info]    (mix 1.16.1) lib/mix/compilers/elixir.ex:230: Mix.Compilers.Elixir.compile/7
[info]    (mix 1.16.1) lib/mix/state.ex:15: Mix.State.lock/2
[info]    (mix 1.16.1) lib/mix/task.ex:478: anonymous fn/3 in Mix.Task.run_task/5
[info]    (mix 1.16.1) lib/mix/tasks/compile.all.ex:124: Mix.Tasks.Compile.All.run_compiler/2
[info]    (mix 1.16.1) lib/mix/tasks/compile.all.ex:104: Mix.Tasks.Compile.All.compile/4
[info]    (mix 1.16.1) lib/mix/tasks/compile.all.ex:93: Mix.Tasks.Compile.All.with_logger_app/2
[info] INFO Main child exited normally with code: 1
[info] WARN Reaped child process with pid: 375 and signal: SIGUSR1, core dumped? false
[info] INFO Starting clean up.
[info] WARN hallpass exited, pid: 307, status: signal: 15 (SIGTERM)

It’s an Elixir app, but not Phoenix. I don’t have a Dockerfile, so I guess it’s auto-generating one but I don’t know how to see that.

Would appreciate if anyone can help with debugging this.

I just had this problem, and I just decided to create my own Dockerfile:

  • elixir_buildpack.config: You can remove it

  • fly.toml:

app = <app>
primary_region = <region>

[build]

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

[[vm]]
  size = <size>
  • Dockerfile
FROM hexpm/elixir:1.16.2-erlang-26.2.3-alpine-3.19.1 as base

RUN mkdir /app
WORKDIR /app

RUN apk --no-cache add g++ make git && mix local.hex --force && mix local.rebar --force

FROM base as test
COPY . /app

FROM base AS app_builder
ENV MIX_ENV=prod

# copy only deps-related files
COPY mix.exs mix.lock ./
COPY config config
RUN mix deps.get --only $MIX_ENV
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile
# at this point we should have a valid reusable built cache that only changes
# when either deps or config/{config,prod}.exs change

COPY priv priv
COPY lib lib
COPY config/runtime.exs config/
# COPY rel rel # could contain rel/vm.args.eex, rel/remote.vm.args.eex, and rel/env.sh.eex
RUN mix release

FROM alpine:3.19.1 as app

RUN apk add --no-cache bash openssl libgcc libstdc++ ncurses-libs

RUN adduser -D app
COPY --from=app_builder /app/_build .
RUN chown -R app:app /prod
USER app
CMD ["./prod/rel/<app_name>/bin/<app_name>", "start"]

1 Like