diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cb1b021 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,97 @@ +# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian +# instead of Alpine to avoid DNS resolution issues in production. +# +# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu +# https://hub.docker.com/_/ubuntu?tab=tags +# +# This file is based on these images: +# +# - https://hub.docker.com/r/hexpm/elixir/tags - for the build image +# - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20250113-slim - for the release image +# - https://pkgs.org/ - resource for finding needed packages +# - Ex: hexpm/elixir:1.18.2-erlang-27.2-debian-bullseye-20250113-slim +# +ARG ELIXIR_VERSION=1.18.2 +ARG OTP_VERSION=27.2 +ARG DEBIAN_VERSION=bullseye-20250113-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 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 ca-certificates \ + && 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/aprs ./ + +USER nobody + +# If using an environment that doesn't automatically reap zombie processes, it is +# advised to add an init process such as tini via `apt-get install` +# above and adding an entrypoint. See https://github.com/krallin/tini for details +# ENTRYPOINT ["/tini", "--"] + +CMD ["/app/bin/server"] diff --git a/config/config.exs b/config/config.exs index 317b6f5..f6daef8 100644 --- a/config/config.exs +++ b/config/config.exs @@ -40,7 +40,7 @@ config :aprs, # Configure esbuild (the version is required) config :esbuild, - version: "0.17.11", + version: "0.24.2", default: [ args: ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*), cd: Path.expand("../assets", __DIR__), diff --git a/config/runtime.exs b/config/runtime.exs index e9365ef..184fff6 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -64,7 +64,7 @@ if config_env() == :prod do ], secret_key_base: secret_key_base - config :aprs, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY") + # config :aprs, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY") config :aprs, ecto_repos: [Aprs.Repo], diff --git a/elixir_buildpack.config b/elixir_buildpack.config deleted file mode 100644 index 7c62c49..0000000 --- a/elixir_buildpack.config +++ /dev/null @@ -1,13 +0,0 @@ -# Erlang version -erlang_version=26.2.0 - -# Elixir version -elixir_version=1.18.2 - -# Always rebuild from scratch on every deploy? -always_rebuild=false - -# Create a release using `mix release`? (requires Elixir 1.9) -release=true - -hook_post_compile="eval mix assets.deploy && rm -f _build/esbuild*" diff --git a/fly.toml b/fly.toml index 5512afe..66791d8 100644 --- a/fly.toml +++ b/fly.toml @@ -1,42 +1,35 @@ -# fly.toml file generated for aprsme on 2023-01-26T13:39:35-06:00 +# fly.toml app configuration file generated for aprs-me on 2025-01-22T13:50:44-06:00 +# +# See https://fly.io/docs/reference/configuration/ for information about how to use this file. +# -app = "aprsme" -kill_signal = "SIGTERM" -kill_timeout = 5 -processes = [] +app = 'aprs-me' +primary_region = 'dfw' +kill_signal = 'SIGTERM' + +[build] [deploy] - release_command = "/app/bin/migrate" + release_command = '/app/bin/migrate' [env] - PHX_HOST = "aprsme.fly.dev" - PORT = "8080" + PHX_HOST = 'aprs-me.fly.dev' + PORT = '8080' -[experimental] - auto_rollback = true - -[[services]] - http_checks = [] +[http_service] internal_port = 8080 - processes = ["app"] - protocol = "tcp" - script_checks = [] - [services.concurrency] - hard_limit = 25 - soft_limit = 20 - type = "connections" + force_https = true + auto_stop_machines = 'stop' + auto_start_machines = true + min_machines_running = 0 + processes = ['app'] - [[services.ports]] - force_https = true - handlers = ["http"] - port = 80 + [http_service.concurrency] + type = 'connections' + hard_limit = 1000 + soft_limit = 1000 - [[services.ports]] - handlers = ["tls", "http"] - port = 443 - - [[services.tcp_checks]] - grace_period = "1s" - interval = "15s" - restart_limit = 0 - timeout = "2s" +[[vm]] + memory = '1gb' + cpu_kind = 'shared' + cpus = 1