balena-supervisor/Dockerfile.template
Christina Ying Wang 3d881347e7 Pin iptables to 1.8.9 (legacy)
With Alpine 3.19, iptables gets bumped to 1.8.10 which uses nftables.
The host OS still uses iptables 1.8.7 (legacy), and we should
use legacy as well until the OS uses nftables.

See: https://balena.zulipchat.com/#narrow/stream/345889-balena-io.2Fos/topic/iptables.20host.20vs.2E.20nftables.20Supervisor
Change-type: patch
Signed-off-by: Christina Ying Wang <christina@balena.io>
2024-03-18 14:15:24 -07:00

218 lines
6.3 KiB
Docker

ARG ARCH=%%BALENA_ARCH%%
ARG FATRW_VERSION=0.2.21
ARG NODE="nodejs~=20"
ARG NPM="npm~=10"
ARG ALPINE_VERSION="3.19"
###################################################
# Build the supervisor dependencies
###################################################
FROM alpine:${ALPINE_VERSION} as build-base
ARG ARCH
ARG NODE
ARG NPM
ARG FATRW_VERSION
ARG FATRW_RELEASES="https://github.com/balena-os/fatrw/releases/download/v${FATRW_VERSION}"
WORKDIR /usr/src/app
RUN apk add --update --no-cache \
build-base \
python3 \
curl \
$NODE \
$NPM \
libuv \
sqlite-dev \
cargo \
rust
COPY package*.json ./
COPY ./build-utils/rust-arch.sh /
RUN strip "$(which node)"
# Install fatrw
RUN FATRW_ARCHIVE="fatrw-$(/rust-arch.sh).tar.gz" && \
FATRW_LOCATION="${FATRW_RELEASES}/${FATRW_ARCHIVE}" && \
curl -SLO "${FATRW_LOCATION}" && \
ls -la "${FATRW_ARCHIVE}" && \
tar -xzf "${FATRW_ARCHIVE}" -C /usr/local/bin && \
rm -f "${FATRW_ARCHIVE}"
# Just install dev dependencies first
RUN npm ci --build-from-source=sqlite3 --sqlite=/usr/lib
###################################################################
# Journal access.
# The supervisor is built on an alpine image but still needs
# to use journalctl (from systemd) which cannot be built for
# musl. We hack around this by copying the binary and its library
# dependencies to the final image
###################################################################
FROM debian:bullseye-slim as journal
RUN apt-get update && apt-get install -y --no-install-recommends systemd
COPY ./build-utils/setup-journal.sh /
RUN /setup-journal.sh
###################################################
# Extra dependencies. This uses alpine 3.11 as the
# procmail package was removed on 3.12
###################################################
FROM alpine:3.11 as extra
RUN apk add --update --no-cache procmail
###################################################
# Image with the final production dependencies.
# This image will also be be used for testing
###################################################
FROM alpine:${ALPINE_VERSION} as runtime-base
ARG NODE
WORKDIR /usr/src/app
# Also copy the fatrw binary
COPY --from=build-base /usr/local/bin/fatrw /usr/local/bin/fatrw
# Similarly, from the procmail package we just need the lockfile binary
COPY --from=extra /usr/bin/lockfile /usr/bin/lockfile
# Copy journalctl and library dependecies to the final image
COPY --from=journal /sysroot /
# Copy mount script for mounting host partitions into container
COPY mount-partitions.sh .
# Runtime dependencies
RUN apk add --update --no-cache \
$NODE \
rsync \
dbus \
dmidecode \
sqlite-libs \
lsblk
# Iptables should be pinned to 1.8.9 (legacy) as balenaOS still uses iptables-legacy
RUN apk add --update --no-cache \
--repository=http://dl-cdn.alpinelinux.org/alpine/v3.18/main \
iptables~=1.8.9 \
ip6tables~=1.8.9
ARG ARCH
ARG VERSION=master
ENV LED_FILE=/dev/null \
SUPERVISOR_IMAGE=balena/$ARCH-supervisor \
VERSION=$VERSION
###############################################################
# Use the base image to run integration tests and for livepush
###############################################################
FROM runtime-base as test
ARG NPM
ARG ARCH
# We want to use as close to the final image when running tests
# but we need npm so we install it here again
RUN apk add --update --no-cache $NPM
WORKDIR /usr/src/app
# Copy build dependencies
COPY --from=build-base /usr/src/app/package.json ./
COPY --from=build-base /usr/src/app/node_modules ./node_modules
# Run livepush here
#dev-copy=entry.sh .
#dev-cmd-live=LIVEPUSH=1 ./entry.sh
# Copy build files
COPY entry.sh .
COPY build-utils ./build-utils
COPY webpack.config.js tsconfig.json tsconfig.release.json tsconfig.js.json .mochapodrc.yml ./
COPY typings ./typings
COPY src ./src
COPY test ./test
# Fail-safe, check the architecture used by apk against the expected architecture
# from the device type
RUN APK_ARCH=$(./build-utils/apk-print-arch.sh); [ "$APK_ARCH" = "$ARCH" ] || (echo "Image architecture ($APK_ARCH) does not match the target architecture ($ARCH)" && exit 1)
# Run type checking and unit tests here
# to prevent setting up a test environment that will
# most likely fail.
RUN npm run test
# When running tests from a container built from this stage,
# skip the mocha-pod setup
ENV MOCHAPOD_SKIP_SETUP=1
# This command will be used by default when running integration tests
# from this stage
CMD npm run test:integration
###################################################
# Build the production package
###################################################
FROM build-base as build-prod
WORKDIR /usr/src/app
# Copy build files
COPY build-utils ./build-utils
COPY webpack.config.js tsconfig.json tsconfig.release.json ./
COPY src ./src
COPY typings ./typings
# Compile the sources using the dev
# dependencies
RUN npm run build
# Run the production install here, to avoid the npm dependency on
# the later stage
RUN npm ci \
--omit=dev \
--omit=optional \
--unsafe-perm \
--build-from-source=sqlite3 \
--sqlite=/usr/lib \
&& npm cache clean --force \
# For some reason this doesn't get cleared with the other
# cache
&& rm -rf node_modules/.cache \
# Remove various uneeded filetypes in order to reduce space
# We also remove the spurious node.dtps, see https://github.com/mapbox/node-sqlite3/issues/861
&& find . -path '*/coverage/*' -o -path '*/test/*' -o -path '*/.nyc_output/*' \
-o -name '*.tar.*' -o -name '*.in' -o -name '*.cc' \
-o -name '*.c' -o -name "*.ts" -o -name '*.eslintrc' \
-o -name '*.h' -o -name '*.html' -o -name '*.markdown' \
-o -name '*.md' -o -name '*.patch' -o -name '*.png' \
-o -name '*.yml' \
-delete \
&& find . -type f -path '*/node_modules/sqlite3/deps*' -delete \
&& find . -type f -path '*/node_modules/knex/build*' -delete \
&& rm -rf node_modules/sqlite3/node.dtps
###################################################
# Build the production image
###################################################
FROM runtime-base
WORKDIR /usr/src/app
COPY --from=build-prod /usr/src/app/dist ./dist
COPY --from=build-prod /usr/src/app/package.json ./
COPY --from=build-prod /usr/src/app/node_modules ./node_modules
COPY entry.sh .
HEALTHCHECK --interval=5m --start-period=1m --timeout=30s --retries=3 \
CMD wget http://127.0.0.1:${LISTEN_PORT:-48484}/v1/healthy -O - -q
CMD ["/usr/src/app/entry.sh"]