Noob NodeJS/Docker question here.
I've written a node.js serverless project in an Ubuntu environment. I'm now trying to dockerise it.
The project has the following in the scripts section of package.js:
"scripts": {
"dev": "node --inspect $(npm bin)/sls offline start",
"docker": "node $(npm bin)/sls offline start --host 0.0.0.0"
}
Running npm run dev in my Ubuntu environment (22.04.1 LTS, node version 18.8.0) works fine, no issues. The API starts up and the project executes as expected.
I have the following in a Dockerfile:
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
RUN export SLS_DEBUG=*
# Node 18x, https://github.com/nodesource/distributions
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install openjdk-11-jdk -y && \
apt install curl -y && \
curl -sL https://deb.nodesource.com/setup_current.x | bash - && \
apt install nodejs -y
ADD ./ /app
WORKDIR /app
RUN npm install
# Serverless port
EXPOSE 3000
# NodeJS debug port
EXPOSE 9229
CMD npm run docker
I'm using the Ubuntu image and the node distribution to try and get the container as close as possible to my dev environment. The image builds successfully.
When running the built image, I just get the directory listing of the container, like:
./
├─lambda_funcs/
│ └─test_func( )/
├─models/
│ └─user.js
├─node_modules/
│ ├─2-thenable( )/
...etc
I'm happy to try using the node image as a base, but I don't understand why the docker image is doing something different than my dev environment. I don't even really understand why the directory listing is being output, other than assuming Node is having trouble finding the serverless module. But the package and package-lock files are being copied across, and I can see the serverless,serverless-offline and sls packages in the dependencies listing.
A Hello World Node app runs fine in the container, so it seems to be something to do with serverless itself?
Any help appreciated. Thanks
EDIT:
To be clear, I am expecting a serverless API to be run and accessible on port 3000 using the following serverless template:
service: My Service
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs14.x
stage: dev
environment:
cowenv: dev
functions:
my_test:
name: test_func
handler: lambda_funcs/test_func/index.handler
events:
- httpApi:
path: /test
method: get
mysql:
stages:
- dev
start:
docker: true
port: 8000
inMemory: true
migrate: true
seed: false
convertEmptyValues: true
noStart: true
package:
individually: true
plugins:
- serverless-offline
npm run docker
is the command I am using in the Dockerfile as an alias for node $(npm bin)/sls offline start --host 0.0.0.0
test_func should talk to the database and return some values.
CodePudding user response:
Not sure why you install the OS image. Just install Node.js image instead.
Dockerfile example:
FROM node:16.16.0
WORKDIR /app
COPY package.json .
RUN yarn install
COPY . .
And then you specify ENV commands ports volumes in your docker-compose file
CodePudding user response:
So in this case it seems like Node was interpreting node $(npm bin)/sls offline start --host 0.0.0.0
as, "run the sls library" aka the structured list library: https://www.npmjs.com/package/sls which means it was displaying exactly what was expected.
If I uninstall sls (not sure how it got installed), running the container outputs:
> node $(npm bin)/sls offline
/app/node_modules/.bin/sls:2
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
^^^^^^^
SyntaxError: missing ) after argument list
I stumbled across https://forum.serverless.com/t/possible-to-run-serverless-in-a-docker-container/5764, more specifically slinkardbrandon's answer. Essentially he uses a direct link to the serverless libraries within the Docker environment as parameters to CMD (a Gist is linked here):
CMD ["node", "./node_modules/serverless/bin/serverless.js", "offline", "start", "--host", "0.0.0.0"]
Why doesn't it work otherwise? Why have I seen sls offline being used in other docker containers with no issues? Who knows! I suspect gremlins.
But at least my application works now. I incidentally also did the rewrite to use node as a base image, so my Dockerfile is a lot cleaner. Thanks to all for your help.