#docker-compose dev flow for gen tasks and migrations

1 messages · Page 1 of 1 (latest)

magic bane
#

Hey there!

I'm working on putting together my dev flow for my elixir application and I think I'm really close to something I'm happy with but I have a lingering issue with how to run various gen tasks.

For example, I want to generate a new ecto migration for my application so I run docker-compose exec api mix ecto.gen.migration test_migration and it creates the migration file. Great! Because, I have my volume defined in my docker-compose.yml, I see the migration file on my host machine.

But when I go to edit the migration file, I get a permission denied error because the owner was set to root by docker/docker-compose. So that's a problem...

Here's my docker file and my docker-compose.yml:

FROM elixir:1.14

EXPOSE 4000

RUN apt-get update && \
    apt-get install -y postgresql-client && \
    apt-get install -y inotify-tools

WORKDIR /app

RUN mix local.hex --force && mix local.rebar --force 
version: '3.5'
services:
    api:
        build:
            context: .
            dockerfile: ./api/Dockerfile
        environment:
            PGUSER: postgres
            PGPASSWORD: postgres
            PGDATABASE: sbt_dev
            PGHOST: db
            PGPORT: 5432
        ports:
            - "4000:4000"
        restart: unless-stopped
        depends_on:
            - db
        volumes:
            - ./api/config:/app/config
            - ./api/lib:/app/lib
            - ./api/priv:/app/priv
            - ./api/test:/app/test
            - ./api/dev.sh:/app/dev.sh
            - ./api/mix.exs:/app/mix.exs
            - ./api/mix.lock:/app/mix.lock
            - ./api/.formatter.exs:/app/.formatter.exs
        command:
            - "./dev.sh"
    db:
        image: postgres:13.7
        environment:
            POSTGRES_USER: postgres
            POSTGRES_PASSWORD: postgres
        restart: unless-stopped

Anyone have any good ideas? Or alternate workflows? Ideally, I'd love to be able to use the gen mix tasks without having to have elixir installed on the host machine.

dense ridge
#

You could set up the docker images to run their commands with a different uid/gid (I think it's user: "<uid:<gid>" eg user: 1001:1001 in the compose file)

wise stirrup
#

Any reason you want the elixir code in docker rather than just having Postgres in docker with a mapped port?

magic bane
magic bane
wise stirrup
#

Using a tool like asdf is a good option too, it allows for very simple installation of multiple versions of multiple languages, and different projects can specify what they want. Working inside a container can be pretty painful

magic bane
#

Alright, I got it working! Here's what my dockerfile looks like now:

#

Dockerfile:

FROM elixir:1.14

ARG USER_ID
ARG GROUP_ID

EXPOSE 4000

RUN apt-get update && \
    apt-get install -y postgresql-client && \
    apt-get install -y inotify-tools

# Add an api_user so files created are not owned by root
RUN groupadd -g ${GROUP_ID} api_user
RUN useradd -l -m -u ${USER_ID} -g api_user -s /bin/bash api_user && su api_user -c 'mkdir -p /home/api_user/app'
USER api_user

WORKDIR /home/api_user/app

RUN mix local.hex --force && mix local.rebar --force
#

and i've modified the docker-compose to pass in USER_ID, GROUP_ID as build args that read from the environment

#

so for example, I can build the container like:
USER_ID=$(id -u ${USER}) GROUP_ID=$(id -g ${USER}) docker-compose build api

wise stirrup