How should the docker compose variables work?

It seems that the env substitution doesn’t work as expected using local mode.

version: "2.1"

services:
  env-config:
    image: arribada/env-config
    environment:
      CONFIG: "${PROMETHEUS_CONFIG}"

I tried few different variation, but {PROMETHEUS_CONFIG} never gets substituted and inside the container it is just as CONFIG="{PROMETHEUS_CONFIG}".

I don’t want to put the text directly as this is checked out on github so it will expose secrets and configs.

The second question is for when I switch to non local mode in the balena portal should I set PROMETHEUS_CONFIG or the CONFIG env variables to get these substituted?

To pass a CONFIG var to your devices you can just set that variable in the dashboard, and when operating in local mode you can pass a --env CONFIG="..." argument to balena push. There is no need for the config: line in your compose file.

Thanks,
Is there a workaround if 2 services use the same config name but expect different content?

for example
service1 expects $CONFIG=“param=1”
service2 expects $CONFIG=“target=localhost”

the question is mainly for the portal

btw I just tried the suggestion with a multiline env variable and it couldn’t parse it:

export PROMETHEUS_CONFIG="
global:
  scrape_interval:     5s 
scrape_configs:
  - job_name: 'lora-connect'
    static_configs:
    - targets: ['192.168.0.113:8070']
alerting:
  alertmanagers:
  - static_configs:
    - targets:
        - localhost:9093
rule_files:
    - alert_rules
"
balena push 192.168.0.113 --env PROMETHEUS_CONFIG="$PROMETHEUS_CONFIG"

the error is :

Unable to parse environment variable: PROMETHEUS_CONFIG=".......

How about using multiline env vars in the docker-compose.yml? I’ve tried it like this, and could successfully deploy, and seems it’s a multiline env var on the other side.

...
    environment:
      - |
        PROMETHEUS_CONFIG=
        global:
          scrape_interval:     5s
        scrape_configs:
          - job_name: 'lora-connect'
            static_configs:
            - targets: ['192.168.0.113:8070']
        alerting:
          alertmanagers:
          - static_configs:
            - targets:
                - localhost:9093
        rule_files:
            - alert_rules

then in the container I can go:

root@67a57cfa4657:/usr/src/app# printf %s "$PROMETHEUS_CONFIG"
global:
  scrape_interval:     5s
scrape_configs:
  - job_name: 'lora-connect'
    static_configs:
    - targets: ['192.168.0.113:8070']
alerting:
  alertmanagers:
  - static_configs:
    - targets:
        - localhost:9093
rule_files:
    - alert_rules

Yes that might be even better with one problem some devices deployed in the same application need a different config.
If I set the same env var in the GUI will that override the one set in the compose file?

I can’t test it now as the balena cli doesn’t work in production mode with pre built multi arch images, that is why I am using local mode for now.

Also the compose file is checked in on github so need to look through all configs to make sure not to expose passwords and sensitive information.

Hi,
Yes the env vars that are set in the dashboard are considered runtime level and therefore overwrite values defined in the compose file.

Thanks, the only other problem that remains is that some of these config env vars contain passwords so adding those directly in the compose file and checking it on github will expose those on the internet.

opened an issue for the multi line support

I think what my colleague is saying is to use env vars for the passwords and pass the values at runtime, form the dashboard. This way they do not have to be committed to github.

some passwords are inside the config files.

so far I have always set passwords and API keys by means of device service variables in the balenaCloud dashboard.

If passwords/API keys should be set in config file(s) then in start script of your docker service you must first update the config file(s) based on the passwords/API keys set by the device service variables before launching the application/service that is reading the configuration from these config file(s).

@janvda thanks for the suggestion. Sounde like the movie inception :slight_smile: replacing env variable inside an env variable. I will try it and who knows it might work out well.

All that said I still think the balena push --env=.. should support multiline env variables.

just for reference the config file that includes password is the routing_key in the Alert Manager
https://prometheus.io/docs/alerting/configuration/#pagerduty_config

apparently prometheus doesn’t support environment variables in their configuration files (https://github.com/prometheus/prometheus/issues/2357).

If there is no other way than using a configuration file for this then in your docker service startup script you must do a substitute of the FAKE routing_key you have specified in the configuration file by the actual routing_key that is stored in the environment variable.

Not clear to me how multiline env variables might also solve this issue.

I have developped a simple tool that converts an env variable into a file which is than used in the AlertManager container. Allowing multiline env variables would make it possible to NOT add the env variable directly in the compose file and pass it vie the cli

balena push --env ALERTMANAGER_CONFIG="$ALERTMANAGER_CONFIG" 192.168.0.113

or set it via the balena portal GUI.
I currently can’t use the gui due to this bug:

P.S I have now added suport to the envToFile tool to expand the env vars so will test shortly and will let you know if it worked.