3
votes

My requirement is to set few environment variables on the docker image that is built by azure devops pipeline.

This pipeline is used for dev/stage/production environments, each stage is tied to its own set of group variables, these variables I want to be available in nodejs app.

I can read the variables within the pipeline using $VARNAME but cant read same when the code runs using process.env.VARNAME.

I understand that it is not the best approach as the image would have environment variables which may potentially have secrets hence I am open to different ideas as well.

What I have tried so far: Added ARG in dockerfile ARG VARNAME=somevalue on the docker build task added

- task: Docker@2
  displayName: Build docker image
  inputs:
    command: build
    repository: $(imageName)
    tags: $(Build.BuildId)        
    buildContext: '$(Pipeline.Workspace)/PublishedWebApp'
    arguments: --build-arg SOMEVAR=anewvalue

I try to access this as process.env.SOMEVAR in nodejs code.

I can actually see the --build-arg on the docker build executed in the pipeline but in the code it never appears.

What I am after is pretty standard requirement, we have multiple environments, each environment will have different keys (different group variables tied to different stage), how do I pass different keys to the deployment?

1
iirc when you use the predefined Azure Devops Docker task, you can submit build args on a docker build task --build-arg STAGE=$(VAR_STAGE)" - see docs.microsoft.com/en-us/azure/devops/pipelines/tasks/build/… - but then you cannot use the build_and_push task but you have to split the build and the push partkgorskowski
Thanks for the pointer, I tried arguments: --build-arg varname=whatever but this also doesnt reflect with in the code. process.env.varname comens as undefined. I had a look here docs.docker.com/engine/reference/commandline/build it says that it sets it for the build time, does that mean it wouldnt be available later the app would run?asolvent
ah I reckon I need to put that as ARG in docker file first, trying thatasolvent
even after adding ARG, it didnt workasolvent

1 Answers

1
votes

There are a few components from what I can see that need to align:

  1. You are passing the key via --build-arg. This is correct.
  2. You have an ARG in the dockerfile to receive what is passed in via --build-arg. This is correct.
  3. You are missing setting the environment variable equal to the passed-in arg.
FROM python:3.7-slim

ARG SOME_PASSED_IN_ARG
ENV SOMEVARNAME $SOME_PASSED_IN_ARG
...

You would access SOMEVARNAME like process.env.SOMEVARNAME from the node application.

I give credit to @levi-lu-msft in their post here: https://stackoverflow.com/a/59784488/1490277

As for best practice, defining logic default environment variables in the container at BUILD is perfectly acceptable (e.g. ENV=PRODUCTION). At RUN, you are able to to overwrite any environment variable using passed in arguments:

docker run ... --e SOME_PASSED_IN_ARG=someOtherValue

A few "better" practices:

  1. Containers are meant to be repeatable. Don't embed at BUILD time environment variable that will expire/change over time. In other words, if you decide to deploy a version from 3yrs ago and a BUILD time environment variable has an expired value (e.g. coupon code), your environment could be fragile and unpredictable.
  2. Never embed secrets in the container at BUILD. #1 above because they may change overtime and also for security. Secret values (e.g., one-time keys, tokens, etc.) are available to anyone (bad actor or mishap actor) to extract simply by listing the environment variables of the image when running.