Multi-stage Build With Typescript, SPI and CAN

I’m trying to build our Node server which will use CAN on a RPi 4 via MCP2515 on SPI0 along with a MCP3008 ADC via SPI1.

My server is built using Typescript and I am trying to do a multi-stage build of the server build but I’m having a lot of trouble with missing dependancies when the RUN npm install --production command is executed. It keeps getting build errors when trying to build the SPI, first is was missing python, then make and now it’s missing g++. I have the feeling I’m going about this the wrong way.

Thoughts,

My docker-compose.yml is below, the can-init service just brings up the CAN interface.

version: "2.0"

services:
  can-init:
    build: "./can-init" # use this directory as the build context for the service
    network_mode: host # expose host network adaptors to the container directly
    cap_add:
      - NET_ADMIN # allow container to change network settings
    restart: no
    environment:
      CAN0_BITRATE: 250000

  server:
    build: "./server" # use this directory as the build context for the service
    network_mode: host # expose host network adaptors to the container directly

My Dockerfile for the server is below:

# Build stage
FROM balenalib/raspberrypi4-64-node:12-build as builder

WORKDIR /app

RUN install_packages iproute2 can-utils

COPY . .
RUN npm install
RUN npm run clean
RUN npm run build-server

# Run stage
FROM balenalib/raspberrypi4-64-node:12-run

RUN install_packages iproute2 can-utils python make

WORKDIR /app
COPY --from=builder /app/lib ./lib
COPY package*.json ./
RUN npm install --production

CMD ["node", "-r", "dotenv/config", "./lib/index.js"]

@westcoastdaz nothing about your docker-compose or Dockerfile jump out to me as incorrect. However, I’m wondering if you’ve tried to get everything installed and functional in a single container for now, just for troubleshooting purposes? It sometimes makes it easier to start that way, and then move on to improving the build process after you know the core application is functioning as expected.

If you’ve already tried that, I’d be curious to see the difference between the working and non-working versions if you’re willing to share here. If not, feel free to email them to me; I’ll be sharing contact info with you shortly. :+1:

@the-real-kenna

Thanks for getting back to me. I did revert back to using a single stage build and was able to get that working correctly. It seemed the like the balenalib/raspberrypi4-64-node:12-run image just was to stripped down. I’m wondering if there is perhaps a better image to use.

Thoughts,

Hi @westcoastdaz

I’m glad to hear that you got it working as a single stage build.

Unsurprisingly, you are correct. That is, run variants are slim. For example, as you noted, run variants do not include gcc. In case you haven’t seen it, run vs. build has a short description of run vs build variants in the context of a multistage build. Which includes the statement, “the build variant is a heavier image that includes many of the tools required for building from source such as build-essential, gcc, etc.” BTW, this page also has a simple multistage build example with npm install. It’s simpler than what you are trying to do, but you might find it helpful.