nicbet / docker-phoenix

A dockerized Phoenix development and runtime environment.
GNU General Public License v3.0
277 stars 57 forks source link

How to pass env vars like MIX_ENV=prod? #31

Closed hyperknot closed 2 years ago

hyperknot commented 2 years ago

Is there a way to pass env vars like MIX_ENV=prod?

What I did was to make a duplicate of run -> runprod and modify that file with -e MIX_ENV=prod. Then I made mixprod which calls runprod. The problem is this is super hard-coded for this specific case and so it's just a workaround.

Ideally we could pass parameters to docker-compose somehow.

nicbet commented 2 years ago

the run script uses the $@ argument collector to pass on all arguments given to ./run to the app's default entrypoint

docker-compose run --service-ports --rm app $@

an easier way to pass in ENV vars to the run script is using .env files - docker-compose picks up .env files in the root directory. However, that requires you to modify the docker-compose.yml file and specify which ENV vars the container should know about.

I ran into a very similar issue recently in another project I'm working on (needing to pass in arbitrary ENV vars to a docker-compose stack) and there was no happy path. It appears that setting runtime ENV vars for a container has great support for the docker run command but with docker-compose you need to work through the yml files ;-)

The way we solved this in the other project by the way was by

hyperknot commented 2 years ago

I believe they work the same way, with -e. It's just that I need to specify it before the argument, so the $@ doesn't work.

Here is my runprod file which works.

#!/usr/bin/env bash
docker-compose run --service-ports --rm \
  -e MIX_ENV=prod \
  -e SECRET_KEY_BASE=xxx \
  app $@
docker-compose run --service-ports --rm app chown -R $(id -u):$(id -g) .

My problem with the .env files is that I'm trying to switch from dev to prod quickly, so I cannot hard-code MIX_ENV into the .env file.

nicbet commented 2 years ago

I think the simplest way for your case would be to first add MIX_ENV to the yml spec:

---
version: "2"
services:
  app:
    image: nicbet/phoenix:1.6.6
    build: .
    ports:
      - "4000:4000"
    volumes:
      - ./src:/app
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_HOST=db
      - MIX_ENV
    depends_on:
      - db
  db:
    image: postgres:12
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres

then you can execute MIX_ENV=prod ./run <command> to set the MIX_ENV to prod. if you don't specify MIX_ENV, e.g., just running ./run, then MIX_ENV is not set in the container. You can test this out with ./run printenv and MIX_ENV=prod ./run printenv

hyperknot commented 2 years ago

That's great, probably all I need.