Search code examples
node.jsdockergoogle-cloud-platformdevopssapper

Error: Cannot find module '/app/__sapper__/build' on Cloud Build


I'm trying to setup an automated Cloud Build for a sapper project that gets deployed to Cloud Run. However I'm getting an error on the deploy. This is my first attempt at CI work flow so I'm sure there are multiple things I'm doing wrong.

cloudbuild.yaml

steps:
  - name: "gcr.io/cloud-builders/gcloud"
    args:
      - kms
      - decrypt
      - --ciphertext-file=.env.enc
      - --plaintext-file=.env
      - --location=global
      - --keyring=jointcreative
      - --key=cloudbuild-env

  - name: "gcr.io/cloud-builders/docker"
    args: ["build", "-t", "gcr.io/$PROJECT_ID/$PROJECT_ID", "."]

  - name: "gcr.io/cloud-builders/docker"
    args: ["push", "gcr.io/$PROJECT_ID/$PROJECT_ID"]

  - name: "gcr.io/cloud-builders/npm"
    args: ["ci", "--production"]

  - name: 'gcr.io/cloud-builders/gcloud'
    args:
    - 'run'
    - 'deploy'
    - 'jointcreative'
    - '--image'
    - 'gcr.io/$PROJECT_ID/$PROJECT_ID'
    - '--region'
    - 'us-central1'
    - '--platform'
    - 'managed'

  - name: "gcr.io/$PROJECT_ID/firebase"
    args: ['deploy']

Dockerfile

FROM mhart/alpine-node:12


WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --production

FROM mhart/alpine-node:slim-12

WORKDIR /app
COPY --from=0 /app .
COPY . .

ENV PORT 8080
ENV HOST 0.0.0.0

EXPOSE 8080
CMD ["node", "__sapper__/build"]

Error logs enter image description here


Solution

  • The reason you get this error is because you don't build the Sapper application with npm run build.

    I published a repository with Sapper deployed to Cloud Run a few minutes ago on Github at https://github.com/mikenikles/sapper-on-cloud-run.

    The Dockerfile I use is based on 3 stages to minimize the final image size.

    # This stage builds the sapper application.
    FROM mhart/alpine-node:12 AS build-app
    WORKDIR /app
    COPY . .
    RUN npm install --no-audit --unsafe-perm
    RUN npm run build
    
    # This stage installs the runtime dependencies.
    FROM mhart/alpine-node:12 AS build-runtime
    WORKDIR /app
    COPY package.json package-lock.json ./
    RUN npm ci --production --unsafe-perm
    
    # This stage only needs the compiled Sapper application
    # and the runtime dependencies.
    FROM mhart/alpine-node:slim-12
    WORKDIR /app
    COPY --from=build-app /app/__sapper__ ./__sapper__
    COPY --from=build-app /app/static ./static
    COPY --from=build-runtime /app/node_modules ./node_modules
    
    EXPOSE 3000
    CMD ["node", "__sapper__/build"]
    

    I also recommend the following .dockerignore file to copy only what is necessary for Sapper to run:

    /*
    !/package.json
    !/package-lock.json
    !/rollup.config.js
    !/src
    !/static
    

    In your cloudbuild.yaml, you may want to consider adding the following to the Cloud Run deploy script if you plan on exposing the service publicly:

      - 'managed'
      - '--allow-unauthenticated'