Btw, did you ever encounter that yarn install
needs phoenix
and phoenix_html
deps that come from mix? I don’t see how you dealt with it.
I modified my package.json
to grab phoenix
and phoenix_html
straight from npm as a regular package.
You can find them at:
And you can use them like normal in your JS, such as: import "phoenix";
. Assuming you’re using ES6 style JS.
Doh. I had no idea they are available in npm.
Thanks a lot!
No problem. It took a while to wire all of that together, but now that it works, it’s really nice. It’s a setup that will work in both dev and prod using the same docker-compose.yml
file because in prod I just wouldn’t use the docker-compose.override.yml
file, because in prod nginx would serve the compiled assets instead of running the webpack dev server.
That behavior is dictated by the build args that you can set with ENV variables.
I really wish mix deps.get
and mix deps.compile
work only with mix.lock
(see Mix install in umbrella projects without mix.exs?)
Then we’ll get huge boost on build time for unrelated changes. For example, if you change a mix file to add an option… boom! docker cannot use cache.
Also it’s very cumbersome as you need to add all mix files from all apps in umbrella project. You have 10 umlbreea apps? Then you need to have 10 COPY
command to copy all mix files into the right place.
If anyone is interested, here is my latest Docker setup. I hardcoded everything for development. For production I will probably do it differently and build a release. But for development it works just great.
docker/dev/Dockerfile
FROM node:12.4-alpine as webpack
RUN npm install -g yarn
WORKDIR /app/assets
COPY assets/package.json assets/*yarn* ./
RUN apk --update --upgrade add ca-certificates build-base bash \
&& update-ca-certificates --fresh \
&& rm -rf /var/cache/apk/* \
&& yarn install \
&& apk del build-base
COPY assets .
ENV NODE_ENV="development"
CMD ["tail", "-f", "/dev/null"]
###############################
FROM elixir:1.8-otp-22-alpine as app
WORKDIR /app
RUN apk --update --upgrade add ca-certificates inotify-tools postgresql-client bash \
&& update-ca-certificates --fresh \
&& rm -rf /var/cache/apk/*
COPY ./docker/dev/wait-for-postgres.sh /
COPY mix.* ./
ENV MIX_ENV="dev" \
MIX_HOME=/opt/mix \
HEX_HOME=/opt/hex
RUN mix local.hex --force \
&& mix local.rebar --force \
&& mix deps.get \
&& mix deps.compile
CMD ["tail", "-f", "/dev/null"]
docker-compose.yml
version: '3.7'
services:
postgres:
image: postgres:11-alpine
container_name: project_postgres
restart: always
ports:
- 15432:5432
volumes:
- ./docker/data/postgres:/var/lib/postgresql/data
webpack:
build:
context: .
dockerfile: ./docker/dev/Dockerfile
target: "webpack"
container_name: project_webpack
restart: unless-stopped
command: yarn run watch
volumes:
- .:/app
- static:/app/priv/static
app:
build:
context: .
dockerfile: ./docker/dev/Dockerfile
target: "app"
container_name: project_app
ports:
- 4000:4000
command: tail -f /dev/null
volumes:
- .:/app
- static:/app/priv/static
- deps:/app/deps
- build:/app/_build
depends_on:
- postgres
- webpack
volumes:
static: {}
deps: {}
build: {}
docker/dev/wait-for-postgres.sh
#!/bin/bash
# wait-for-postgres.sh
set -e
host="$1"
shift
cmd="$@"
until PGPASSWORD=$POSTGRES_PASSWORD psql -h "$host" -U "postgres" -c '\q'; do
>&2 echo "Postgres is unavailable - sleeping"
sleep 1
done
>&2 echo "Postgres is up - executing command"
exec $cmd
And Makefile
.PHONY: app server console sh clean
app:
docker-compose up --detach --build app
setup: app
docker-compose exec app /wait-for-postgres.sh postgres mix ecto.setup
server: setup
docker-compose exec app mix phx.server
console: setup
docker-compose exec app iex -S mix
sh: setup
docker-compose exec app bash
clean:
docker-compose down
Now I can just execute make console
or make server
and it will start all services and even wait for postgres to be healthy and execute migrations before starting the server on iex.
Thanks @cnck1387 for the helpful tips.
FWIW, I’ve captured a quick tutorial on minimal (Alpine) Multi-Stage Docker image builds with Elixir 1.9 and Phoenix in this Gist: https://gist.github.com/nicbet/102f16359828405ce34ca083976986e1
Hi @cnck1387,
I was wondering if you have these dockerfiles and compose files open sourced? I’ve read many blog posts with slightly different approaches and just not sure how to tie it all together for a basic generated phoenix umbrella app (with ecto). I’m trying to get a development environment (editing using vscode remote container plugin) and a mix release driven multi-stage build delivering the .tar.gz release ready for deployment in a container in the same project.