I’m trying to migrate my app over to Fly, but I’m getting a function Mix.env/0 is undefined (module Mix is not available)
when i try to visit the page after deploy. Any help would be much appreciated!
Log output
2022-02-22T18:04:58.737 app[53cbdd68] lax [info] Starting clean up.
2022-02-22T18:08:49.656 app[fc323489] sea [info] 18:08:49.648 request_id=FtYuCOib1m4Tyu8AAAFB [info] GET /
2022-02-22T18:08:49.661 app[fc323489] sea [info] 18:08:49.660 request_id=FtYuCOib1m4Tyu8AAAFB [info] Sent 500 in 12ms
2022-02-22T18:08:49.663 app[fc323489] sea [info] 18:08:49.661 [error] #PID<0.2381.0> running HelloWeb.Endpoint (connection #PID<0.2380.0>, stream id 1) terminated
2022-02-22T18:08:49.663 app[fc323489] sea [info] Server: hello.fly.dev:80 (http)
2022-02-22T18:08:49.663 app[fc323489] sea [info] Request: GET /
2022-02-22T18:08:49.663 app[fc323489] sea [info] ** (exit) an exception was raised:
2022-02-22T18:08:49.663 app[fc323489] sea [info] ** (UndefinedFunctionError) function Mix.env/0 is undefined (module Mix is not available)
2022-02-22T18:08:49.663 app[fc323489] sea [info] Mix.env()
2022-02-22T18:08:49.663 app[fc323489] sea [info] (benchmark 0.1.0) lib/benchmark_web/templates/layout/root.html.heex:78: anonymous fn/2 in HelloWeb.LayoutView."root.html"/1
2022-02-22T18:08:49.663 app[fc323489] sea [info] (phoenix_live_view 0.17.5) lib/phoenix_live_view/engine.ex:124: Phoenix.HTML.Safe.Phoenix.LiveView.Rendered.to_iodata/1
2022-02-22T18:08:49.663 app[fc323489] sea [info] (phoenix 1.6.2) lib/phoenix/controller.ex:772: Phoenix.Controller.render_and_send/4
2022-02-22T18:08:49.663 app[fc323489] sea [info] (phoenix 1.6.2) lib/phoenix/router.ex:355: Phoenix.Router.__call__/2
2022-02-22T18:08:49.663 app[fc323489] sea [info] (benchmark 0.1.0) lib/benchmark_web/endpoint.ex:1: HelloWeb.Endpoint.plug_builder_call/2
2022-02-22T18:08:49.663 app[fc323489] sea [info] (benchmark 0.1.0) lib/benchmark_web/endpoint.ex:1: HelloWeb.Endpoint.call/2
2022-02-22T18:08:49.663 app[fc323489] sea [info] (phoenix 1.6.2) lib/phoenix/endpoint/cowboy2_handler.ex:43: Phoenix.Endpoint.Cowboy2Handler.init/4
DockerFile
ARG BUILDER_IMAGE="hexpm/elixir:1.12.2-erlang-23.3.4-debian-bullseye-20210902-slim"
ARG RUNNER_IMAGE="debian:bullseye-20210902-slim"
FROM ${BUILDER_IMAGE} as builder
# install build dependencies
RUN apt-get update -y && apt-get install -y build-essential git nodejs npm \
&& 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 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 - Moved down
# note: if your project uses a tool like https://purgecss.com/,
# which customizes asset compilation based on what it finds in
# your Elixir templates, you will need to move the asset compilation
# step down so that `lib` is available.
# COPY assets assets - Moved down
# For Phoenix 1.6 and later, compile assets using esbuild
# RUN mix assets.deploy - Moved down
# For Phoenix versions earlier than 1.6, compile assets npm
# RUN cd assets && yarn install && yarn run webpack --mode production
# RUN mix phx.digest
# Compile the release
COPY lib lib
COPY priv priv
COPY assets assets
RUN cd assets && npm install
RUN mix assets.deploy
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
# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/prod/rel ./
USER nobody
# Create a symlink to the application directory by extracting the directory name. This is required
# since the release directory will be named after the application, and we don't know that name.
RUN set -eux; \
ln -nfs /app/$(basename *)/bin/$(basename *) /app/entry
CMD /app/entry start
fly.toml
# fly.toml file generated for hello on 2022-02-20T14:00:44-08:00
app = "hello"
kill_signal = "SIGTERM"
kill_timeout = 5
processes = []
[deploy]
release_command = "/app/entry eval Hello.Release.migrate"
[env]
[experimental]
allowed_public_ports = []
[[services]]
http_checks = []
internal_port = 4000
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "30s"
interval = "15s"
restart_limit = 0
timeout = "2s"
runtime.exs
import Config
# config/runtime.exs is executed for all environments, including
# during releases. It is executed after compilation and before the
# system starts, so it is typically used to load production configuration
# and secrets from environment variables or elsewhere. Do not define
# any compile-time configuration in here, as it won't be applied.
# The block below contains prod specific runtime configuration.
if config_env() == :prod do
database_url =
System.get_env("DATABASE_URL") ||
raise """
environment variable DATABASE_URL is missing.
For example: ecto://USER:PASS@HOST/DATABASE
"""
config :hello, Hello.Repo,
# ssl: true,
# IMPORTANT: Or it won't find the DB server
socket_options: [:inet6],
url: database_url,
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")
# The secret key base is used to sign/encrypt cookies and other secrets.
# A default value is used in config/dev.exs and config/test.exs but you
# want to use a different value for prod and you most likely don't want
# to check this value into version control, so we use an environment
# variable instead.
secret_key_base =
System.get_env("SECRET_KEY_BASE") ||
raise """
environment variable SECRET_KEY_BASE is missing.
You can generate one by calling: mix phx.gen.secret
"""
app_name =
System.get_env("FLY_APP_NAME") ||
raise "FLY_APP_NAME not available"
config :hello, HelloWeb.Endpoint,
url: [host: "#{app_name}.fly.dev", port: 80],
http: [
# Enable IPv6 and bind on all interfaces.
# Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.
# See the documentation on https://hexdocs.pm/plug_cowboy/Plug.Cowboy.html
# for details about using IPv6 vs IPv4 and loopback vs public addresses.
ip: {0, 0, 0, 0, 0, 0, 0, 0},
port: String.to_integer(System.get_env("PORT") || "4000")
],
secret_key_base: secret_key_base
# ## Using releases
#
# If you are doing OTP releases, you need to instruct Phoenix
# to start each relevant endpoint:
#
config :hello, HelloWeb.Endpoint, server: true
# ## Configuring the mailer
#
# In production you need to configure the mailer to use a different adapter.
# Also, you may need to configure the Swoosh API client of your choice if you
# are not using SMTP. Here is an example of the configuration:
#
# config :hello, Hello.Mailer,
# adapter: Swoosh.Adapters.Mailgun,
# api_key: System.get_env("MAILGUN_API_KEY"),
# domain: System.get_env("MAILGUN_DOMAIN")
#
# For this example you need include a HTTP client required by Swoosh API client.
# Swoosh supports Hackney and Finch out of the box:
#
# config :swoosh, :api_client, Swoosh.ApiClient.Hackney
#
# See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details.
end
if config_env() == :dev do
database_url = System.get_env("DATABASE_URL")
if database_url != nil do
config :hello, Hello.Repo,
url: database_url,
socket_options: [:inet6]
end
end