3

I have a situation where I need to set an ENV based on runtime condition like thus:

RUN if [ "$RUNTIME" = "prod" ] then VARIABLE="Some Production URL"; else VARIABLE="Some QA URL"; fi;
ENV={VARIABLE}

Been looking at different solutions but none of them seem to be panning out (for example the basic one where VARIABLE is lost when RUN exits). What would be an elegant way to achieve this?

Siyu
  • 11,187
  • 4
  • 43
  • 55
  • Possible duplicate of [Conditional Block in Docker](https://stackoverflow.com/questions/42719134/conditional-block-in-docker) – eLRuLL Dec 13 '18 at 23:04
  • 1
    Not the same. I Need a way to set ENV dynamically! the use case is kibana app talking to an elasticsearch backend. During different Runtime stages of our CICD process, i need to configure differernt ElasticSearch urls using `ENV ELASTICSEARH_URL=Dev/QA/Prod Elastic URLS' – Dorian McAllister Dec 14 '18 at 01:35
  • It seems that an script can help you with this. Depending of the value of the RUNTIME – Eddy Hernandez Dec 14 '18 at 04:46
  • that is what i was thinking - but how would i set an ENV inside a sh script? the problem didn't seem to be getting solved – Dorian McAllister Dec 14 '18 at 11:49

3 Answers3

3

The literal conditional execution can be achieved with multistage build and ONBUILD.

ARG mode=prod

FROM alpine as img_prod
ONBUILD ENV ELASTICSEARH_URL=whatever/for/prod

FROM alpine as img_qa
ONBUILD ENV ELASTICSEARH_URL=whatever/for/qa

FROM img_${mode}
...

Then you build with docker build --build-arg mode=qa .

Siyu
  • 11,187
  • 4
  • 43
  • 55
1

It is an unfortunate constraint that you only have this "dev/qa/prod" environment variable. However, it is possible to achieve what you want.

First, you might consider baking your environment specific configuration into the image for all environments. (Normally I would discourage to do this!) For example you can COPY three files into your image:

  • dev-env.sh: contains your dev config in the form: ELASTICSEARCH_URL=http://elastic-dev:123
  • qa-env.sh (similar)
  • prod-env.sh (similar)

Then you evaluate at run-time (not at build-time) in which environment you are: You add an ENTRYPOINT script to your image which will source the correct file, depending on the ENVIRONMENT_NAME variable.

Dockerfile (part):

ENTRYPOINT ["docker-entrypoint.sh"]

docker-entrypoint.sh (copied into WORKDIR of the image):

#!/bin/bash
set -e

if [ "$ENVIRONMENT_NAME" = "prod" ]; then
    source prod-env.sh
fi
# else if qa ... , else if dev ..., else fail

exec "$@"

This script will run when you launch the docker container, so this approach is no option for you if you need the variables to be available in Dockerfile-instructions (at build-time).

Another (build-time) workaround is described here and consists of using temporary files to store environment variables across multiple image layers.

Fabian Braun
  • 3,612
  • 1
  • 27
  • 44
0

Wouldn't passing env var with docker run be the solution you need? Something like this:

docker run -e YOUR_VARIABLE="Some Production URL" ...

Izydorr
  • 1,926
  • 3
  • 23
  • 40
  • we dont pass runtime. its passed by our CICD pipelines that we dont own. the only runtime envs we have are the deploy environment dev/qa/prod – Dorian McAllister Dec 14 '18 at 11:48
  • Why don't you determine the Elasticsearch URL just before starting Kibana? Either in entrypoint or in any other scipt you use. Check there your ENV and configure Kibana properly. – Izydorr Dec 15 '18 at 22:25