Failed docker deployment: Cannot find module '/app/heroku'

24 Views Asked by At

I have a Node app in Docker I'm trying to deploy to Heroku with this deploy github action: https://github.com/AkhileshNS/heroku-deploy/tree/master

My app is already created in Heroku, and its using the default node buildpack. By all accounts, the deployment appears to succeed on the GHA side.

Here is my Dockerfile:

FROM node:20 AS base 
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["node", "./src/index.ts"]

Here are my package.json:

{
  "name": "goal-service",
  "version": "1.0.0",
  "description": "Service that powers the Goal API",
  "main": "index.js",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/onarollonaroll/goal-service.git"
  },
  "engines": {
    "node": "20.x",
    "npm": "10.x"
  },
  "author": "Onaroll",
  "license": "ISC",
  "scripts": {
    "compile": "tsc",
    "dev": "ts-node-dev --respawn ./src/index.ts",
    "test": "jest",
    "format": "npx prettier --write .",
    "start": "node ./src/index.ts"
  },
  "dependencies": {
    "@graphql-tools/schema": "^10.0.3",
    "@parcel/watcher": "^2.4.0",
    "graphql": "^16.8.1",
    "graphql-tag": "^2.12.6",
    "graphql-yoga": "^5.2.0",
    "heroku": "^8.11.0"
  },
  "devDependencies": {
    "@types/jest": "^29.0.3",
    "@types/node": "^20.0.0",
    "husky": "^9.0.11",
    "jest": "^29.0.3",
    "nodemon": "^3.0.0",
    "prettier": "^3.2.5",
    "pretty-quick": "^4.0.0",
    "ts-jest": "^29.0.2",
    "ts-node": "^10.9.1",
    "ts-node-dev": "^2.0.0",
    "typescript": "^5.4.3"
  },
  "jest": {
    "preset": "ts-jest",
    "testEnvironment": "node",
    "roots": [
      "test"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "pretty-quick --staged"
    }
  }
}

Here is my folder structure (only showing relevant files):

├── README.md
├── src
│   ├── index.ts
├── package.json
├── package-lock.json
├── Dockerfile
├── docker-compose.yml

Here is my index.ts (if this needed):

import { readFileSync } from 'fs'
import path from 'path'
import { gql } from 'graphql-tag'
import { createYoga } from 'graphql-yoga'
import { createServer } from 'http'
import { makeExecutableSchema } from '@graphql-tools/schema'
import { resolvers } from './resolvers'

const typeDefs = gql(
  readFileSync(path.resolve(__dirname, './schema.graphql'), {
    encoding: 'utf-8',
  })
)

function startYogaServer() {
  const schema = makeExecutableSchema({ typeDefs, resolvers })
  const yoga = createYoga({ schema })
  const server = createServer(yoga)
  server.listen(4000, () => {
    console.info('Server is running on http://localhost:4000/graphql')
  })
}

startYogaServer()

If I try to open the app via Heroku, I get a standard "Application Error" that tells me to check the logs.

In the logs I see this error:

node:internal/modules/cjs/loader:1147
  throw err;
  ^

Error: Cannot find module '/app/heroku'
    at Module._resolveFilename (node:internal/modules/cjs/loader:1144:15)
    at Module._load (node:internal/modules/cjs/loader:985:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
    at node:internal/main/run_main_module:28:49 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

Node.js v20.11.1

I didn't think my app needed to install Heroku, but I tried installing it anyways (npm install heroku) and still get the same error.

I saw a suggestion elsewhere recommending I set NODE_MODULES_CACHE to false in Heroku, which I've also done, to no avail.

Any ideas as to what I'm doing wrong here?

Edit: I now think this above error may be an error caused by running heroku logs --tail via the heroku CLI on the heroku website, because maybe my container doesn't have Heroku installed?

When I click "View logs" in the dropdown on the service's heroku page, I see these logs:

2024-03-26T13:48:40.543188+00:00 app[web.1]: 
2024-03-26T13:48:40.543188+00:00 app[web.1]: Node.js v20.11.1
2024-03-26T13:48:40.606107+00:00 heroku[web.1]: Process exited with status 1
2024-03-26T13:48:40.627333+00:00 heroku[web.1]: State changed from starting to crashed
2024-03-26T13:48:42.941754+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=goal-service-staging-3c32681ee39d.herokuapp.com request_id=d654a8fe-0ceb-46c5-b2ea-2ae63a7fe2d5 fwd="72.74.249.49" dyno= connect= service= status=503 bytes= protocol=https
2024-03-26T13:48:43.066833+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=goal-service-staging-3c32681ee39d.herokuapp.com request_id=68a2d6fa-e9b3-422e-a80b-bab6cbad21e8 fwd="72.74.249.49" dyno= connect= service= status=503 bytes= protocol=https
2024-03-26T13:49:01.893680+00:00 app[api]: Starting process with command `heroku logs --tail` by user [email protected]
2024-03-26T13:49:18.874678+00:00 heroku[run.5163]: State changed from starting to up
2024-03-26T13:49:22.565432+00:00 heroku[run.5163]: Process exited with status 1
2024-03-26T13:49:22.590829+00:00 heroku[run.5163]: State changed from up to complete

Which I'm not sure provide any additional information or not. I cannot see what is causing the 503.

1

There are 1 best solutions below

0
Ryan Doherty On

The answer for me ended up being adjusting my Dockerfile to correctly start the app.

As such, here is my new Dockerfile:

FROM node:20 AS base 
WORKDIR /app
COPY package.json .
RUN npm install && npm install ts-node -g
COPY . .
CMD ["ts-node", "src/index.ts"]

I needed to use ts-node to run the app, and it needed to be installed globally to work here.

Additionally, I needed to use process.env.PORT in my index.ts rather than a hard-coded value.