docker build creates two images instead of one with the two components - node.js

i want to build a easy web server to get in touch with docker compose but there are two images build and the webserver doesnt run.
app.js:
'use strict';
const cors = require('cors');
const { request } = require('express');
const express = require('express');
const {flaschenpost} = request('flaschenpost');
const http = require('http');
const logger = flaschenpost.getLogger();
const api = express();
api.use(cors());
api.get('/', (req,res) => {
res.json(
{
now: Date.now()
});
});
const server = http.createServer(api);
const port = 3_000;
server.listen(post, ()=> {
logger.info('Server started.', {port});
});
my Dockerfile looks like this:
FROM node:16.13.0-alpine
USER node
WORKDIR /home/node
COPY --chown=node:node ./package.json ./package.json
COPY --chown=node:node ./package-lock.json ./package-lock.json
RUN npm install --production
COPY --chown=node:node . .
CMD [ "node", "app.js"]
sudo docker build -t api
sudo docker run -d --init -p 3000:3000 --name api api
The output is after running docker ps
|REPO |TAG |IMAGE_ID |CREATED |SIZE |
|api |latest |f164f3da6ad2|4 minutes ago|127MB|
|node |16.13.0-alpine|44e24535dfbf|12 months ago|110MB|
curl http://localhost:3000
outputs this:
curl: (7) Failed to connect to localhost port 3000 after 0 ms: Connection refused

