Docker Elixir Build Image Base
This builds a Docker image that can be used as a base to build Elixir (and Erlang) projects.
Contents
As of elixir-build:2.2.0
:
- Erlang 21.0
- Elixir 1.6.6
- Node 8.9.3 (npm 5.5.1)
make
,git
openssl
hex
and rebar
are also installed.
A multi-stage minimal image build
With the new Docker multi-stage builds facility (17.05+) it is now simple to write a single Dockerfile
that can build an Elixir project, and create a minimal run-time image using simply docker build
.
Assuming distillery is set up, and its rel/config.exs
is configured for a stand-alone ERTS release as so:
environment :docker do
set dev_mode: false
set include_erts: true
set include_src: false
set cookie: :crypto.hash(:sha256, :crypto.rand_bytes(25)) |> Base.encode16 |> String.to_atom
end
Then a Dockerfile
to build a minimal run-time image for a Phoenix project may look like:
FROM nexus.in.ft.com:5000/membership/elixir-build:2.2.0 AS build
WORKDIR /build
COPY mix.exs .
COPY mix.lock .
COPY deps deps
ARG MIX_ENV=docker
ARG APP_VERSION=0.0.0
ENV MIX_ENV ${MIX_ENV}
ENV APP_VERSION ${APP_VERSION}
RUN mix deps.get
COPY lib lib
COPY test test
COPY config config
COPY rel rel
# Uncomment line below if you have assets in the priv dir
# COPY priv priv
# Build Phoenix assets
COPY assets assets
RUN cd assets && npm install && ./node_modules/.bin/brunch build --production
RUN mix phx.digest
RUN mix release --env=${MIX_ENV}
### Minimal run-time image
FROM alpine:latest
RUN apk --no-cache update && apk --no-cache upgrade && apk --no-cache add ncurses-libs openssl bash ca-certificates
RUN adduser -D app
ARG MIX_ENV=docker
ARG APP_VERSION=0.0.0
ENV MIX_ENV ${MIX_ENV}
ENV APP_VERSION ${APP_VERSION}
WORKDIR /opt/app
# Copy release from build stage
COPY --from=build /build/_build/${MIX_ENV}/rel/* ./
USER app
# Mutable Runtime Environment
RUN mkdir /tmp/app
ENV RELEASE_MUTABLE_DIR /tmp/app
ENV START_ERL_DATA /tmp/app/start_erl.data
# Start command
# NB 'myapp' should be replaced by your application name, as per mix.exs
CMD ["/opt/app/bin/myapp", "foreground"]
This uses distillery
to build a the stand-alone release in one stage, and then copies the release artefacts from the first stage to a second stage, starting afresh from the minimal Alpine base image. Adds additional package openssl
to libcrypto.so
is available at runtime, YMMV.
NB the APP_VERSION
environment var is used in the mix.exs
above to set the version, e.g.:
@version System.get_env("APP_VERSION") || "0.0.0"
def project do
[app: :myapp,
version: @version,
...
so passing it as a --build-arg
allows the release version to be set, making the whole build image command for a project simply:
docker build --build-arg APP_VERSION=1.1.2 .