Distillery 2 / Docker - Runtime different parameters with the same prod release

We are migrating our umbrella apps to docker / kubernetes.
We already have a working build process that uses docker build cache and correctly build a “frontend” and “backend” images. (Derived from this guide: Kubernetes Native Phoenix Apps: Introduction. They both shares few apps from our umbrellla, with slight different env variables. (the difference in image size currently not a issue)

Whats is the available ways to run slight different (one to a very few parameters) variations of a specific / prod image? We do use a lot of application.get_env, but those final “runner” images dosen’t have them, only the compiled release.
This will reduce to a single prod image.
Is it the best approach?

Config providers are more suitable to run different complete envs (like prod or dev)?

1 Like

I’d honestly just have multiple environments, you can ‘include’ base configs and just refine values in them so it would minimize duplication.

Well according to Twelve factor App, you should really have one release application, and by one I mean, one codebase/compiled/bundled app (probably with distillery and mix release), while “environment” specific stuff should be config provided via ENV vars or config files (with sane defaults) that application loads at start.

If you choose ENV vars, and if you use distillery >= 2.0.0 for release, you could easily read ENV at runtime with distillery plugin called config tuple.

Finally, your code looks like
config/config.exs:

config :api_search,
   :elastic,
   elastic_url:
     {:system, "ELASTIC_URL", "elasticsearch-client.elasticsearch.svc.cluster.local"}

usage somewhere in lib/application.ex:

...
env = Application.get_all_env(:api_search)
elastic_url = env[:elastic][:elastic_url]
...

If you succeed this, since you’ve mentioned docker in title, you have one release binaries and you’re making one docker image that could be run everywhere (staging, qa, prod, etc…).

1 Like

Thanks for the remind that I have to update the documentation in the forum, there are new features :slight_smile:

1 Like

I got “Unable to configure release!”.
How do I pass new env when calling “_build/dev/rel/app/bin/app console”?

application.ex

...
extra_services = {:system, "EXTRA_SERVICES", type: :string, default: "false"}
...

this

extra_services = {:system, "EXTRA_SERVICES", type: :string, default: "false"}

should go in config/config.exs

(like i mentioned in my post) and if you put and configured distillery plugin (mentioned in my last post), you should be able to fetch value from environment variable via

Application.get_all_env(:atom_of_your_app_name)

Recap:

  • distillery >= 2.0
  • mix.exs - deps
    {:config_tuples, "~> 0.2.1"}
  • rel/config.exs - in release :atom_of_your_app_name do section add
    set config_providers: [ConfigTuples.Provider]
  • config/config.exs - add config line, ie:
    config :atom_of_your_app_name,
    :services,
    extra_services: {:system, "EXTRA_SERVICES", type: :string, default: "false"}
  • now in you application.ex you can use populated value from environment like
    env = Application.get_all_env(:api_search)
    env[:atom_of_your_app_name][:services][:extra_services]
  • note :atom_of_your_app_name should be same as in mix.exs -> def project, app:

Btw. full ConfigTuple config is here

1 Like