TimothyYe / godns

A dynamic DNS client tool that supports AliDNS, Cloudflare, Google Domains, DNSPod, HE.net & DuckDNS & DreamHost, etc, written in Go.
https://timothyye.github.io/godns/
Apache License 2.0
1.5k stars 220 forks source link

Configure GoDNS Docker container via environment variables #171

Closed drewgingerich closed 2 years ago

drewgingerich commented 2 years ago

I'm interested in being able to configure my Docker-deployed instance of GoDNS with just environment variables. This way I don't have to create a new image containing my config file. I can think of three ways to do this:

  1. Add a CLI that has feature parity with the config file. This could be done like Traefik does it, using CLI flags with a dot syntax that is parsed to build the configuration object.
  2. Add a simplified CLI that supports only a basic case such as one provider and one domain.
  3. Add templating to the config file, and provide a simple default config file inside the Docker image that's set up to accept a few environment variables. Something like:
    // godns-config.json
    {
     "provider": "{{ .GODNS_PROVDER_NAME }}",
     "login_token": "{{ .GODNS_PROVIDER_TOKEN }}",
     "domains": [
       {
         "domain_name": "{{ .GODNS_DOMAIN }}",
         "sub_domains": "{{ .GODNS_SUBDOMAINS }}"
       }
     ],
     "ip_url": "{{ .GODNS_IP_RESOLVER_URL }}",
     "ip_type": "{{ .GODNS_IP_TYPE }} ",
     "interval": "{{ .GODNS_INTERVAL }}",
     "resolver": "{{ .GODNS_DNS_RESOLVER_IP }}",
     "debug_info": "{{ .GODNS_DEBUG }}"
    }

Of these, I like option 3 the most. Option 1 is cool, but is also complicated. Option 2 feels like it could become a dead-end. Option 3 extends what already exists.

I'm interested to know your thoughts, does this sound like a good direction and solution? If this does sound good then I'll plan to get started sometime soon.

TimothyYe commented 2 years ago

So for option 3, it also only supports one provider and one domain?

TimothyYe commented 2 years ago

The current solution for the docker container is that you can mount a config file out of the container, there is no need to create a new image with the config file. I'm not sure if this can meet your requirement.

docker run \
-d --name godns --restart=always \
-v /path/to/config.json:/config.json \
timothyye/godns:latest
drewgingerich commented 2 years ago

So for option 3, it also only supports one provider and one domain?

Yes, but for more complex configurations the user can mount their own config as they do now. The way Docker works, the user-provided config file will shadow the default config file, adding up to keeping the same user experience that exists right now, plus a small convenience bonus for people that only need to update one domain.

TimothyYe commented 2 years ago

I see, if we choose option 3, does that mean the GoDNS program inside the container should read all the environment variables and compile the config template file into a real config file at the runtime?

drewgingerich commented 2 years ago

The current solution for the docker container is that you can mount a config file out of the container, there is no need to create a new image with the config file. I'm not sure if this can meet your requirement.

docker run \
-d --name godns --restart=always \
-v /path/to/config.json:/config.json \
timothyye/godns:latest

Ah sorry, I should have provided more detail. I interact with my server remotely from my laptop by using a Docker context. This lets me work on my Docker Compose configuration on my laptop, and then push the changes to my server using normal Docker commands.

While this is convenient in most ways, a weakness is that any files a Docker container mounts still have to exist on the server. So to mount a GoDNS config file I have to copy it from my laptop to the server, or I have to make a custom image that contains the config file to carry it over for me.

drewgingerich commented 2 years ago

I see, if we choose option 3, does that mean the GoDNS program inside the container should read all the environment variables and compile the config template file into a real config file at the runtime?

Yes exactly, and that's where solution 3 would be a change to how things are.

drewgingerich commented 2 years ago

Alternatively we could avoid touching GoDNS at all and just use envsubst to populate a default config shell template (rather than a Go template). I can make this version and you can see how you like the end result before considering whether GoDNS should do its own templating.

drewgingerich commented 2 years ago

Oops I didn't realize the current image doesn't have a shell, so envsubst is not easily available. Adding envsubst feels pretty hacky, so I don't want to do that.

I partially raised this issue just to talk it through with you. Now that I've gotten to think about it more I'm feeling like this doesn't make sense to do right now since it adds complexity without much value. If there's a different use for a CLI or config file templating in the future then I'll bring this back up, but for now I'll close this issue. Plenty of other stuff to work on :)