Hacker News new | ask | show | jobs
by fio_ini 1405 days ago
You can accomplish the same thing using environment variables. You can pass them in at build time or deploy time. `ENVIRONMENT=dev docker-compose up` or `docker-compose build --build-arg ENVIRONMENT=dev` and in your case maybe you write some function `find_answer() { something-async ... }; ENVIRONMENT=$(find_answer) docker-compose ...` You can also read in .env files... Which in my opinion is cleaner since you can check the configurations into source control for YAML or .env files which is easier to read than hundreds of lines of bash and it's esoteric syntax. I love bash but I'm just sayin.
1 comments

It's a simple example, maybe too simple to get the point. What I want is to conditionally set things on a yaml file. If you have ever used a templating language, you know this problem

    services:
        redis:
            ...
    
        {{ if some_condition }}
            volumes:
                bla bla
        {{ end if }}
    
        {{ if some_other_condition }}
        another_service:
            ...
        {{ end if }}
    
    volumes:
        {{ for volume in volumes }}
            - ...
        {{ end for }}
The compose file is declarative for clarity, so instead of fighting it, do the things you want to do at other levels. Variables? Pass in some env vars. Conditionals? You can specify multiple configuration files so that whatever calls `docker compose up` can deal with the conditionals of deciding which config files to include.
no haha I get the point but it's just another example I see someone over engineering a problem where it should be declarative. In what use case would you dynamically provision some arbitrary n number of volumes without knowing the path names to them? for volumes why wouldn't you just use "volume_name:/some/path" ... "another_volume:/another/path" and let docker manage the volume for you? you're going to end up writing in a different file "/some/path,/another/path" so why not just put it in the compose file?Also why wouldn't you just mount the root path and put n paths inside of them instead of making them all volumes? I'm struggling to see that you're use case actually needs such a feature and you're solving a problem for something that's actually broken somewhere else. you're adding some virtual layer that's making things harder to manage or understand because you don't understand all the features of docker compose technology instead of fixing the root of the issue. I'm not convinced that you're "feature" is necessary.
Everything is simple until someone asks you to try and diagnose (and hopefully fix) a bug on an upgrade between two different versions of a piece of software that can be deployed using 5 different strategies or that has 20 moving services...
your volume example is an anti-pattern in regard to something like the 12 factor app. you're conditionally changing and setting the volumes based on an environment your in? your code and service is gonna be busted. how would you even know if anything worked in prod if it's not reproducible in dev since # if dev then volume xyz else volume abc #
It's an anti-pattern just because you say so. This is a simplified example of a complex problem that needs arbitrary volume mounts. Using volume mounts to run software inside containers is a common dev pattern on scenarios where rebuilding takes too much time to quickly iterate. I am sorry, but unfortunately I cannot expand the issue further here to help you understand it, and I am happy too if you think I am over-engineering compose.
I honestly don't care if it's you misunderstanding or your teammates are building a bad framework/foundation to iterate upon. Doesn't matter to me either way bud. But you're going against the premise of docker and docker-compose which is write once and run anywhere because the services will be different every time you deploy since they'll have have variable path and file locations etc. - that's why it's an anti-pattern not because "i say so"
the point of docker-compose is partly so that your stack is ephemeral? you stand things up and shut it down with one simple switch and it can move between different environments and use the same declaration as the last environment. so now I gotta drag your bash script around and embed my yaml file in it? lol
The point of docker compose is to orchestrate containers. It's great for you to have lines that you always color inside, but other people choose different lines.
you're coloring outside the lines and making a mess you should grab a different coloring book this ones not for you.
Podman allows for Kubernetes templates, so theoretically you could use Helm for this potentially.. otherwise, Minikube on Podman. I wish they had Go templating in the compose files though, that would be rad.
Why do you want to set things conditionally like that?

This feels like it's a very incorrect solution to a problem that you're making far more complicated than it needs to be.

I apply this solution exclusively on the development environment. I have found that having the power to bail out to a shell whenever docker compose does not support something helps me iterate faster on my local dev (without affecting others).

The following is just a contrived example. Why would I do that? Because I can

    # Bring up services without a command
    #
    # usage:
    # nocmd.sh up -d service_name
    
    function _compose {
      docker-compose -f docker-compose.yml $@
    }
    
    function nocmd {
    cat << EOF
      services:
        $1:
          command: tail -f /dev/null
    EOF
    }
    
    function nocmd_compose {
      local service=${@: -1}
      _compose -f <(nocmd "$service") $@
    }
    
    nocmd_compose $@
I can punch myself in the dick but I don't