My node application works on my local(MacOS), but it does not work if I use docker.
it works if I try local:
npm install
npm start
It throws error if I try docker
docker-compose build
docker-compose up
I'm getting this error.
Error: Cannot find module '/src/node_modules/sqlite3/lib/binding/napi-v6-linux-musl-x64/node_sqlite3.node'
Package.json
{
"name": "api",
"version": "1.0.0",
"description": "API",
"main": "index.js",
"scripts": {
"test": "rm -rf usersdb.sqlite && jest --forceExit",
"test:coverage": "npm run test -- --coverage --forceExit",
"start": "nodemon app.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.20.1",
"cors": "^2.8.5",
"dotenv": "^10.0.0",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"lodash": "^4.17.21",
"mysql": "^2.18.1",
"nodemon": "^2.0.20",
"sqlite3": "^5.1.4"
},
"devDependencies": {
"jest": "^28.1.1",
"supertest": "^6.3.3"
}
}
docker-compose.yml
version: "3.7"
services:
api:
image: test/api
build: ./
command: npm start
restart: on-failure
environment:
SERVER_PORT: 3004
TOKEN_KEY: test123
volumes:
- .:/src
ports:
- "3004:3004"
Dockerfile
FROM node:12.22-alpine as base
WORKDIR /src
COPY package*.json ./
EXPOSE 3004
RUN apk add --no-cache python2 g++ make
RUN npm install
FROM base as dev
ENV NODE_ENV=development
RUN npm install -g nodemon
COPY . ./
CMD ["nodemon", "app.js"]
Delete the volumes: block from your docker-compose.yml.
The volumes: block in your docker-compose.yml file is overwriting your entire application with content from your host system. That includes overwriting the Linux-OS node_modules tree with the MacOS version from your host system.
You don't need this volumes: block. The code and node_modules: tree are built into your image. If you need to develop your application, you can install Node on your host system (on MacOS this might be as little as brew install node) and use that for day-to-day development, even if you're planning to eventually use Docker for final deployment or if you have dependencies that run in containers.
Related
My typescript compiler is looking in the wrong place for the types for one of my modules (redis), but only when run inside of Docker. Here's the end of the logging information running tsc inside the container:
======== Module name '../classes/range' was successfully resolved to '/app/node_modules/#types/semver/classes/range.d.ts' with Package ID '#types/semver/classes/range.d.ts#7.3.4'. ========
... more successful logs ...
node_modules/#types/connect-redis/index.d.ts(22,29): error TS2694: Namespace '"/app/redis"' has no exported member 'RedisClient'.
As you can see, it appears that the tsc command is looking inside of /app/redis for the member RedisClient rather than inside /app/node_modules/#types/redis which does export the type information. The tsc compiler doesn't have any problems when run from my local machine, only when it's being run inside the docker instance. Why is this the case?
Inside docker, the tsc command is being run from my package.json file, which is being run using docker-compose. The docker-compose file looks like this:
version: "3"
services:
api:
image: "typeorm-api:production"
container_name: "typeorm-api"
build:
context: ./
dockerfile: Dockerfile
volumes:
- ./src:/app/src
environment:
ENV: production
PORT: 1234
env_file:
- ".env.production"
# This command will overwrite what is contained in the Dockerfile
command: "npm run start:production"
ports:
- 1234:1234
depends_on:
- redis_server
reverse:
container_name: reverse
hostname: reverse
image: nginx:latest
volumes:
- ${PWD}/nginx/nginx.conf:/etc/nginx/nginx.conf
ports:
- 80:80
- 443:443
redis_server:
image: "redis:alpine"
container_name: redis_server
volumes:
- "./redis/production/data:/var/lib/redis"
expose:
- 6379
The npm run start:production command runs a command that's contained inside my package.json file (which installs my dependencies inside my application on the build step) and looks like this:
"start:production": "tsc --extendedDiagnostics --traceResolution && node dist/index.js"
The part that's failing is the tsc step and gives the error mentioned above.
The development settings work fine. Other files that might be useful in debugging, listed below.
Full package.json file:
{
"name": "myapi",
"version": "0.2.1",
"devDependencies": {
"#types/bcryptjs": "^2.4.2",
"#types/connect-redis": "^0.0.16",
"#types/cors": "^2.8.10",
"#types/express": "^4.17.11",
"#types/express-session": "^1.17.3",
"#types/ioredis": "^4.22.0",
"#types/node": "^14.14.31",
"#typescript-eslint/eslint-plugin": "^4.15.2",
"#typescript-eslint/parser": "^4.15.2",
"eslint": "^7.21.0",
"ts-node": "9.1.1",
"ts-node-dev": "^1.1.6"
},
"dependencies": {
"#types/redis": "^2.8.28",
"apollo-server-express": "^2.21.0",
"bcryptjs": "^2.4.3",
"class-validator": "^0.13.1",
"connect-redis": "^5.1.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-session": "^1.17.1",
"graphql": "^15.5.0",
"ioredis": "^4.23.0",
"pg": "^8.5.1",
"redis": "^3.0.2",
"reflect-metadata": "^0.1.13",
"type-graphql": "^1.1.1",
"typeorm": "0.2.31",
"typescript": "^4.2.2"
},
"scripts": {
"start:development": "ts-node-dev --respawn --poll src/index.ts",
"start:production": "tsc --extendedDiagnostics --traceResolution && node dist/index.js"
}
}
Full Dockerfile
FROM node:15.4.0-alpine3.10
# Specify that when you create the container, put the application inside the /app container
WORKDIR /app
# Copy our package.json + package-lock.json file into the /app folder (wildcard allows for package.lock.json)
COPY package*.json /app/
RUN npm ci
# Copy source files + compilation configuration, db connection options, etc.
COPY ./src .
COPY tsconfig.json .
COPY ormconfig.js .
COPY modules.d.ts .
# This command will be overwritten to be start:production with our docker-compose.prod.yml file
CMD npm run start:development
EXPOSE 1234
I'm so dumb.
I'd named a file that I was using in my project redis.ts and placed it in the root of my project. So, when the compiler was following it's normal rules to look for types, it looked at that file first, and didn't see the type declarations declared in it (because it wasn't the redis.d.ts file).
It didn't look inside the node_modules folder because of the name I chose. After changing the redis.ts file to redisConfiguration.ts everything works fine!
I am trying to get a Typescript project running in Docker. I created the Docker file based on a tutorial but when I run it I get:
/usr/local/bin/docker-entrypoint.sh: 8: exec: .: Permission denied
I am not sure how to diagnosis this problem.
I can enter the container with
docker run --rm -it d3ca97c88aec bash -il
and run the server with
npm start
I have no file called docker-entrypoint.sh and I didn't make one.
I STRONGLY FEEL THIS IS BECAUSE TYPESCRIPT MAKES A BUILD FOLDER AND THAT BUILD FOLDER IS PERMISSIONED DIFFERENTLY.
Dockerfile
FROM node:12
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm#5+)
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production
# Bundle app source
COPY . .
ENV COUCH_URL=NotSafeForStackOverflow
RUN npx tsc
EXPOSE 8080
CMD npx ts-node index.ts
{
"name": "express-react-app",
"version": "1.0.0",
"main": "index.js",
"repository": "",
"author": "",
"license": "",
"private": null,
"dependencies": {
"agentkeepalive": "^4.1.3",
"apollo-utilities": "^1.3.4",
"base64-arraybuffer": "^0.2.0",
"express": "^4.17.1",
"express-graphql": "^0.11.0",
"graphql": "^15.3.0",
"graphql-depth-limit": "^1.1.0",
"graphql-tag": "^2.11.0",
"graphql-type-json": "^0.3.2",
"i": "^0.3.6",
"merge-graphql-schemas": "^1.7.8",
"nano": "^8.2.2",
"node-webcrypto-ossl": "^2.1.1",
"npm": "^6.14.8",
"text-encoding": "^0.7.0",
"ts-node": "^9.0.0",
"typescript": "^3.7.4",
"uuid": "^8.3.0"
},
"scripts": {
"start": "npx ts-node index.ts",
"build": "npx tsc",
"dev": "nodemon --watch '**/*.ts' --exec 'ts-node' index.ts"
},
"devDependencies": {
"#types/express": "^4.17.7",
"#types/graphql": "^14.5.0",
"#types/node": "^14.6.3"
}
}
when you run CMD npx ts-node index.ts
it will overwrite default CMD [ "node" ]
please refer link below to how to use node image :
https://github.com/nodejs/docker-node/blob/master/README.md#how-to-use-this-image
you shoud be able done by using docker-compose :
version: "2"
services:
node:
image: "node:8"
user: "node"
working_dir: /home/node/app
environment:
- NODE_ENV=production
volumes:
- ./:/home/node/app
expose:
- "8081"
command: "npm start"
The fronted is made with create-react-app and the backend is Node.js with Firebase.
This is my folder structure:
my-app
├── docker-compose.yml
├── client
│ ├── Dockerfile
│ ├── package.json
├── server
│ ├── Dockerfile
│ ├── package.json
docker-compose.yml
version: "3.8"
services:
client:
container_name: client
build: ./client
ports:
- "3000:3000"
tty: true
server:
container_name: server
build: ./server
ports:
- "5000:5000"
client/package.json
{
"name": "react-ui",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.19.2",
"node-sass": "^4.14.1",
"normalize.css": "^8.0.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.1",
"react-scripts": "^3.4.1",
"redux": "^4.0.5"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"proxy": "http://server:5000",
"secure": false
}
client/Dockerfile
FROM node:lts
WORKDIR /client
COPY package*.json /client/
RUN npm install
COPY . /client/
RUN npm run build
EXPOSE 3000
CMD [ "npm", "start" ]
server/package.json
{
"name": "snake-react-node",
"version": "3.0.0",
"engines": {
"node": "10.x"
},
"scripts": {
"start": "node ./build/index.js",
"build": "tsc",
"dev": "nodemon ./src/index.ts"
},
"dependencies": {
"#types/express": "^4.17.7",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"firebase-admin": "^9.0.0",
"moment": "^2.27.0",
"rimraf": "^3.0.2",
"ts-node-dev": "^1.0.0-pre.56",
"typescript": "^3.9.7"
},
"license": "MIT",
"devDependencies": {
"nodemon": "^2.0.4",
"npm-run-all": "^4.1.5"
}
}
server/Dockerfile
FROM node:lts
WORKDIR /server
COPY package*.json /server/
RUN npm install
COPY . /server/
RUN npm run build
EXPOSE 5000
CMD [ "npm", "start" ]
When I run docker-compose up on the root directory, two images and two containers get created, one for each Dockerfile. The app runs flawlessly and a production build is created but I would like to be able to use Docker for development too, with live reloads
Since your server container publishes ports: out, you can change the proxy settings in your package.json file to point at this. In your non-Docker host development environment, set
"proxy": "http://localhost:5000"
and then you can npm run dev to have a totally ordinary local live-reloading development server, targeting your backend service that's running in Docker.
There's not really any technical benefits to trying to simulate a local development environment inside a Docker container, especially for a browser-based application. A typical Webpack-based build toolchain doesn't have complex native dependencies that would require special setup, and since the application itself runs in the browser, it can't take advantage of Docker networking and the container itself doesn't provide any of the application's runtime environment. So the only real difference between running the dev server on the host vs. in a container is which version of Node the Webpack build is using, and hopefully this isn't a substantial difference to your application.
You can use bind volume mounts for dev live reload. Make another dev compose file like docker-compose-dev.yml and add the volumes: section.
Whenever code is changed on the host machine using your favorite IDE, the container will pick it up and do the hot reload.
Note: I haven't tested this setup. Just suggesting something you could do.
#docker-compose-dev.yml
version: "3.8"
services:
client:
container_name: client
build: ./client
volumes:
- ./frontend-src:/client/src
ports:
- "3000:3000"
tty: true
server:
container_name: server
build: ./server
ports:
- "5000:5000"
I have dockerised a Node.js app for my Ubuntu server. The Dockerfile is incredibly simple, and had been working fine. Suddenly, on my Ubuntu server, I'm now seeing this error:
sudo docker run -p 80:8080 username/test:test
/bin/sh: 0: Can't open /usr/local/bin/docker-entrypoint.sh
My Dockerfile looks like this:
FROM node:12
# Create the app directory
WORKDIR /Tap2Tap/TapServer
COPY package*.json ./
RUN npm install
# Bundle app source
COPY . .
EXPOSE 8080
CMD ["npm", "start"]
There is no reference to this docker-entrypoint.sh and I don't know why it seems to have spontaneously stopped working. Any help would be much appreciated.
Best,
Peter
package.json file is:
{
"name": "Tap2Tap",
"version": "0.0.0",
"scripts": {
"start": "node ./bin/www.js"
},
"dependencies": {
"dotenv": "^8.2.0",
"express": "^4.17.1",
"helmet": "^3.22.0",
"https": "^1.0.0",
"mqtt": "^4.0.1",
"pg": "^8.0.3",
"winston": "^3.2.1",
"winston-daily-rotate-file": "^4.4.2"
}
When make volumes in docker-compose.yml and run docker-compose up and in "yarn run" step, it says (error Couldn't find a package.json file in "/usr/src/app")
my Dockerfile
FROM node:12
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json .
COPY yarn.lock .
RUN yarn
COPY . .
CMD [ "yarn", "watch" ]
docker-compose.yml
version: "3"
services:
listings-service:
build: ./listings-service
volumes:
- ./listings-service:/usr/src/app
package.json
{
"name": "listings-service",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"watch": "babel-watch -L ./index.js"
},
"devDependencies": {
"babel-watch": "^7.0.0",
"nodemon": "^2.0.2"
},
"dependencies": {
"#babel/core": "^7.9.0",
"#babel/polyfill": "^7.8.7",
"#babel/preset-env": "^7.9.0",
"babel-plugin-module-resolver": "^4.0.0",
"core-js": "3"
}
}
why do you need the volume here? your docker files compy all the files in and place them inside the docker image. In addition, running yarn will install dependencies and place them in /usr/src/app.
Adding the volume on the docker-compose ==> all files from the docker image will be removed and placed with the files inside the local path ./listings-service