Something is wrong.
Dockerfile
FROM node:17
ENV NODE_ENV=production
WORKDIR /app
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install --production
COPY . .
CMD [ "node", "index.js" ]
Now build it
docker build -t api .
Inspect image to if you get what you really want
docker inspect image api:latest
[
{
"Id": "sha256:7bbad5c790f4583e19b1dcf3b3c1aeb0a45fc46ad997d54222a51f1867e8789b",
"RepoTags": [
"api:latest"
],
"RepoDigests": [],
"Parent": "sha256:e58f7a2e8bb5c548475104eb813a6f12b8f610aa939b69de92d349116c2d9a00",
"Comment": "",
"Created": "2022-11-14T09:51:03.762665424Z",

Related

Docker not exposing my application to run locally

I've an express application which looks as follows:
const express = require("express");
const PORT = process.env.PORT || 3001;
app = express();
app.all("*", (req, res) =>
res.status(200).json({
status: 200,
message: "Hello world from Docker.",
})
);
app.listen(PORT, "127.0.0.1", () =>
console.log("The server is running on port: %s", PORT)
);
I want to build an image based on this simple express application so my Dockerfile looks as follows:
FROM node:18-alpine
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
EXPOSE 3001
CMD ["npm", "start"]
.dockerignore looks as follows:
node_modules
This is how i built my image:
docker build -t my-app:1.0 .
Now if i start an image locally as follows:
docker run -p 3001:3001 my-app:1.0
And if i visit on my web-browser at http://localhost:3001, there's nothing showing in the browser.
OS: Windows 10
What am i missing here?
You can expose the app for external connections this way:
app.listen(PORT, "0.0.0.0", () =>
console.log("The server is running on port: %s", PORT)
);

How to build and start next.JS in production with graphql appollo server?

I am trying to dockerize a next.JS TypeScript app which uses express and apollo graphql.
My server/index.ts looks like this:
app.prepare().then(() => {
const server = express.default();
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
});
server.get("*", (req, res) => {
return handle(req, res);
});
apolloServer.start().then((res) => {
console.log(res);
const graphqlHandler = apolloServer.createHandler({ path: "/" });
server.use("/api/graphql", graphqlHandler);
server.listen(process.env.PORT || 3000, (err: string | void) => {
if (err) throw err;
console.log(
`>>> Listening on http://localhost:${process.env.PORT || 3000}`
);
});
});
});
apollo client:
const GRAPHQL_URL = process.env.NODE_ENV == 'development' ? 'http://localhost:3000/api/graphql': 'https://app1.com/api/graphql' ;
package.json:
"scripts": {
"build:next": "next build",
"build": "npm run build:next && npm run build:server",
"start": "next start",
"start:production": "node dist/index.js"
If building with npm run build and then npm run start:production, then after the first refresh I get the error ``` ReferenceError: Cannot access 'data' before initialization ````. In this case the query request is on the CSR and not with getServerSideProps. The environment variable here is still "development" and not "production".
If building with next build and next start then my appollo server does not start and I get a 404 that the graphql API is not found.
I am starting the app in production in a docker container:
FROM node:16
ENV PORT 3000
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Installing dependencies
COPY package*.json /usr/src/app/
RUN npm install
# Copying source files
COPY . /usr/src/app
# Building app
RUN npm run build
EXPOSE 3000
# Running the app
ENTRYPOINT [ "npm", "run", "start:production" ]
What am I doing wrong here?

Dockerfile not working on backend with react

I'm trying to run a react app with 2 node servers. One for the front end and one for the back-end connected with a mysql data-base.
I'm trying to use docker for the container and I managed to get the database and the front-end server up. However,When the back-end server is fired it seems like it doesn't acknowledge the Dockerfile.
node_server | npm WARN exec The following package was not found and will be installed: nodemon
node_server | Usage: nodemon [nodemon options] [script.js[args]
node_server |
node_server | See "nodemon --help" for more.
node_server |
node_server exited with code 0
Dockerfile - client:
FROM node:latest
RUN mkdir -p /usr/src/app
WORKDIR /usr/scr/app
EXPOSE 3000
COPY package.json .
RUN npm install express body-parser nano nodemon cors
COPY . .
Dockerfile - server
FROM node:latest
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
RUN npm init -y
RUN npm install express body-parser nano nodemon cors
EXPOSE 5000
CMD ["npx", "nodemon", "src/server.js"]
docker-compose
version: '3'
services:
backend:
build:
context: ./server
dockerfile: ./Dockerfile
depends_on:
- mysql
container_name: node_server
image:
raff/node_server
ports:
- "5000:5000"
volumes:
- "./server:/usr/src/app"
frontend:
build:
context: ./client
dockerfile: ./Dockerfile
container_name: node_client
image:
raff/node_client
ports:
- "3000:3000"
volumes:
- "./client:/usr/src/app"
mysql:
image: mysql:5.7.31
container_name: db
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: admin
MYSQL_DATABASE: assignment
The server side is not done yet, but i don't believe it's causing this error.
Server.js
"use strict";
const path = require("path");
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());
const mysql = require("mysql");
let con = mysql.createConnection({
host: "mysql",
port: "3306",
user: "root",
password: "admin",
});
const PORT = 5000;
const HOST = "0.0.0.0";
app.post("/posting", (req, res) => {
var topic = req.body.param1;
var data = req.body.param2;
sql_insertion(topic, data);
});
// Helper
const panic = (err) => console.error(err);
// Connect to database
con.connect((err) => {
if (err) {
panic(err);
}
console.log("Connected!");
con.query("CREATE DATABASE IF NOT EXISTS assignment", (err, result) => {
if (err) {
panic(err);
} else {
console.log("Database created!");
}
});
});
//select database
con.query("use assignment", (err, result) => {
if (err) {
panic(err);
}
});
// Create Table
let table =
"CREATE TABLE IF NOT EXISTS posts (ID int NOT NULL AUTO_INCREMENT, Topic varchar(255), Data varchar(255), Timestamp varchar(255), PRIMARY KEY(ID));";
con.query(table, (err) => {
if (err) {
panic(err);
} else {
console.log("Table created!");
}
});
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client/build" , "index.html"));
});
app.listen(PORT, HOST);
console.log("up!");
Modify this line
CMD ["npx", "nodemon", "src/server.js"]
By
CMD ["npx", "nodemon", "--exec", "node src/server.js"]
While putting the command in package.json under scripts section is better.
Your volumes: declarations are hiding everything that's in the image, including its node_modules directory. That's not normally required, and you should be able to trim the frontend: container definition down to
backend:
build: ./server # default `dockerfile:` location
depends_on:
- mysql
image: raff/node_server # only if you plan to `docker-compose push`
ports:
- "5000:5000"
The image then contains a fixed copy of the application, so there's no particular need to use nodemon; just run the application directly.
FROM node:latest
WORKDIR /usr/src/app # also creates the directory
COPY package.json package-lock.json .
RUN npm ci # do not `npm install` unmanaged packages
COPY . . # CHECK: `.dockerignore` must include `node_modules`
EXPOSE 5000
CMD ["node", "src/server.js"]
This apparently isn't a problem for your frontend application, because there's a typo in WORKDIR -- the image installs and runs its code in /usr/scr/app but the bind mount is over /usr/src/app, so the actual application's /usr/scr/app/node_modules directory isn't hidden.

Having modules problems Dockerizng simple node app

Having some problems while trying to create my first node.js app , super new to JS..
Trying to dockerize the app , like so :
docker build -t echo_app .
docker run -p 3000:3000 echo_app
End goal is to echo user input , like so :
http://example/?name=Eyal -> Hello Eyal
http://example/ -> Hello World
ERROR IM GETTING
Error: Cannot find module 'express'
Require stack:
- /app/index.js
.
.
code: 'MODULE_NOT_FOUND',
requireStack: [ '/app/index.js' ]
}
Directroy containes :
index.js
const express = require('express')
const log4js = require('log4js')
const app = express()
const logger = log4js.getLogger()
const echo = (req, res) => {
logger.debug("Request: ", req)
const input = 'name' in req.query ? req.query.input : ''
if (input.length == 0) {
res.send('Echo World')
} else {
res.send(`Echo ${input}`)
}
}
app.get('/', (req, res) => echo(req, res))
Dockerfile
FROM mhart/alpine-node:12
WORKDIR /app
ADD . ./
ENTRYPOINT ["node", "/app/index.js"]
package.json
{
"name": "echo",
"version": "1.0.0",
"description": "You talk, we talk back!",
"main": "index.js",
"author": "eyal",
"license": "MIT",
"dependencies": {
"express": "^4.17.1",
"js-yaml": "^3.13.1",
"log4js": "^5.2.2",
"saslprep": "^1.0.3"
}
}
To get it up and running, you first need to install the node dependencies by adding npm install to your Dockerfile, like this
FROM mhart/alpine-node:12
WORKDIR /app
ADD . ./
RUN npm install
ENTRYPOINT ["node", "/app/index.js"]
Then you need to have your Node app listen for requests by adding
app.listen(3000, () => {
console.log(`Example app listening at http://localhost:3000`)
})
at the bottom of index.js.
Finally, a small error in your code. req.query.input needs to be req.query.name.
That should hopefully get you going.

Why is container exiting immediately after executing docker run command?

I am running docker for the first time and my container is exiting immediately after docker run command. The docker ps is showing me an empty list. When I run docker ps -a I am getting the results of all the containers I pushed in Exited state.
I have tried using -ti command but the container is going in exit state.
I am using following commands to run the file: $ sudo docker build -t test_api3 . and $ sudo docker run -p 8080:3000 -ti test_api3 or ($ sudo docker run -p 8080:3000 -d test_api3)
Dockerfile
FROM node:8
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD [ "npm","start" ]
package.json
{
"name": "firstapp",
"version": "1.0.0",
"description": "first demo app",
"main": "http-server.js",
"scripts": {
"start": "node http-server.js"
},
"keywords": [
"S"
],
"author": "test",
"license": "ISC"
}
http-server.js
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
I am running ubuntu os and it works (Let me know your setup if it still cannot work). The only problem with the code is that you cannot use the address 127.0.0.1 and must use 0.0.0.0 in your http-server.js. For more explanation refer to the link below
https://forums.docker.com/t/network-param-for-connecting-to-127-0-0-1-in-container/2333

Resources