While a lot of our older software was written in Ruby and Ruby on Rails we’ve been expanding the past couple of years into Elixir and Phoenix (Elixir’s batteries-included web framework). Docker remains our preferred mechanism to deliver our software in a well-tested and repeatable format. I’d like to share with you a simple Dockerfile for Phoenix, specifically supporting Phoenix >= 1.4 which uses webpack instead of brunch.
We’re using a multi-stage to keep the image slim and nimble. In the first step we get a copy of the Elixir dependencies, mainly for the phoenix and phoenix_html Node modules that are co-located in the Elixir Hex packages. The second build file lets us build and emit the finalized assets with webpack. In the final step we’re back to an Elixir base image and we can copy everything over, merge the assets, and set the command for starting the server.
FROM elixir:1.7.3-alpine as asset-builder-mix-getter
ENV HOME=/opt/app
WORKDIR $HOME
RUN mix do local.hex --force, local.rebar --force
COPY config/ ./config/
COPY mix.exs mix.lock ./
RUN mix deps.get
############################################################
FROM node:8.11.4 as asset-builder
ENV HOME=/opt/app
WORKDIR $HOME
COPY --from=asset-builder-mix-getter $HOME/deps $HOME/deps
WORKDIR $HOME/assets
COPY assets/ ./
RUN yarn install
RUN ./node_modules/webpack/bin/webpack.js --mode="production"
############################################################
FROM elixir:1.7.3-alpine
ENV HOME=/opt/app
WORKDIR $HOME
RUN mix do local.hex --force, local.rebar --force
COPY config/ $HOME/config/
COPY mix.exs mix.lock $HOME/
COPY lib/ ./lib
COPY priv/ ./priv
ENV MIX_ENV=prod
RUN mix do deps.get --only $MIX_ENV, deps.compile, compile
COPY --from=asset-builder $HOME/priv/static/ $HOME/priv/static/
RUN mix phx.digest
CMD ["mix", "phx.server"]
This produces an image around 100MB. Compared to our Slim Dockerfiles for Rails that’s a space savings of 50%! We’ve seen some pure-Elixir applications even smaller when you use Distillery to create an optimized release, which we’d recommend for heavier production use as it gives you a lot more control.
I hope you enjoyed seeing an example of building a slim Docker image for Phoenix.