2

I'm trying to dockerize an Adonis app built with version 5. I'm running into this error while starting this multi-container app:

Error: Cannot find module 'tslib'
Require stack:
- /app/node_modules/@adonisjs/redis/build/src/RedisConnection/index.js
- /app/node_modules/@adonisjs/redis/build/src/RedisManager/index.js
- /app/node_modules/@adonisjs/redis/build/providers/RedisProvider.js
- /app/node_modules/@poppinss/utils/build/src/esmRequire.js
- /app/node_modules/@poppinss/utils/build/index.js
- /app/node_modules/@adonisjs/fold/build/src/Ioc/index.js
- /app/node_modules/@adonisjs/fold/build/index.js
- /app/node_modules/@adonisjs/application/build/index.js
- /app/node_modules/@adonisjs/core/build/standalone.js
- /app/server.js
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
at Function.Module._load (internal/modules/cjs/loader.js:725:27)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18)
at Object.<anonymous> (/app/node_modules/@adonisjs/redis/build/src/RedisConnection/index.js:12:17)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Module.require (internal/modules/cjs/loader.js:952:19)

This is the package.json file:

{
  "name": "foo-bar-baz",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "build": "node ace build --production",
    "start": "node server.js",
    "dev": "node ace serve --watch",
    "lint": "eslint . --ext=.ts",
    "format": "prettier --write ."
  },
  "devDependencies": {
    "@adonisjs/assembler": "^3.0.6",
    "adonis-preset-ts": "^1.1.0",
    "eslint": "^7.16.0",
    "eslint-config-prettier": "^7.1.0",
    "eslint-plugin-adonis": "^1.0.15",
    "eslint-plugin-prettier": "^3.3.0",
    "pino-pretty": "^4.3.0",
    "prettier": "^2.2.1",
    "typescript": "^4.1.3",
    "youch": "^2.1.1",
    "youch-terminal": "^1.0.1"
  },
  "dependencies": {
    "@adonisjs/core": "^5.0.4-preview-rc-2.1",
    "@adonisjs/lucid": "^10.0.0",
    "@adonisjs/redis": "^5.0.9",
    "@adonisjs/repl": "^1.1.6",
    "@adonisjs/session": "^4.0.6",
    "@adonisjs/shield": "^4.0.3",
    "@adonisjs/view": "^3.1.0",
    "luxon": "^1.25.0",
    "mysql": "^2.18.1",
    "proxy-addr": "^2.0.6",
    "reflect-metadata": "^0.1.13",
    "source-map-support": "^0.5.19"
  }
}

This is docker-compose.yaml file:

version: '3.8'

services:
  redis:
    image: redis
    volumes:
      - redis:/data

  mysql:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    env_file: ./env/mysql.env
    volumes:
      - mysql:/var/lib/mysql

  app:
    build:
      context: .
      dockerfile: Dockerfile
    env_file: ./env/app.env
    ports:
      - 80:3333
    depends_on:
      - redis
      - mysql

volumes:
  redis:
  mysql:

And this is the Dockerfile:

FROM node:lts

WORKDIR /app

COPY package*.json ./

RUN npm install --production

COPY build/ .

ENV NODE_ENV=production PORT=3333 HOST=0.0.0.0

EXPOSE ${PORT}

USER node

CMD [ "node", "server.js" ]

If I remove --production and install all dependencies, then everything works. I'm not sure where I missed what. Can someone help me please? Thanks in advance.

msrumon
  • 1,250
  • 1
  • 10
  • 27
  • Is it possible the build folder contains some `node_modules` (leftovers?) and when `COPY build/ .` runs they overwrite the ones installed by `npm install`. Because `npm install` runs before copying that folder – kidroca Dec 23 '20 at 19:51
  • No it's not possible. I built the image as soon as I run `node ace build --prod`. – msrumon Dec 23 '20 at 19:53

2 Answers2

2

I've followed the stack trace to see the file where the exception occurs it does indeed try to use the tslib module

/app/node_modules/@adonisjs/redis/build/src/RedisConnection/index.js

"use strict";
/*
 * @adonisjs/redis
 *
 * (c) Harminder Virk <virk@adonisjs.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.RedisConnection = void 0;
const tslib_1 = require("tslib");

So perhaps it's an issue with the @adonisjs/redis

When you include eslint-adonis-plugin (or install without the --production flag) tslib is installed too as it's resolved as a dependency of eslint-adonis-plugin and you don't get the error

kidroca
  • 3,480
  • 2
  • 27
  • 44
0

It seems to be typescript related so perhaps you need to transpile your code before running node server.js

  • If you run the transpiler at runtime to start the application then typescript and related packages need to be in dependencies
  • If you prebuild the application then it should be a dev dependency (seems this is the case for you)

Here's what I've found:

Run the following command to create a production build.

node ace build --production 

At this stage, you can upload the build folder to your production server, install the dependencies and run node server.js to start the server.

So first build, then copy the build and then install dependencies. You don't have to copy package*.json the build does it for you

#...

# COPY package*.json ./ # remove this

COPY build/ .

RUN npm ci --production # or npm install --production

# ...

CMD [ "node", "server.js" ]

If everything works when you install all dependencies (npm install without --production) You can move all dependencies from devDependencies to dependencies and then start moving them back to devDependencies one by one to see which one is causing the problem.


Can you verify everything works locally by copying the build folder somewhere and then running node server.js inside it. You can copy the .env file from the project so that you don't have to set all the ENV variables locally (though make sure you set NODE_ENV=production in this case). We're copying the folder away so it does not resolve any node_module from the parent (project) folder

I just did this and everything works fine:

  • npx create-adonis-ts-app hello-world and created the same setup (package.json) as yours
  • npm run build
  • copy build outside of project
  • run node server.js from inside
{"level":30,"time":1608752346315,"pid":15784,"hostname":"DESKTOP-98A1RFS","name":"adonis-5-hello-world","msg":"started server on 0.0.0.0:3333"}
kidroca
  • 3,480
  • 2
  • 27
  • 44
  • If you look into the 'Dockerfile' more closely, you'll notice that I'm already copying the transpiled output inside the container. So there shouldn't be any problem regarding this matter. If you want to know which package is responsible for the error, it's "eslint-adonis-plugin". – msrumon Dec 23 '20 at 18:36
  • Can you try to run the `build` locally to see whether the error happen. I had no problem running in production mode and I've update the answer with my steps – kidroca Dec 23 '20 at 19:45
  • No error while running locally. `scp package.json .env ./build && npm i --prod && NODE_ENV=production node build/server` works perfectly fine. – msrumon Dec 23 '20 at 19:52
  • just in case maybe use the full `--production` flag - there's no `--prod` – kidroca Dec 23 '20 at 20:32