mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
145 lines
4.1 KiB
Docker
145 lines
4.1 KiB
Docker
ARG ALPINE_VERSION=3.18.4
|
|
ARG OTP_VERSION=26.1.1
|
|
ARG ELIXIR_VERSION=1.15.6
|
|
|
|
ARG BUILDER_IMAGE="firezone/elixir:${ELIXIR_VERSION}-otp-${OTP_VERSION}"
|
|
ARG RUNNER_IMAGE="alpine:${ALPINE_VERSION}"
|
|
|
|
FROM ${BUILDER_IMAGE} as compiler
|
|
|
|
WORKDIR /app
|
|
|
|
# Install build deps
|
|
RUN apk add --update --no-cache \
|
|
make \
|
|
git \
|
|
nodejs \
|
|
npm \
|
|
build-base
|
|
|
|
# Add pnpm
|
|
RUN npm i -g pnpm
|
|
|
|
# Copy only the files needed to fetch the dependencies,
|
|
# to leverage Docker layer cache for them
|
|
RUN echo "0.0.0" > VERSION
|
|
COPY mix.exs mix.lock ./
|
|
COPY apps/domain/mix.exs ./apps/domain/mix.exs
|
|
COPY apps/web/mix.exs ./apps/web/mix.exs
|
|
COPY apps/api/mix.exs ./apps/api/mix.exs
|
|
COPY config config
|
|
|
|
# Fetch and compile the dependencies
|
|
ARG MIX_ENV="prod"
|
|
RUN mix deps.get --only ${MIX_ENV}
|
|
RUN mix deps.compile --skip-umbrella-children
|
|
|
|
# Copy the files needed to fetch asset deps
|
|
COPY apps/web/assets/package.json ./apps/web/assets/
|
|
COPY apps/web/assets/pnpm-lock.yaml ./apps/web/assets/
|
|
|
|
# Install npm deps and assets pipeline
|
|
RUN cd apps/web \
|
|
&& mix assets.setup
|
|
|
|
# Copy the files needed to compile application assets
|
|
COPY apps/web/assets ./apps/web/assets
|
|
COPY apps/web/priv ./apps/web/priv
|
|
|
|
# Install pipeline and compile assets for Web app
|
|
RUN cd apps/web \
|
|
&& mix assets.deploy
|
|
|
|
# Copy the rest of the application files and compile them
|
|
COPY VERSION ./
|
|
COPY priv priv
|
|
COPY apps apps
|
|
RUN mix compile
|
|
|
|
FROM ${BUILDER_IMAGE} as builder
|
|
|
|
# Install build deps
|
|
RUN apk add --update --no-cache \
|
|
git
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy the compiled dependencies from the previous step
|
|
# leveraging the possible layer cache
|
|
COPY --from=compiler /app /app
|
|
|
|
COPY rel rel
|
|
|
|
ARG APPLICATION_NAME
|
|
ARG MIX_ENV="prod"
|
|
RUN mix release ${APPLICATION_NAME}
|
|
|
|
# start a new build stage so that the final image will only contain
|
|
# the compiled release and other runtime necessities
|
|
|
|
FROM ${RUNNER_IMAGE} AS runtime
|
|
|
|
ENV LANG=C.UTF-8 \
|
|
HOME=/app/ \
|
|
TERM=xterm
|
|
|
|
ARG RUNNER_IMAGE
|
|
RUN set -xe \
|
|
&& ALPINE_MINOR_VERSION=$(echo ${RUNNER_IMAGE} | cut -d ':' -f 2 | cut -d '.' -f 1,2) \
|
|
&& echo "@main http://dl-cdn.alpinelinux.org/alpine/v${ALPINE_MINOR_VERSION}/main" >> /etc/apk/repositories \
|
|
&& echo "@community http://dl-cdn.alpinelinux.org/alpine/v${ALPINE_MINOR_VERSION}/community" >> /etc/apk/repositories \
|
|
&& echo "@edge http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories
|
|
|
|
RUN set -xe \
|
|
# Upgrade Alpine and base packages
|
|
&& apk --no-cache --update-cache --available upgrade \
|
|
# Install bash, Erlang/OTP and Elixir deps
|
|
&& apk add --no-cache --update-cache \
|
|
bash \
|
|
libstdc++ \
|
|
ca-certificates \
|
|
ncurses \
|
|
openssl \
|
|
pcre \
|
|
unixodbc \
|
|
zlib \
|
|
tini \
|
|
# Update ca certificates
|
|
&& update-ca-certificates --fresh
|
|
|
|
# Create default user and home directory, set owner to default
|
|
RUN set -xe \
|
|
mkdir -p /app && \
|
|
adduser -s /bin/sh -u 1001 -G root -h /app -S -D default && \
|
|
chown -R 1001:0 /app
|
|
|
|
WORKDIR /app
|
|
|
|
ARG APPLICATION_NAME
|
|
ENV APPLICATION_NAME=$APPLICATION_NAME
|
|
|
|
# Only copy the final release from the build stage
|
|
ARG MIX_ENV="prod"
|
|
COPY --from=builder /app/_build/${MIX_ENV}/rel/${APPLICATION_NAME} ./
|
|
|
|
# Change user to "default" to limit runtime privileges
|
|
USER default
|
|
|
|
# This is critical when you run this container in containers where
|
|
# running process would get a PID 1.
|
|
#
|
|
# BEAM is usually not started by itself but via some shell script (eg. the one generated by
|
|
# Elixir 1.9 releases or Distillery) and this script is not designed to become an init script
|
|
# for a Docker container and it DOES NOT reap zombie processes.
|
|
#
|
|
# So whenever a child process runs and terminates inside the same container it would result in memory and
|
|
# PID leak to a point where host VM would get unresponsive.
|
|
#
|
|
# A good example why you would start a process within container is the `ping` command for liveness probes.
|
|
# It starts a VM to issue an RPC command to a live node and then terminates, but would never be reaped.
|
|
#
|
|
# Tini would become an entrypoin script and would take care of zombie reaping no matter how you start the VM.
|
|
ENTRYPOINT ["/sbin/tini", "--"]
|
|
|
|
CMD bin/server
|