Home > Net >  Environment variables from .env and/or docker-compose not replaced in Dockerfile CMD
Environment variables from .env and/or docker-compose not replaced in Dockerfile CMD

Time:09-28

I'm trying to pass a couple of environment variables from an .env file in the root of the project to the Dockerfile's CMD. I've read through the numerous other similar questions here on SO but nothing has made this work. What am I doing wrong?

.env (in root of project)

TOKEN=AToken
DECK=ADeck

docker-compose.yml (in root of project)

version: "3"
services:
  discord-initiative-savageworlds:
    build:
      context: .
    environment:
        - TOKEN=${TOKEN}
        - DECK=${DECK}

And the Dockerfile (in root of project):

FROM ubuntu:latest
ARG TOKEN
ARG DECK
...Run Installers and Stuff...
COPY . .
RUN dotnet publish
RUN cd DiscordInitiative/bin/Debug/net5.0/publish
RUN echo "${TOKEN}"
CMD ./DiscordInitiative --token="${TOKEN}" --deck="${DECK}"

Running docker-compose up builds the project successfully, but the CMD shows that the environment variables are not being replaced:

Step 12/13 : RUN echo "${TOKEN}"
 ---> Running in 7096ef978516

Removing intermediate container 7096ef978516
 ---> 6985b62bb75e
Step 13/13 : CMD ./DiscordInitiative --token="${TOKEN}" --deck="${DECK}"

The project & branch this is in is on GitHub here.

Thanks for any tips!

CodePudding user response:

The .env file and the environment directive in your docker-compose file are Docker Compose concepts applying at runtime, not applying to image build. Your configuration would inject those environment variables to the built, running container, but it won't inform the build environment.

(Edit: Upon reflection, this may be what you actually want.)

You could fully leverage the ARG instruction in your Dockerfile by changing your docker-compose to say:

version: "3"
services:
  discord-initiative-savageworlds:
    build:
      context: .
      args:
        - TOKEN=${TOKEN}
        - DECK=${DECK}

This will effectively set your 'environment' at build time, and will enable your Dockerfile to function as pasted above.

Edit:

I suspected there might be things in the redacted portion of the Dockerfile that could throw wrenches. The TL;DR from our comment thread is that your Dockerfile would need to change, too:

FROM ubuntu:latest
...Run Installers and Stuff...
COPY . .
RUN dotnet publish
RUN cd DiscordInitiative/bin/Debug/net5.0/publish
ARG TOKEN
ARG DECK
RUN echo "${TOKEN}"
CMD ./DiscordInitiative --token="${TOKEN}" --deck="${DECK}"

Moving those ARG instructions as near to the bottom as possible sets them from your docker-compose.yml after a bunch of other RUN instructions, and similar things that have the potential to blow away the intermediate container state.

Edit 2:

In reality, though, what you're asking for is variables that are available in the container at runtime (when CMD is executing). So, your question would lead me to believe that you don't need the ARGs at all, and that your container would function as expected.

Also, if you eliminate the ARGs you can get rid of the RUN echo ..., as that would never return anything at that point in the build process.

Injecting ARGs is totally not what you want to do with sensitive values, as the arguments then become a part of your image layers, and subject to snooping. The pattern of injecting sensitive values to the environment at runtime is much preferred (though I wouldn't say most preferred).

  • Related