0

I have an app that I want to run on a single self contained Docker image. I had it running fine on an Ubuntu based image, but the same script now causes me trouble on Alpine.

Here is my docker file :

FROM julienlengrand/alpine-node-rethinkdb

# Preparing
# RUN ln -snf /bin/bash /bin/sh

# # Define mountable directories.
VOLUME ["/data"]

# # Define working directory.
WORKDIR /data

# # Install app dependencies
COPY package.json /data
RUN npm install

# # Bundle app source
COPY . /data

# # Expose rethinkdb ports.
#   - 8080: web UI
#   - 28015: process
#   - 29015: cluster
EXPOSE 8080
#EXPOSE 28015
#EXPOSE 29015

# Expose node app ports
EXPOSE 4567

CMD [ "/bin/sh", "/data/startApp.sh" ]

My startApp script is relatively simple :

#!/bin/sh
rethinkdb --bind all & sleep 1; node dbCreate.js; sleep 2; nohup node workers/worker.js & node app.js

But when I try to run it, I get the following error:

module.js:442
    throw err;
    ^

'rror: Cannot find module '/data/app.js
    at Function.Module._resolveFilename (module.js:440:15)
    at Function.Module._load (module.js:388:25)
    at Module.runMain (module.js:575:10)
    at run (bootstrap_node.js:352:7)
    at startup (bootstrap_node.js:144:9)
    at bootstrap_node.js:467:3

This happens whether I run it automatically, or directly within the image using the shell.

I have checked and everything is correctly placed in the data folder. Additionally, if I run all the commands one after the other directly in the sh shell everything runs as expected.

I have also tried to simplify my script as such :

#!/bin/sh
rethinkdb --bind all & sleep 1; node dbCreate.js; sleep 2; node app.js

bu the same issue happens.

Any idea what can go wrong? What could make my /data folder unavailable when running via the startApp script? Could it be that it is a specificity from Alpine?

Thanks,

jlengrand
  • 12,152
  • 14
  • 57
  • 87
  • 1
    One suggestion though, do not put everything on a single docker image. think `microservices` - a single docker container should only do one thing. You should have one container for your NodeJS app and another one for RethinkDB. You would use `docker-compose` to easily orchestrate those containers, that is how docker-based apps are supposed to work. – huygn Aug 05 '16 at 06:32
  • Hey @HuyGiang. Yes, you are totally right, and that is something we want to do too. Consider this a necessary middle step :). – jlengrand Aug 05 '16 at 06:37
  • I would start with 2 separated container from the beginning, as building the image would be a lot easier, there are official images for both Node and RethinkDB and you can debug your Node container easier without custom startup script. – huygn Aug 05 '16 at 06:40
  • I have 2 different node scripts running though, the main app thread and a worker. Does it mean that I should run at least 3 different docker containers? – jlengrand Aug 05 '16 at 06:42
  • It depends on how your app and your worker interact. If they can run independently, you should separate them to their own container. – huygn Aug 05 '16 at 06:46
  • Back to your `Dockerfile`, try replacing `VOLUME ["/data"]` with `RUN mkdir /data` and rebuild & run – huygn Aug 05 '16 at 06:47
  • @HuyGiang. That is actually exactly what I was trying already :). Doesnt seem to change anything though :S – jlengrand Aug 05 '16 at 06:49
  • it says `Cannot find module '/data/app.js`, so you should check if `app.js` has been copied to `/data` yet. try `docker run -it --rm yourconatiner sh` and `ls /data` to whats inside. – huygn Aug 05 '16 at 06:53
  • @HuyGiang. The scripts are in data. I have validated this. If I run directly from within the container everything runs fine. I won't paste the content of my ls here, but all the expected files are there . – jlengrand Aug 05 '16 at 06:55

1 Answers1

1

The error message you are receiving looks like a classic carriage return issue as the quote after app.js has moved to the start of the line

'rror: Cannot find module '/data/app.js

Node should normally be able to deal with both line endings but shell scripts aren't so kind.

I generally default all projects/files/editors/git to a Unix \n unless there are specific requirements not too.

You can convert existing files with dos2unix or one of the answers in the question jlengrand found. I like perl -pi -e 's/\r\n/\n/g', because pie

Community
  • 1
  • 1
Matt
  • 68,711
  • 7
  • 155
  • 158
  • Indeed. The problem was coming from a Windows carriage return in my startApp.sh script. I removed it on the host side by using the method described here : http://stackoverflow.com/questions/2613800/how-to-convert-dos-windows-newline-crlf-to-unix-newline-n-in-bash-script – jlengrand Aug 05 '16 at 07:40
  • Out of interest, are you requiring that file based on the arguments to `node`? I'm trying to figure out how the carriage return got into the module loader. – Matt Aug 05 '16 at 07:51
  • No, the only thing I am doing in the script is calling node app.js. I have not touched the node scripts. I was a bit surprised as well that it was enough, tbh and was expecting to have to unixify the node app too. – jlengrand Aug 05 '16 at 08:17