From 42b2675a2259d374372b0639993a3f85864e55bb Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Wed, 18 Sep 2024 08:41:59 -0300 Subject: [PATCH 01/10] wip: use develop to keep code in sync --- docker-compose.yml | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 077d0d8..6474232 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,15 +21,30 @@ services: depends_on: - db init: true + develop: + watch: + - path: ./ + ignore: + - ./build/ + - ./deps/ + target: /opt/app + action: sync + - path: ./config/ + target: /opt/app + action: sync+restart + - path: ./lib/wabanex/application.ex + target: /opt/app + action: sync+restart + - path: ./mix.exs + target: /opt/app + action: sync+restart + - path: ./mix.lock + action: rebuild environment: &app_environment POSTGRES_HOST: *db_host POSTGRES_USER: *db_user POSTGRES_PASS: *db_pass POSTGRES_NAME: wabanex_dev - volumes: &app_volumes - - '.:/opt/app' - - 'app_build:/opt/app/_build' - - 'app_deps:/opt/app/deps' working_dir: /opt/app restart: unless-stopped entrypoint: sleep @@ -41,7 +56,6 @@ services: profiles: - setup environment: *app_environment - volumes: *app_volumes restart: 'no' command: | mix ecto.setup \ @@ -53,7 +67,6 @@ services: profiles: - migrate environment: *app_environment - volumes: *app_volumes restart: 'no' command: | mix ecto.migrate \ @@ -61,5 +74,3 @@ services: volumes: db_data: {} - app_build: {} - app_deps: {} -- 2.47.2 From 76d5fc9adf2c140f9d2bd7a4fd35676e5f56d34a Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Fri, 20 Sep 2024 21:16:32 +0000 Subject: [PATCH 02/10] feat: use release to deploy application Adjust `Dockerfile` and `docker-compose` to use the `release` structure. --- Dockerfile | 72 +++++++++++++++++++++++++++++++++--- docker-compose.yml | 2 + lib/wabanex/release.ex | 28 ++++++++++++++ rel/overlays/bin/migrate | 5 +++ rel/overlays/bin/migrate.bat | 1 + rel/overlays/bin/server | 5 +++ rel/overlays/bin/server.bat | 2 + 7 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 lib/wabanex/release.ex create mode 100755 rel/overlays/bin/migrate create mode 100755 rel/overlays/bin/migrate.bat create mode 100755 rel/overlays/bin/server create mode 100755 rel/overlays/bin/server.bat diff --git a/Dockerfile b/Dockerfile index f0578c2..0bb3f02 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,70 @@ -FROM hexpm/elixir:1.17.2-erlang-27.0.1-debian-bookworm-20240701-slim AS builder +ARG ELIXIR_VERSION=1.17.2 +ARG OTP_VERSION=27.0.1 +ARG DEBIAN_VERSION=bookworm-20240701-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 RUN apt-get update \ - && apt-get -y install git make - + && apt-get -y install \ + build-essential \ + git \ + make \ + && apt-get clean \ + && rm -rf /var/lib/ap/lists/*_* WORKDIR /opt/app +# install hex + rebar +RUN mix do local.hex --force, local.rebar --force +# set build ENV +ARG BUILD_MIX_ENV=prod +ENV MIX_ENV=${BUILD_MIX_ENV} +# 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/${BUILD_MIX_ENV}.exs config/ +RUN mix deps.compile +COPY priv priv +COPY lib lib +# 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 COPY ./mix.exs ./ -COPY ./mix.lock ./ -RUN mix do local.hex --force, local.rebar --force \ - && mix do deps.get, deps.compile +EXPOSE 4000 +ENTRYPOINT ["./priv/docker/service/docker-entrypoint.sh"] +CMD ["sample-cookie"] + +# 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 \ + ca-certificates \ + libncurses5 \ + libstdc++6 \ + locales \ + openssl \ + tini \ + && 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 /opt/app +RUN chown nobody /opt/app +# set runner ENV +ARG BUILD_MIX_ENV=prod +ENV MIX_ENV=${BUILD_MIX_ENV} +# Only copy the final release from the build stage +COPY --from=builder --chown=nobody:root /app/_build/${BUILD_MIX_ENV}/rel/wabanex ./ +USER nobody +EXPOSE 4000 +ENTRYPOINT ["tini", "--"] +CMD ["/app/bin/server"] diff --git a/docker-compose.yml b/docker-compose.yml index 6474232..052ec9c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,6 +17,8 @@ services: build: target: builder context: . + args: + BUILD_MIX_ENV: dev hostname: app depends_on: - db diff --git a/lib/wabanex/release.ex b/lib/wabanex/release.ex new file mode 100644 index 0000000..10ba398 --- /dev/null +++ b/lib/wabanex/release.ex @@ -0,0 +1,28 @@ +defmodule Wabanex.Release do + @moduledoc """ + Used for executing DB release tasks when run in production without Mix + installed. + """ + @app :wabanex + + def migrate do + load_app() + + for repo <- repos() do + {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :up, all: true)) + end + end + + def rollback(repo, version) do + load_app() + {:ok, _, _} = Ecto.Migrator.with_repo(repo, &Ecto.Migrator.run(&1, :down, to: version)) + end + + defp repos do + Application.fetch_env!(@app, :ecto_repos) + end + + defp load_app do + Application.load(@app) + end +end diff --git a/rel/overlays/bin/migrate b/rel/overlays/bin/migrate new file mode 100755 index 0000000..1d0884e --- /dev/null +++ b/rel/overlays/bin/migrate @@ -0,0 +1,5 @@ +#!/bin/sh +set -eu + +cd -P -- "$(dirname -- "$0")" +exec ./wabanex eval Wabanex.Release.migrate diff --git a/rel/overlays/bin/migrate.bat b/rel/overlays/bin/migrate.bat new file mode 100755 index 0000000..b065b42 --- /dev/null +++ b/rel/overlays/bin/migrate.bat @@ -0,0 +1 @@ +call "%~dp0\wabanex" eval Wabanex.Release.migrate diff --git a/rel/overlays/bin/server b/rel/overlays/bin/server new file mode 100755 index 0000000..36cba5a --- /dev/null +++ b/rel/overlays/bin/server @@ -0,0 +1,5 @@ +#!/bin/sh +set -eu + +cd -P -- "$(dirname -- "$0")" +PHX_SERVER=true exec ./wabanex start diff --git a/rel/overlays/bin/server.bat b/rel/overlays/bin/server.bat new file mode 100755 index 0000000..5c38da8 --- /dev/null +++ b/rel/overlays/bin/server.bat @@ -0,0 +1,2 @@ +set PHX_SERVER=true +call "%~dp0\wabanex" start -- 2.47.2 From b5eca5326fcf8dc15a895b5300e52a7d33b88090 Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Fri, 20 Sep 2024 21:54:20 +0000 Subject: [PATCH 03/10] feat: configure dnscluster to allow multi-node * Configure `docker-compose` to scale at least 2 nodes. * Add script to start service with proper naming * Create custom resolver. * This is not strictly necessary. --- config/dev.exs | 4 ++++ config/runtime.exs | 2 ++ docker-compose.yml | 2 ++ lib/wabanex/application.ex | 4 ++++ lib/wabanex/dev_dns_cluster_resolver.ex | 26 ++++++++++++++++++++++++ mix.exs | 1 + mix.lock | 1 + priv/docker/service/docker-entrypoint.sh | 2 ++ 8 files changed, 42 insertions(+) create mode 100644 lib/wabanex/dev_dns_cluster_resolver.ex create mode 100755 priv/docker/service/docker-entrypoint.sh diff --git a/config/dev.exs b/config/dev.exs index 1faf08e..955f22a 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -1,5 +1,9 @@ import Config +config :wabanex, + dns_cluster_query: :ignore, + dns_cluster_resolver: Wabanex.DevDNSClusterResolver + # Configure your database config :wabanex, Wabanex.Repo, database: "wabanex_dev", diff --git a/config/runtime.exs b/config/runtime.exs index 7120844..90fc85f 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -1,5 +1,7 @@ import Config +config :wabanex, dns_cluster_query: System.get_env("DNS_CLUSTER_QUERY") || :ignore + config :wabanex, Wabanex.Repo, username: System.get_env("POSTGRES_USER") || "postgres", password: System.get_env("POSTGRES_PASS") || "postgres", diff --git a/docker-compose.yml b/docker-compose.yml index 052ec9c..c4a520f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,12 +43,14 @@ services: - path: ./mix.lock action: rebuild environment: &app_environment + DNS_CLUSTER_QUERY: *app_host POSTGRES_HOST: *db_host POSTGRES_USER: *db_user POSTGRES_PASS: *db_pass POSTGRES_NAME: wabanex_dev working_dir: /opt/app restart: unless-stopped + scale: 2 entrypoint: sleep command: infinity db_setup: diff --git a/lib/wabanex/application.ex b/lib/wabanex/application.ex index 2960117..536404e 100644 --- a/lib/wabanex/application.ex +++ b/lib/wabanex/application.ex @@ -15,6 +15,10 @@ defmodule Wabanex.Application do WabanexWeb.Telemetry, # Start the PubSub system {Phoenix.PubSub, name: Wabanex.PubSub}, + {DNSCluster, + query: Application.get_env(:wabanex, :dns_cluster_query) || :ignore, + log: :info, + resolver: Application.get_env(:wabanex, :dns_cluster_resolver) || DNSCluster.Resolver}, # Start the Endpoint (http/https) WabanexWeb.Endpoint # Start a worker by calling: Wabanex.Worker.start_link(arg) diff --git a/lib/wabanex/dev_dns_cluster_resolver.ex b/lib/wabanex/dev_dns_cluster_resolver.ex new file mode 100644 index 0000000..a802fe0 --- /dev/null +++ b/lib/wabanex/dev_dns_cluster_resolver.ex @@ -0,0 +1,26 @@ +defmodule Wabanex.DevDNSClusterResolver do + @moduledoc """ + Local DNS resolver for cluster query. + """ + require Record + + Record.defrecord(:hostent, Record.extract(:hostent, from_lib: "kernel/include/inet.hrl")) + + def basename(node_name) when is_atom(node_name) do + [basename, _] = node_name |> to_string() |> String.split("@") + basename + end + + def connect_node(node_name) when is_atom(node_name) do + Node.connect(node_name) + end + + def list_nodes, do: Node.list(:visible) + + def lookup(query, type) when is_binary(query) and type in [:a, :aaaa] do + case :inet_res.getbyname(~c"#{query}", type) do + {:ok, hostent(h_addr_list: addr_list)} -> addr_list + {:error, _} -> [] + end + end +end diff --git a/mix.exs b/mix.exs index edb04fb..3323f16 100644 --- a/mix.exs +++ b/mix.exs @@ -36,6 +36,7 @@ defmodule Wabanex.MixProject do {:credo, "~> 1.7.0", only: [:dev, :test], runtime: false}, {:crudry, "~> 2.4.0"}, {:dialyxir, "~> 1.4.0", only: [:dev, :test], runtime: false}, + {:dns_cluster, "~> 0.1.1"}, {:ecto_sql, "~> 3.12.0"}, {:gettext, "~> 0.25.0"}, {:jason, "~> 1.4.0"}, diff --git a/mix.lock b/mix.lock index 6a6d8e5..e75b24d 100644 --- a/mix.lock +++ b/mix.lock @@ -11,6 +11,7 @@ "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"}, + "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"}, "ecto": {:hex, :ecto, "3.12.0", "9014a3ccac7f91e680b9d237d461ebe3d4e16d62ca8e355d540e2c6afdc28309", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "41e781a76e131093af8e1edf68b1319bf320878faff58da41ffa4b10fc6ff678"}, "ecto_sql": {:hex, :ecto_sql, "3.12.0", "73cea17edfa54bde76ee8561b30d29ea08f630959685006d9c6e7d1e59113b7d", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dc9e4d206f274f3947e96142a8fdc5f69a2a6a9abb4649ef5c882323b6d512f0"}, "erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"}, diff --git a/priv/docker/service/docker-entrypoint.sh b/priv/docker/service/docker-entrypoint.sh new file mode 100755 index 0000000..f359da7 --- /dev/null +++ b/priv/docker/service/docker-entrypoint.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +elixir --name ${HOSTNAME}@$(hostname -i | cut -d ' ' -f1) --cookie ${1} -S mix phx.server -- 2.47.2 From 670d06b7a842088864b51b4978c57c7d62572e34 Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Fri, 20 Sep 2024 22:04:20 +0000 Subject: [PATCH 04/10] chore: remove boilerplate comments --- config/config.exs | 12 ---------- config/dev.exs | 35 --------------------------- config/prod.exs | 48 -------------------------------------- config/runtime.exs | 28 ++++++++++++++++++++++ config/test.exs | 8 ------- lib/wabanex/application.ex | 13 ----------- 6 files changed, 28 insertions(+), 116 deletions(-) diff --git a/config/config.exs b/config/config.exs index 0702aa3..387793c 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,10 +1,3 @@ -# 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 import Config config :wabanex, @@ -21,7 +14,6 @@ config :wabanex, Wabanex.PromEx, grafana: :disabled, metrics_server: :disabled -# Configures the endpoint config :wabanex, WabanexWeb.Endpoint, url: [host: "localhost"], secret_key_base: "wkyuhU+mCGwXUSBYVKZSRGoFmDYCbOFzdokbVmBBI9JgCWOqGPfuA/3JI5/b4Wdl", @@ -29,14 +21,10 @@ config :wabanex, WabanexWeb.Endpoint, pubsub_server: Wabanex.PubSub, live_view: [signing_salt: "SXtw7DzV"] -# 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 -# Import environment specific config. This must remain at the bottom -# of this file so it overrides the configuration defined above. import_config "#{config_env()}.exs" diff --git a/config/dev.exs b/config/dev.exs index 955f22a..9cea01d 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -4,18 +4,11 @@ config :wabanex, dns_cluster_query: :ignore, dns_cluster_resolver: Wabanex.DevDNSClusterResolver -# Configure your database config :wabanex, Wabanex.Repo, database: "wabanex_dev", show_sensitive_data_on_connection_error: true, pool_size: 10 -# For development, we disable any cache and enable -# debugging and code reloading. -# -# The watchers configuration can be used to run external -# watchers to your application. For example, we use it -# with webpack to recompile .js and .css sources. config :wabanex, WabanexWeb.Endpoint, http: [port: 4000], debug_errors: true, @@ -23,36 +16,8 @@ config :wabanex, WabanexWeb.Endpoint, check_origin: false, watchers: [] -# ## SSL Support -# -# In order to use HTTPS in development, a self-signed -# certificate can be generated by running the following -# Mix task: -# -# mix phx.gen.cert -# -# Note that this task requires Erlang/OTP 20 or later. -# Run `mix help phx.gen.cert` for more information. -# -# The `http:` config above can be replaced with: -# -# https: [ -# port: 4001, -# cipher_suite: :strong, -# keyfile: "priv/cert/selfsigned_key.pem", -# certfile: "priv/cert/selfsigned.pem" -# ], -# -# If desired, both `http:` and `https:` keys can be -# configured to run both http and https servers on -# different ports. - -# Do not include metadata nor timestamps in development logs config :logger, :console, format: "[$level] $message\n" -# Set a higher stacktrace during development. Avoid configuring such -# in production as building large stacktraces may be expensive. config :phoenix, :stacktrace_depth, 20 -# Initialize plugs at runtime for faster development compilation config :phoenix, :plug_init_mode, :runtime diff --git a/config/prod.exs b/config/prod.exs index 10f9447..9671347 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -1,55 +1,7 @@ import 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 :wabanex, WabanexWeb.Endpoint, url: [host: "example.com", port: 80], cache_static_manifest: "priv/static/cache_manifest.json" -# Do not print debug messages in production config :logger, level: :info - -# ## SSL Support -# -# To get SSL working, you will need to add the `https` key -# to the previous section and set your `:url` port to 443: -# -# config :wabanex, WabanexWeb.Endpoint, -# ... -# url: [host: "example.com", port: 443], -# https: [ -# port: 443, -# cipher_suite: :strong, -# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"), -# certfile: System.get_env("SOME_APP_SSL_CERT_PATH"), -# transport_options: [socket_opts: [:inet6]] -# ] -# -# The `cipher_suite` is set to `:strong` to support only the -# latest and more secure SSL ciphers. This means old browsers -# and clients may not be supported. You can set it to -# `:compatible` for wider support. -# -# `:keyfile` and `:certfile` expect an absolute path to the key -# and cert in disk or a relative path inside priv, for example -# "priv/ssl/server.key". For all supported SSL configuration -# options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1 -# -# We also recommend setting `force_ssl` in your endpoint, ensuring -# no data is ever sent via http, always redirecting to https: -# -# config :wabanex, WabanexWeb.Endpoint, -# force_ssl: [hsts: true] -# -# Check `Plug.SSL` for all available options in `force_ssl`. - -# Finally import the config/prod.secret.exs which loads secrets -# and configuration from environment variables. -import_config "prod.secret.exs" diff --git a/config/runtime.exs b/config/runtime.exs index 90fc85f..bc5dec1 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -1,5 +1,33 @@ import Config +# [warn] Conditional IPv6 support missing from runtime configuration. +# +# Add the following to your config/runtime.exs: +# +# maybe_ipv6 = if System.get_env("ECTO_IPV6") in ~w(true 1), do: [:inet6], else: [] +# +# config :wabanex, Wabanex.Repo, +# ..., +# socket_options: maybe_ipv6 +# +# [warn] Conditional server startup is missing from runtime configuration. +# +# Add the following to the top of your config/runtime.exs: +# +# if System.get_env("PHX_SERVER") do +# config :wabanex, WabanexWeb.Endpoint, server: true +# end +# +# [warn] Environment based URL export is missing from runtime configuration. +# +# Add the following to your config/runtime.exs: +# +# host = System.get_env("PHX_HOST") || "example.com" +# +# config :wabanex, WabanexWeb.Endpoint, +# ..., +# url: [host: host, port: 443] + config :wabanex, dns_cluster_query: System.get_env("DNS_CLUSTER_QUERY") || :ignore config :wabanex, Wabanex.Repo, diff --git a/config/test.exs b/config/test.exs index c5b87de..4b124fa 100644 --- a/config/test.exs +++ b/config/test.exs @@ -1,21 +1,13 @@ import Config -# Configure your database -# -# The MIX_TEST_PARTITION environment variable can be used -# to provide built-in test partitioning in CI environment. -# Run `mix help test` for more information. config :wabanex, Wabanex.Repo, database: "wabanex_test#{System.get_env("MIX_TEST_PARTITION")}", pool: Ecto.Adapters.SQL.Sandbox -# We don't run a server during test. If one is required, -# you can enable the server option below. config :wabanex, WabanexWeb.Endpoint, http: [port: 4002], server: false -# Print only warnings and errors during test config :logger, level: :warning config :junit_formatter, diff --git a/lib/wabanex/application.ex b/lib/wabanex/application.ex index 536404e..346d587 100644 --- a/lib/wabanex/application.ex +++ b/lib/wabanex/application.ex @@ -1,38 +1,25 @@ defmodule Wabanex.Application do - # See https://hexdocs.pm/elixir/Application.html - # for more information on OTP Applications @moduledoc false use Application def start(_type, _args) do children = [ - # Start the PromEx supervisor Wabanex.PromEx, - # Start the Ecto repository Wabanex.Repo, - # Start the Telemetry supervisor WabanexWeb.Telemetry, - # Start the PubSub system {Phoenix.PubSub, name: Wabanex.PubSub}, {DNSCluster, query: Application.get_env(:wabanex, :dns_cluster_query) || :ignore, log: :info, resolver: Application.get_env(:wabanex, :dns_cluster_resolver) || DNSCluster.Resolver}, - # Start the Endpoint (http/https) WabanexWeb.Endpoint - # Start a worker by calling: Wabanex.Worker.start_link(arg) - # {Wabanex.Worker, arg} ] - # See https://hexdocs.pm/elixir/Supervisor.html - # for other strategies and supported options opts = [strategy: :one_for_one, name: Wabanex.Supervisor] Supervisor.start_link(children, opts) end - # Tell Phoenix to update the endpoint configuration - # whenever the application is updated. def config_change(changed, _new, removed) do WabanexWeb.Endpoint.config_change(changed, removed) :ok -- 2.47.2 From 8dfe22682ae2786513e52de0e8c67691b9d8a5e1 Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Fri, 20 Sep 2024 22:05:36 +0000 Subject: [PATCH 05/10] chore: ignore files/folders in git and docker --- .dockerignore | 33 +++++++++++++++++++++++++++++++++ .gitignore | 6 ++++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..12c776b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,33 @@ +.dockerignore +docker-compose.yml +docker-compose.*.yml + +# Ignore git, but keep git HEAD and refs to access current commit hash if needed: +# +# $ cat .git/HEAD | awk '{print ".git/"$2}' | xargs cat +# d0b8727759e1e0e7aa3d41707d12376e373d5ecc +.git +!.git/HEAD +!.git/refs + +# Common development/test artifacts +/cover/ +/doc/ +/test/ +/tmp/ +/.elixir_ls +/.elixir-tools/ + +# Mix artifacts +/_build/ +/deps/ +*.ez + +# Generated on crash by the VM +erl_crash.dump + +# Static artifacts - These should be fetched and built inside the Docker image +/assets/node_modules/ +/priv/plts/ +/priv/static/assets/ +/priv/static/cache_manifest.json diff --git a/.gitignore b/.gitignore index 92ca450..c63085e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ # paths +/.elixir_ls/ +/.elixir-tools/ /_build/ /cover/ /report/ @@ -13,5 +15,5 @@ erl_crash.dump *.ez wabanex-*.tar docker-compose.*.yml -priv/docker/pgcli/history -priv/docker/pgcli/log +/priv/docker/pgcli/history +/priv/docker/pgcli/log -- 2.47.2 From 23cfc7738b7fb48f6054f181e67335fca2499c46 Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Fri, 20 Sep 2024 22:08:41 +0000 Subject: [PATCH 06/10] chore: remove unused services --- docker-compose.yml | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index c4a520f..5924a18 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,13 +13,13 @@ services: - 'db_data:/var/lib/postgresql/data' restart: unless-stopped app: - image: &app_image 'joaodubas/ex_trainer:${EX_TRAINER_TAG:-dev}' + image: 'joaodubas/ex_trainer:${EX_TRAINER_TAG:-dev}' build: target: builder context: . args: BUILD_MIX_ENV: dev - hostname: app + hostname: &app_host ex_trainer depends_on: - db init: true @@ -42,7 +42,7 @@ services: action: sync+restart - path: ./mix.lock action: rebuild - environment: &app_environment + environment: DNS_CLUSTER_QUERY: *app_host POSTGRES_HOST: *db_host POSTGRES_USER: *db_user @@ -51,30 +51,8 @@ services: working_dir: /opt/app restart: unless-stopped scale: 2 - entrypoint: sleep - command: infinity - db_setup: - image: *app_image - depends_on: - - db - profiles: - - setup - environment: *app_environment - restart: 'no' - command: | - mix ecto.setup \ - && MIX_ENV=test mix ecto.setup - db_migrate: - image: *app_image - depends_on: - - db - profiles: - - migrate - environment: *app_environment - restart: 'no' - command: | - mix ecto.migrate \ - && MIX_ENV=test mix.ecto.migrate + entrypoint: ./priv/docker/service/docker-entrypoint.sh + command: local-cookie volumes: db_data: {} -- 2.47.2 From fe32f3f2075bab646a838c12babf39cdc096668d Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Fri, 20 Sep 2024 22:09:53 +0000 Subject: [PATCH 07/10] feat: upgrade elixir and erlang runtimes --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0bb3f02..c8360d6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -ARG ELIXIR_VERSION=1.17.2 -ARG OTP_VERSION=27.0.1 -ARG DEBIAN_VERSION=bookworm-20240701-slim +ARG ELIXIR_VERSION=1.17.3 +ARG OTP_VERSION=27.1 +ARG DEBIAN_VERSION=bookworm-20240904-slim ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}" ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}" -- 2.47.2 From c3104ac1c74c7588aa12ae44ba47a8f730df17a5 Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Sun, 22 Sep 2024 14:09:39 +0000 Subject: [PATCH 08/10] chore: improve make targets 1. Remove deps upgrade, since we're using the watch definition 2. In it's place add target to start services with watch option 3. Adjust ecto interaction to run command directly 4. Remove tests for now because the folder isn't synced in the image --- Makefile | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index ab5f641..20683ff 100644 --- a/Makefile +++ b/Makefile @@ -32,21 +32,17 @@ test: ## run tests compose_up: ## start containers for this service @$(COMPOSE) up -d -.PHONY: compose_deps_upgrade -compose_deps_upgrade: ## install/upgrade deps - @$(COMPOSE) run --entrypoint mix app do deps.get, deps.compile, compile - -.PHONY: compose_test -compose_test: ## run tests in containers - @$(COMPOSE) run -e MIX_ENV=test --entrypoint make app test +.PHONY: compose_watch +compose_watch: ## start containers for this service watching for updates in filesystem + @$(COMPOSE) up -w .PHONY: compose_database_create compose_database_create: - @$(COMPOSE) --profile setup run db_setup + @$(COMPOSE) run --rm --entrypoint mix app ecto.create .PHONY: compose_database_migrate compose_database_migrate: ## apply migrations to our database - @$(COMPOSE) --profile migrate run db_migrate + @$(COMPOSE) run --rm --entrypoint mix app ecto.migrate .PHONY: compose_database_setup compose_database_setup: compose_database_create compose_database_migrate ## create and apply migrations -- 2.47.2 From ce214c85933ec7cd4e3a612ee9bf167e89267546 Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Sun, 22 Sep 2024 14:12:53 +0000 Subject: [PATCH 09/10] chore: add target to connect to a remote host --- Makefile | 4 ++++ priv/docker/service/docker-remote.sh | 2 ++ 2 files changed, 6 insertions(+) create mode 100755 priv/docker/service/docker-remote.sh diff --git a/Makefile b/Makefile index 20683ff..9e7f75f 100644 --- a/Makefile +++ b/Makefile @@ -51,6 +51,10 @@ compose_database_setup: compose_database_create compose_database_migrate ## cre compose_ps: ## status of containers @$(COMPOSE) ps +.PHONY: compose_remote +compose_remote: ## connect to remote node + @$(COMPOSE) exec app ./priv/docker/service/docker-remote.sh + .PHONY: help help: @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/priv/docker/service/docker-remote.sh b/priv/docker/service/docker-remote.sh new file mode 100755 index 0000000..1a543ec --- /dev/null +++ b/priv/docker/service/docker-remote.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +iex --name ex_trainer_remote@127.0.0.1 --hidden --cookie local-cookie --remsh ${HOSTNAME}@$(hostname -i | cut -d ' ' -f1) -- 2.47.2 From e79366a43accd43e6f97b70b64644eb4e70146ee Mon Sep 17 00:00:00 2001 From: Joao P Dubas Date: Sun, 22 Sep 2024 14:13:51 +0000 Subject: [PATCH 10/10] chore: scale apps to 3 nodes --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 5924a18..05612ac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,7 +7,7 @@ services: environment: POSTGRES_USER: &db_user postgres POSTGRES_PASSWORD: &db_pass postgres - POSTGRES_DB: &db_name postgres + POSTGRES_DB: postgres volumes: - './priv/docker/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql' - 'db_data:/var/lib/postgresql/data' @@ -50,7 +50,7 @@ services: POSTGRES_NAME: wabanex_dev working_dir: /opt/app restart: unless-stopped - scale: 2 + scale: 3 entrypoint: ./priv/docker/service/docker-entrypoint.sh command: local-cookie -- 2.47.2