Pass ENV variables specified in shell from docker-compose to Dockerfile

Viewed 99

I would like to set the DEPLOY_ENV environment variable when I build my Docker image, but the value doesn't seem to be making it to the Dockerfile. Here's my build command:

docker-compose.yml

version: '3'
services:
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    environment:
      - DEPLOY_ENV=${DEPLOY_ENV:-development}
    ports:
      - "3000:3000"
    volumes:
      - ".:/app"

When I run DEPLOY_ENV=staging docker-compose config, I can see that it replaces the DEPLOY_ENV variable as expected:

services:
  web:
    build:
      context: /home/user/app
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b
      '0.0.0.0'"
    environment:
      DEPLOY_ENV: staging
    ports:
    - published: 3000
      target: 3000
    volumes:
    - /home/user/app:/app:rw
version: '3'

However, I can't figure out how to populate the value in my Dockerfile. Here's a Dockerfile I'm using to test:

FROM ruby:2.7.2

SHELL ["/bin/bash", "-c"]

ENV RAILS_ENV=${DEPLOY_ENV}
ENV NODE_ENV=${DEPLOY_ENV}
ENV APP_HOME=/app

LABEL app=app
LABEL environment=${RAILS_ENV}

RUN echo ${DEPLOY_ENV}

When I run docker-compose build, it doesn't dipslay the value of DEPLOY_ENV:

Building web
[+] Building 1.4s (6/6) FINISHED                                                                                                                                                            
 => [internal] load build definition from Dockerfile                                                                                                                                   0.1s
 => => transferring dockerfile: 1.55kB                                                                                                                                                 0.0s
 => [internal] load .dockerignore                                                                                                                                                      0.1s
 => => transferring context: 35B                                                                                                                                                       0.0s
 => [internal] load metadata for docker.io/library/ruby:2.7.2                                                                                                                          1.0s
 => [1/2] FROM docker.io/library/ruby:2.7.2@sha256:1dd0106849233fcd913b7c4608078fa1a5sd5e3ce1af2a55e4d726b0d8868e2f                                                                    0.0s
 => CACHED [2/2] RUN echo ${DEPLOY_ENV}                                                                                                                                                0.0s
 => exporting to image                                                                                                                                                                 0.1s
 => => exporting layers                                                                                                                                                                0.0s
 => => writing image sha256:27e159270471d3078fff8eb4eads7e4e586b345bfa13d3bdb3ec317266678549                                                                                           0.0s
 => => naming to docker.io/library/app_web

I plan to set secret values when building my image and want to avoid hardcoding the values or use build args since they can be exposed.

What am I missing?

1 Answers

You could utilize the args primitive in docker compose, which passes build variables in your Dockerfile

args:
  DEPLOY_ENV_ARG: ${DEPLOY_ENV:-development}
environment:
  - DEPLOY_ENV=${DEPLOY_ENV:-development}

And in your Dockerfile

ARG DEPLOY_ENV_ARG
ENV RAILS_ENV=${DEPLOY_ENV_ARG}
Related