asolvent
asolvent

Reputation: 881

How to embed environment variables in a docker image in azure devops pipeline?

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?

Upvotes: 5

Views: 4232

Answers (1)

David Garza
David Garza

Reputation: 173

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.

Upvotes: 2

Related Questions