Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Environment variables are not applied on container build #1837

Closed
mclate opened this issue Aug 10, 2015 · 20 comments
Closed

Environment variables are not applied on container build #1837

mclate opened this issue Aug 10, 2015 · 20 comments

Comments

@mclate
Copy link

mclate commented Aug 10, 2015

When building container, environment variables are not applied.

docker-compose.yml:

img:
    build: img
    environment:
        VAR: Hello

/img/Dockerfile:

FROM python:2.7
RUN python -c 'import os; print os.environ["VAR"]'

Expected to have "Hello" written, received KeyError: VAR - missing environment variable.

If you get into container with docker-compose run --rm img bash (after removing that last failing line) and do python -c 'import os; print os.environ["VAR"]' you will get expected result.

docker-compose==1.3.3

docker-version:

Client version: 1.7.1
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 786b29d
OS/Arch (client): linux/amd64
Server version: 1.7.1
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 786b29d
OS/Arch (server): linux/amd64
@dnephin
Copy link

dnephin commented Aug 11, 2015

This is expected. The environment: key in the docker-compose.yml is the same as specifying it to the docker run command to start the container. build and dockerfile are the old keys used for building the image.

This is maybe not obvious from the documentation and could be improved.

Docker doesn't support injecting environment into the build environment (it must be part of the Dockerfile), but I believe there are some open proposals to add support for something like that.

@mclate
Copy link
Author

mclate commented Aug 11, 2015

Just a reference for anyone who find this issue, here is docker discussion regarding build-time variables: moby/moby#14634 and corresponding PR: moby/moby#15182

@mclate mclate closed this as completed Aug 11, 2015
@andrewmclagan
Copy link

This bit us hard, really needs better docs.

@darkn3rd
Copy link

The documentation is really confusing, e.g. talks about env-file, which is used for docker-compose.yml and is used for docker run. Given that docker-compose is an orchestration tool for building and running containers, it is easy to assume that environment would apply to build time, using --env <key>=<value> or something like this.

@cliffano
Copy link

Bit me as well.
Just to leave a note that environment variables can be set as build args in the compose file. Like others on this thread, I was initially expecting env_file or environment to be used by both build and run.
Verified with compose file v2, docker-compose v1.7, docker-engine v1.11 .

@aanand
Copy link

aanand commented Jul 20, 2016

Updated docs in #3747

@jwhitlark
Copy link

Note that if you need to include env vars from a file, you can do the following. This will require (in the docker-compose build section) args set from these variables, which you can then refer to in your docker file. This means that while you can't directly reuse your env_file, you can do so with a little extra work.

env $(cat vars.env | xargs) docker-compose up --build <whatever>

@williamli
Copy link

williamli commented Jul 21, 2017

the answer to this stack overflow question helped https://stackoverflow.com/questions/19537645/get-environment-variable-value-in-dockerfile

it is possible to map the .env environment variables to ARGS to be used by the Dockerfile during build.

docker-compose.yml

version: "2"
services:

  lumen:
    build:
      context: .
      dockerfile: ./Dockerfile
      args:
        - PORT=${PORT}
    volumes:
       ...

Dockerfile

FROM php:7.0-apache
ARG PORT

ENV PORT "$PORT"

EXPOSE ${PORT}
...

@PatrLind
Copy link

@williamli Can you add a link to the Stack Overflow question?

@Softwaremaker
Copy link

Softwaremaker commented Sep 4, 2017

Sorry guys - I am not sure I understand how to resolve this - and I would like to use a pre-built image.

For example, my compose file is:

version: '3'

services:
web1:
image: softwaremaker/web-w
environment:

  • wtmsdemo_customerapi01=http://api1/api/values
    ports:
  • "89:80"
    depends_on:
  • api1
    api:
    image: softwaremaker/api-w
    networks:
    default:
    external:
    name: nat

I used to think that the api image (softwaremaker/api-w) will be able to resolve into the environment variables I had set up above but it doesnt work.

@williamli
Copy link

williamli commented Oct 3, 2017

@PatrLind
added stackoverflow link to my original comment.

https://stackoverflow.com/questions/19537645/get-environment-variable-value-in-dockerfile

@remort
Copy link

remort commented Nov 12, 2019

The issue is still relevant for env files other than default .env file.
F.e. Next code will not work:

  nginx:
    env_file:
      - .env
      - .env.local
    environment:
     - SERVER_NAME=${SERVER_NAME}
    build:
      context: ./nginx
      dockerfile: Dockerfile
      args:
        server_name: ${SERVER_NAME}

