# syntax=docker/dockerfile:1.7-labs # ^ needed for --parents flag ARG ALPINE_VERSION ARG ELIXIR_DOCKER_IMAGE #### STEP 1 - Build our app FROM hexpm/elixir:${ELIXIR_DOCKER_IMAGE} as builder ARG FLAVOUR ARG FLAVOUR_PATH ARG FORKS_TO_COPY_PATH # necessary utils + dependencies for comeonin COPY --link deps-alpine.sh ./ COPY --link deps-alpine-build.sh ./ RUN chmod +x ./*.sh RUN sh deps-alpine-build.sh # RUN apk --update add tar curl git rust cargo npm yarn bash make gcc libc-dev openssl-dev ENV HOME=/opt/app/ TERM=xterm MIX_ENV=prod FLAVOUR_PATH=./ WORKDIR $HOME # Prepare elixir deps COPY --link mix.exs ./ COPY --link lib/mix ./lib/mix # sometimes mix tries to read the config RUN mkdir -p ./config COPY --link data/current_flavour/config/config_basics.exs ./config/config.exs RUN mix do local.hex --force, local.rebar --force # FIXME: copying mix.lock here means the optimisations of fetching hex and git deps seperately are useless, so commenting those for now COPY --link mix.lock ./ # # first get deps from hex.pm # COPY --link data/current_flavour/config/deps*hex ./config/ # COPY --parents --link flavours/*/config/deps*hex ./ # # RUN mix deps.get --only prod # RUN HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix deps.get --only prod # RUN ls -la config/* # # Compile initial hex deps, only if we're not using forks (warning: this makes the assumption that no Bonfire extensions are coming from Hex. otherwise this should be done only after copying config) # RUN if [ "$FORKS_TO_COPY_PATH" = "data/null" ] ; then MIX_ENV=prod mix deps.compile ; else echo "Skip" ; fi # # add flavour's git deps (typically Bonfire extensions) # COPY --link data/current_flavour/config/deps*git ./config/ # COPY --parents --link flavours/*/config/deps*git ./ # # fetch more deps/extensions # RUN mix deps.get --only prod # add main dep sources COPY --link data/current_flavour/config/deps.flavour.* ./config/ RUN ls -la config/* RUN mix deps.get --only prod # RUN HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix deps.get --only prod # # ^ useful in case of spotty connectivity ## add extra deps # from other flavours COPY --parents --link flavours/*/config/* ./ # specified by the core app RUN cp -rfL deps/bonfire/deps.* ./config/ RUN ls -la config/* && ls flavours/*/config/* # fetch extras (we need extensions for the non-configurable paths in config/deps_hooks.js) # RUN mix deps.get --only prod # RUN HEX_HTTP_CONCURRENCY=1 HEX_HTTP_TIMEOUT=120 mix deps.get --only prod # we need config before compiling Bonfire extensions COPY --link data/current_flavour/config/ ./config/ # Optionally include local forks RUN if [ "$FORKS_TO_COPY_PATH" = "data/null" ] ; then rm ./config/deps*path && rm ./flavours/*/config/deps*path ; else echo "Include locally forked extensions." ; fi COPY --link ${FORKS_TO_COPY_PATH} ./${FORKS_TO_COPY_PATH} # Update Bonfire extensions to latest git version (mostly useful in CI, and temporary: eventually we want to rely on version numbers and lockfile) # RUN mix bonfire.deps.update # Fetch git deps - should be after forks are copied (and updates are fetched, if doing so) in case a forked/updated extension specified any different deps) RUN mix deps.get --only prod RUN ls deps/ # Include translations COPY --link priv/localisation/ priv/localisation/ # RUN ls -la priv/localisation/ # copy these before compiling so we don't override things like flavour_assets/components.css (generated by Surface compiler) COPY --link data/current_flavour/config/flavour_assets data/current_flavour/config/flavour_assets RUN ls -la data/current_flavour/config/flavour_assets && ls -la data/current_flavour/config/flavour_assets/hooks # Compile remaining deps # RUN MIX_ENV=prod mix deps.compile # disabled because doesn't properly compile Surface hooks/CSS # JS package manager # RUN npm install -g pnpm # install JS deps COPY --link js-deps-get.sh ./ # COPY --link assets/package.json ./assets/ # COPY --link assets/pnpm-lock.yaml ./assets/ # COPY --link assets/yarn.lock ./assets/ RUN chmod +x config/*.sh RUN chmod +x ./*.sh RUN sh config/deps.js.sh # FIXME: should we be installing dev deps here? # Update mime types RUN MIX_ENV=prod mix deps.clean --build mime # bonfire-app code & assets COPY --link lib lib # COPY --link assets assets # RUN ls -la assets/static # workaround for compilation errors RUN MIX_ENV=prod mix deps.clean needle_ulid jason poison --build # compile protocols (attempted fix for 'could not load module Poison.Encoder due to reason :unavailable') # RUN MIX_ENV=prod mix compile.protocols # compile app (needs to be before building assets so it includes Surface hooks & component CSS) RUN MIX_ENV=prod mix compile # Include any migrations provided by flavour (maybe not needed?) # COPY --link data/current_flavour/repo priv/repo RUN mkdir -p priv/repo/migrations # Copy DB/repo migrations from installed extensions RUN mix bonfire.extension.copy_migrations --force --to priv/repo/migrations # docs/guides COPY --link LICENSE ./ COPY --link ./*.md ./ COPY --link docs/*.md ./docs/ # include an archive of the source code RUN mkdir -p apps/ RUN mkdir -p extensions/ RUN mkdir -p forks/ RUN mkdir -p priv/static/ # COPY --link priv/extras/ priv/extras/ # prepare static assets COPY --link data/current_flavour/config/deps_hooks.js data/current_flavour/config/deps_hooks.js RUN cd ./deps/bonfire_ui_common/assets && yarn && yarn build RUN MIX_ENV=prod CI=1 mix phx.digest RUN ls -la priv/static RUN ls -la priv/static/assets RUN tar --exclude=*.env --exclude=.git --exclude=node_modules --exclude=priv/static/data --exclude=*/*/assets/static/data -czvf priv/static/source.tar.gz lib deps apps extensions forks config docs priv/repo priv/static mix.exs mix.lock LICENSE || echo "Could not prepare code archive" # build final OTP release RUN MIX_ENV=prod CI=1 mix release ##### STEP 2 - Prepare the server image #### # From this line onwards, we're in a new image, which will be the image used in production FROM alpine:${ALPINE_VERSION} ENV APP_REVISION=${APP_VSN}-${APP_BUILD} WORKDIR /opt/app # Essentials COPY --link deps-alpine.sh ./ RUN chmod +x ./deps-alpine.sh RUN sh deps-alpine.sh # RUN apk add --update --no-cache \ # mailcap \ # ca-certificates \ # openssh-client \ # openssl-dev \ # # ^ for HTTPS, etc # git \ # # build-base \ # # ^ required by tree_magic # tzdata \ # gettext \ # # ^ localisation # imagemagick \ # vips-tools \ # poppler-utils \ # # ^ image resizing # bash \ # curl # #^ misc # copy app build COPY --from=builder /opt/app/_build/prod/rel/bonfire /opt/app COPY --from=builder /opt/app/flavours/ /opt/app/flavours/ RUN ls /opt/app/lib/ # start CMD ["./bin/bonfire", "start"]