0

I have a docker container running and I want to execute command make target-branch branch="branch_name" so that inside container I have TARGET environment variable set to "branch_name".

I tried writing the following in Makefile

target-branch:
    @ export TARGET=$(branch)

It didn't work, after going inside container and executing printenv there is no such environment variable.

Also tried exporting it using bash script

--- Makefile ---
target-branch:
    @ sh scripts/set_target_branch.sh $(branch)

--- scripts/set_target_branch.sh ---
#!/bin/bash

export TARGET="$1"
echo $TARGET

After make target-branch branch="branch_name", echo inside script outputs "branch_name", but the TARGET variable still absents inside the container upon printenv.

Just in case, my Dockerfile, docker-compose.yml,

Slava.In
  • 597
  • 1
  • 9
  • 22
  • what does `echo $(branch)` do inside your target? Another option is to set the env var on the same line as your command: `TARGET=$(BRANCH) docker run ...` – Larry Oct 06 '22 at 06:02
  • `echo` is just to show that `TARGET` variable has the proper value upon script execution. I want to set it while container is running already, so I can change it any amount of times while container is up. – Slava.In Oct 06 '22 at 06:06
  • 1
    are dynamic env vars possible with Docker? I thought a restart was always required. This answer uses files and volumes for dynamic values coming from the host: https://stackoverflow.com/a/45894934 - may be useful here – Larry Oct 06 '22 at 06:10
  • 1
    You are apparently trying to export a shell variable from a child process to its parent process. This is not possible. It is the parent process that must set the environment variable. One ugly workaround would be to use your Makefile to print the export command (`@printf 'export TARGET="%s"\n' "$(branch)"`) and use `eval` when invoking `make`: `eval "$(make target-branch branch="branch_name")"` (warning: this is dangerous and your Makefile shall print only this, nothing else). But directly typing `export TARGET="branch_name"` is much simpler and natural. – Renaud Pacalet Oct 06 '22 at 06:25
  • And if you are trying to run `make` from outside your container things are even worse: you cannot directly set the environment variables of a process inside your container from outside. And this is a good thing (imagine the safety and security issues if this was possible...) – Renaud Pacalet Oct 06 '22 at 06:32
  • 1
    If this is what you want (set the variable from outside) one possibility would be to mount a volume in your container, regularly update a file in the volume from the outside of your container, and use its content inside your container. The file could be a source-able shell script (`export TARGET="branch_name"`) or anything you want. Of course this solution also has safety and security implications that you should consider. – Renaud Pacalet Oct 06 '22 at 06:39
  • The fundamental problem is that each `make` recipe runs a subprocess whose environment disappears as soon as it exits. To successfully `export` something, you need to run whatever needs to read what you `export`ed as a subprocess of the process which did the `export`. This is a common FAQ. – tripleee Oct 06 '22 at 06:43
  • 1
    As an aside, littering your `Makefile` with `@` makes debugging harder. If you don't want to see what it's doing, use `make -s` – tripleee Oct 06 '22 at 06:43
  • Does [How can i pass ENV variables between make targets](https://stackoverflow.com/questions/38927419/how-can-i-pass-env-variables-between-make-targets) describe this case? I can't totally tell from this question how the `TARGET` variable is intended to be used. – David Maze Oct 06 '22 at 10:01
  • @DavidMaze , it's less about targets, and more about just passing/changing environment variable inside container – Slava.In Oct 06 '22 at 10:03

1 Answers1

0

Thanks to @Larry , @RenaudPacalet and this post

It seems that the better way to handle environment variable in this case is to just set it upon docker start (docker compose-up in my case), so what I did:

--- .env ---
TARGET_BRANCH=master

--- docker-compose.yml ---
services:
  my-app:
    environment: 
      TARGET: "${TARGET_BRANCH}"

--- Makefile ---
start:
    IMAGE=$(IMAGE) \
    CONTAINER=$(CONTAINER) \
    docker-compose up -d 

So to change TARGET you would just change TARGET_BRANCH in .env to whatever is needed, and then execute make start to update it inside container.

Slava.In
  • 597
  • 1
  • 9
  • 22