Error in Release Startup

I’m trying to run through this tutorial to deploy to Digital Ocean. At this point in the tutorial, I run all the commands successfuly. I get to the _build/prod/rel/docker_phx/bin/docker_phx eval "DockerPhx.Release.migrate" (with appropriate substitutions made for my actual app), I am rewarded with this:

ERROR! Config provider Config.Reader failed with:
** (ArgumentError) argument error
    :erlang.binary_to_integer(nil)
    (stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
    (stdlib) erl_eval.erl:888: :erl_eval.expr_list/6
    (stdlib) erl_eval.erl:240: :erl_eval.expr/5
    (stdlib) erl_eval.erl:232: :erl_eval.expr/5
    (stdlib) erl_eval.erl:888: :erl_eval.expr_list/6
    (stdlib) erl_eval.erl:240: :erl_eval.expr/5
    (stdlib) erl_eval.erl:232: :erl_eval.expr/5

{"init terminating in do_boot",{badarg,[{erlang,binary_to_integer,[nil],[]},{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,680}]},{erl_eval,expr_list,6,[{file,"erl_eval.erl"},{line,888}]},{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,240}]},{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,232}]},{erl_eval,expr_list,6,[{file,"erl_eval.erl"},{line,888}]},{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,240}]},{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,232}]}]}}
init terminating in do_boot ({badarg,[{erlang,binary_to_integer,[nil],[]},{erl_eval,do_apply,6,[{_},{_}]},{erl_eval,expr_list,6,[{_},{_}]},{erl_eval,expr,5,[{_},{_}]},{erl_eval,expr,5,[{_},{_}]},{erl_

Crash dump is being written to: erl_crash.dump...done

My config.exs:

# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
#
# This configuration file is loaded before any dependency and
# is restricted to this project.

# General application configuration
use Mix.Config

config :my_actual_app,
ecto_repos: [MyActualApp.Repo]

# Configures the endpoint
config :my_actual_app, MyActualAppWeb.Endpoint,
  url: [host: "localhost"],
  secret_key_base: "nCGzazsIf+XMNgGg4kH7vegQWaJevlu3N+x4ZQg+Q51Ipm8ItXKwXpUIKZfETHxn",
  render_errors: [view: MyActualAppWeb.ErrorView, accepts: ~w(html json)],
  pubsub_server: MyActualApp.PubSub,
  live_view: [signing_salt: "RX4GG8P/"]

# Configures Elixir's Logger
config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]

# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason
config :phoenix, :format_encoders, json: Jason

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"

Myprod.exs:

use Mix.Config

# For production, don't forget to configure the url host
# to something meaningful, Phoenix uses this information
# when generating URLs.
#
# Note we also include the path to a cache manifest
# containing the digested version of static files. This
# manifest is generated by the `mix phx.digest` task,
# which you should run after static files are built and
# before starting your production server.
config :my_actual_app, MyActualAppWeb.Endpoint,
  http: [port: {:system, "PORT"}],
  url: [host: "localhost", port: {:system, "PORT"}],
  cache_static_manifest: "priv/static/cache_manifest.json",
  secret_key_base: System.get_env("SECRET_KEY_BASE"),
  server: true,
  root: ".",
  version: Application.spec(:my_actual_app, :vsn)

config :my_actual_app, MyActualApp.Repo,
  url: System.get_env("DATABASE_URL"),
  pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
  ssl: true,
  types: MyActualApp.PostgresTypes

# Do not print debug messages in production
config :logger, level: :info

My releases.exs:

# In this file, we load production configuration and secrets
# from environment variables. You can also hardcode secrets,
# although such is generally not recommended and you have to
# remember to add this file to your .gitignore.
import Config

config :my_actual_app, MyActualApp.Repo,
  url: System.get_env("DATABASE_URL"),
  pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")

config :my_actual_app, MyActualAppWeb.Endpoint,
  http: [
    port: String.to_integer(System.get_env("PORT")),
    transport_options: [socket_opts: [:inet6]]
  ],
  url: [scheme: "https", host: System.get_env("APP_DOMAIN"), port: 443],
  secret_key_base: System.get_env("SECRET_KEY_BASE")

My repo.ex:

defmodule MyActualApp.Repo do
  use Ecto.Repo,
    otp_app: :my_actual_app,
    adapter: Ecto.Adapters.Postgres

  def init(_, opts) do
    {:ok, Keyword.put(opts, :url, System.get_env("DATABASE_URL"))}
  end
end

Like, my spidey senses are telling me it’s one of the configurations in the .env (which, of course, I’m not posting here). I just can’t tell which one.

From the error it looks like some environment variable is nil (not set) when an integer is expected, probably the POOL_SIZE.

Are you reading your .env file somewhere? It’s not automatically used by Elixir so you need some code to read the values from it or some external system that puts the values from .env to your current environment.

There are several packages for reading dotenv files for Elixir. I’ve made DotenvParser for example.

2 Likes

Does the POOL_SIZE not default to the “10” there? Also, no I’m not reading in the environment variables. I’ll give the DotenvParser a shot; update incoming.

Ah true, then it would probably be PORT that is fed directly to String.to_integer/1. But I guess they’re all empty since nothing is loading them from .env.

Personally I use .env only in local development and Systemd to set up the environment in production. I don’t use config/releases.exs or the regular dev/prod exs files, but instead use config/runtime.exs for anything that doesn’t need to be set up at compile time. I wrote a blog post about it, but of course it’s very different from your setup and I don’t use Docker so maybe consider it just as food for thought. :slight_smile:

2 Likes

I’m hoping to deploy this thing (finally) to my Digital Ocean droplet, and Docker kind of helps me with that. Or I’m using it as a crutch. Who knows lol

Either way, the DotenvParser definitely worked, and now i"m off to a new fun error with SSL!

2 Likes

Have you considered Digital Ocean’s Apps instead of Droplets? I found it super easy to setup. The SSL is handled for you - you just serve the app over HTTP.

1 Like

I thought about it, and maybe for the next one I will do exactly that. I wanted the experience of building the app from the ground up–from a basically blank droplet to a functioning web application. I also want to gain experience with Docker, and particularly running a swarm (I’ll have a couple of different web apps in their own containers). Admittedly, it’s grueling, and I’m trying to fight through the struggles as best as I can, but I’m learning stuff as I go, so I’ll take it.

3 Likes