while SERVER_NAME is defined in second env file (.env.local).
I see no options to pass env vars from .env.local to build context ((

@tarellel
Copy link

tarellel commented Nov 20, 2019

@remort
I can confirm this as well, if I have variables being used during build they are only passed to the build process if the the file is called .env if they are named .env.docker they don't get picked up. Even when the env_file is specified to use the .env.docker file.

My solution for this during my build copying the other named env file and renaming it to .env

COPY .env.docker ${APP_HOME}/.env
WORKDIR $APP_HOME

After this it appeared to pickup the environment variables when the container runs

Operating System: macOS (10.14.6)
Docker Desktop Version: 2.1.0.5 (40693)
Engine Version: 19.03.5
Compose: 1.24.1

@Adel-Magebinary
Copy link

Adel-Magebinary commented Feb 19, 2020

Hi guys,

A quick question for all of you, will this be a better way to build an image for dev? It works fine so far. However, is this the recommended practice? All images are based on buster.

FROM redis:buster as redis
RUN mkdir /env && env > /env/.env_redis
RUN cat /etc/passwd
RUN ls -lah /home
FROM ruby:slim-buster AS ruby
RUN mkdir /env && env > /env/.env_ruby

FROM node:lts-buster-slim AS node
RUN mkdir /env && env > /env/.env_node

#build nginx
FROM nginx:latest AS nginx
RUN mkdir /env && env > /env/.env_nginx

#build php
FROM php:fpm-buster AS php
#FROM php:7.3.14-fpm-buster AS php
RUN mkdir /env && env > /env/.env_php
COPY --from=redis / /
COPY --from=ruby / /
COPY --from=node / /
COPY --from=nginx / /

ADD conf/include-site.conf /etc/nginx/conf.d/include-site.conf
ADD conf/supervisord.conf /etc/supervisord.conf

RUN su root
EXPOSE 80 443
WORKDIR "/var/www/html"

ENTRYPOINT ["/bin/bash", "/start.sh"]

@ruslanzelinskyy
Copy link

ruslanzelinskyy commented May 3, 2020

Problem is still exists.
env_file key in build section will be more clear than passing env vars through args to container build.
Like this:

#NOT_WORKING
build:
      context: ./client
      dockerfile: Dockerfile
      env_file: ${CURRENT_ENV_FILE}

Because i am using shell scripts to build and up docker compose.
For production i need different env_file than for dev/local.
And there are many docker-compose.env.yml files with many args so it's not convinient as i think

@MausamGaurav
Copy link

I think there needs to be some elegant way around this. I really like the docker syntax and using arguments instead of environment variables doesn't make sense to me. I would not want want someone to manually change my docker-compose files. Changing values in the .env files appears consistent to me.

@sxiii
Copy link

sxiii commented Aug 11, 2021

This seems still haven't been fixed. I've spent today about 5 hours trying to figure this out. I've tried basically to use vars.env file to take username from it to create a new user during build of the container. I've tried enormous number of combinations of env_file link to the file; args: block and environment: block in docker-compose.yml; as well as different approached like adduser and useradd in the container itself. I've always got errors like: adduser: Only one or two names allowed.; executor failed running [/bin/sh -c adduser -G sudo terra]: exit code: 1; sometimes also exit code: 2 and some others. Tried enabling and disabling BUILD_KIT, etc. etc. The only way it works is when I hard-code the USERNAME in the Dockerfile. All other approaches does not work - seems either RUN useradd ... ... $USER or USER $USER commands are not working under any conditions. I don't want to use hostname variables here whatsoever, just the .env file. Why can't I use same env file for build and for running? Is there any ways around that? Help would be much appreciated. Thanks!

@g-kartik
Copy link

g-kartik commented Jan 7, 2022

The issue is still relevant for env files other than default .env file. F.e. Next code will not work:

  nginx:
    env_file:
      - .env
      - .env.local
    environment:
     - SERVER_NAME=${SERVER_NAME}
    build:
      context: ./nginx
      dockerfile: Dockerfile
      args:
        server_name: ${SERVER_NAME}

while SERVER_NAME is defined in second env file (.env.local). I see no options to pass env vars from .env.local to build context ((

Same here

@alanondra
Copy link

Some containers will have environment variables passed to them, some will not. Redis seems to be one of those containers that won't. At the moment this is the only container in my compose file (that I'm aware of) that seems to just flat-out ignore the environment file. Every other container where I'm using this strategy works fine.

# docker-compose.yml
redis:
    build:
        context: ./.docker/redis
        dockerfile: dockerfile
    env_file:
        - .env
    restart: unless-stopped
    networks:
        - app
# .docker/redis/dockerfile
FROM redis:7.0-rc-alpine

COPY etc/sysctl /etc/sysctl.d
COPY etc/redis /usr/local/etc/redis

# outputs "password: "
RUN echo "password: $REDIS_PASSWORD" >> /var/log/redis-build.log;

@jackgray
Copy link

jackgray commented Dec 12, 2023

Funny to see this is over 8 years old at this point. Seems like bread and butter stuff I am doing but can't figure out what else I should be doing...

ARG DEBIAN_VERSION=bullseye
ARG BASE_PYTHON_VERSION=3.10
###  Now, get a new machine with only the essentials  ###
FROM python:${BASE_PYTHON_VERSION}-slim-${DEBIAN_VERSION} as Application

# This makes the BASE_PYTHON_VERSION available inside this stage
ARG BASE_PYTHON_VERSION=3.10
ARG DEBIAN_VERSION=bullseye
[+] Building 1.2s (3/3) FINISHED                                                                                                                                                                      docker:default
 => [internal] load .dockerignore                                                                                                                                                                               0.4s
 => => transferring context: 2B                                                                                                                                                                                 0.0s
 => [internal] load build definition from Dockerfile                                                                                                                                                            0.7s
 => => transferring dockerfile: 32.61kB                                                                                                                                                                         0.0s
 => CANCELED [internal] load metadata for docker.io/kasmweb/desktop:1.14.0                                                                                                                                      0.0s
Dockerfile:708
--------------------
 706 |     ENV BASE_PYTHON_VERSION=3.10
 707 |     ###  Now, get a new machine with only the essentials  ###
 708 | >>> FROM python:${BASE_PYTHON_VERSION}-slim-${DEBIAN_VERSION} as Application
 709 |     
 710 |     # This makes the BASE_PYTHON_VERSION available inside this stage
--------------------
ERROR: failed to solve: failed to parse stage name "python:-slim-": invalid reference format

As you can see, it doesn't matter where I define the build args, seems they can't be used in a FROM statement either way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests