discuit icon indicating copy to clipboard operation
discuit copied to clipboard

[Feature Request] Docker: Support Configuration via Environment Variables

Open Codycody31 opened this issue 11 months ago • 4 comments

Summary

Currently, discuit relies on a YAML file for configuration. While this works well in many scenarios, Docker and other containerized environments often prefer using environment variables for configuration due to their simplicity, security, and ease of use with container orchestration tools like Kubernetes and Docker Compose. This feature request proposes an enhancement to allow discuit to be configured using environment variables, in addition to the existing YAML file-based approach.

Motivation

In containerized deployments, managing configuration files can be cumbersome and less secure. Environment variables, on the other hand, can be easily injected into containers at runtime, making them ideal for such environments. Supporting environment variables would make discuit more flexible and easier to deploy in a variety of environments, following the twelve-factor app methodology.

Proposed Solution

Introduce the capability to read configuration settings from environment variables, with a clear precedence order where environment variables override the settings defined in the YAML file. This allows users to provide a base configuration through the YAML file while overriding specific settings with environment variables as needed.

Considerations

  • Each configuration option should have a corresponding environment variable, potentially prefixed with DISCUIT_ to avoid clashes with other environment variables (e.g., DISCUIT_DBADDR for dbAddr).
  • The application should clearly document this functionality and the precedence of environment variables over YAML file settings.
  • This change should be backward compatible, not affecting existing deployments that use only the YAML file for configuration.

Benefits

  • Flexibility: Users can choose the most convenient way to configure discuit, whether through a file, environment variables, or a combination of both.
  • Security: Sensitive information like database credentials can be more securely managed through environment variables, especially in cloud environments.
  • Container Compatibility: This enhances compatibility with Docker and other container platforms, aligning discuit with common practices in containerized application deployment.

Issues

  • The UI relies on the config.yaml for its information which is gathered when it is built. So for this to work, an alternative solution will need to be found.

Yup I used GPT, There is no way I could make my idea sound this good/well formatted

Codycody31 avatar Feb 28 '24 02:02 Codycody31

Sounds good. What we'd need here is a function to go through the env variables and populate config.Config struct, overriding the fields that correspond to env variables found.

previnder avatar Mar 06 '24 09:03 previnder

That's kind of what I was able to do here. It's still a WIP but it does work. The next bit I was looking at would be adding something like -injectEnv or something similar which could be called via the UI prod build to have discuit return a YAML file with the injected env vars. However, I am unsure if that would work as the webpack.common.js script would need to run it (Mainly, not sure if possible to use os or something so I need to check).

Codycody31 avatar Mar 06 '24 15:03 Codycody31

I totally forgot that the config file is also used by node. That makes it a bit tricky, for sure.

previnder avatar Mar 09 '24 08:03 previnder

Yeah, I started working on it. However, it doesn't seem to be too hard to do. I'll need to test it out in docker to ensure it works before I go through a PR together. Also, what do you think a good flag name for this would be? I threw it together as flag.BoolVar(&f.injectConfig, "inject-config", false, "Inject environment variables to yaml")`, though I am not sure how you would prefer it to be.

// RecreateYaml creates a new yaml file with default values and returns a Config.
func RecreateYaml(c Config) (string, error) {
	yamlData, err := yaml.Marshal(c)
	if err != nil {
		return "", err
	}

	// Return the yaml file content as a string
	return string(yamlData), nil
}

Codycody31 avatar Mar 21 '24 03:03 Codycody31