文章目录
1. Project Demo
Here we outline a project of NodeJS,which we are going deploy to Docker ,and connect it with the explorer in our local machine.And to make this project impressive,we intendedly add some mistakes,which ,I bet ,you will make whatsoever.
2. Do some preparation
Basically,we have two texts for preparation.
- Create a new file called package.json and copy paste the following into it:
{
"dependencies": {
"express": "*"
},
"scripts": {
"start": "node index.js"
}
}
- Create a new file called index.js and copy paste the following into it:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('How are you doing');
});
app.listen(8080, () => {
console.log('Listening on port 8080');
});
- The Dockerfile that defines deps and cmds
# specify a base image
FROM alpine
# install deps
RUN npm install
# default cmd
CMD ["npm", "start"]
- Make sure you have the directory and file as this structure.
$ ls -a
./ ../ Dockerfile index.js package.json
3. A Few Planned Errors
Assuming that you have done the preparation as i said in last section, at present,you run docker build .
,soon you find out a error msg:
$ docker build .
Sending build context to Docker daemon 4.096kB
Step 1/3 : FROM alpine
---> caf27325b298
Step 2/3 : RUN npm install
---> Running in 7a06dee511f0
/bin/sh: npm: not found 【by author: here comes the error !】
The command '/bin/sh -c npm install' returned a non-zero code: 127
4. Base Image Issues
We select our base image based upon the collection of default programs that we need to successfully build our image by default.
In terms of alpine image ,it is a rather small one of only 5 megabytes, and it does not cover the necessary programs including “npm” that we need for real.
The tag of “alpine” tends to indicate that this image is as compact and small as possible,and it should only involves very limited sets of programs. Here we must distinguish the tag of “alpine” from the image of “alpine”.
We are not to use the alpine image in the DockerHub.
# specify a base image
FROM node:alpine
# install deps
RUN npm install
# default cmd
CMD ["npm", "start"]
Soon we find glitches again:
The configuration file of package.json is NOT in the container at all ,and it is outside of it , so during step2/3 of running npm install
, the node in the container is just not able to find the package.json file,thus throwing an error message .It is a matter of communication stuff.
5. Copying Build Files
We need a copy
cmd to copy necessary files from outside the container into it ,and after that, rebuild the container .
# specify a base image
FROM node:alpine
# install deps
COPY ./ ./
RUN npm install
# default cmd
CMD ["npm", "start"]
About the ‘copy’ cmd:
We’ll look into the ‘copy’ line:
- the first
./
means the working directory where you run thebuild
cmd ,i.e. the one in which you place the package.json , index.js, etc. - the second
./
refers the working directory where, inside the container, the project is really build.
Flip over back to the terminal ,rebuild the project and see what happens.
It’s good that you finally successfully build the project. Even though i presume that you are already aware of building and running the image,yet i still post the code snippet down here.
docker build .
docker run ContainerID
or :
we use tag to flag the container.
docker build -t justinwins/simpleweb . 【there's a dot at the end of the line】
docker run justinwins/simpleweb
When you see:
> @ start /
> node index.js
Listening on port 8080
Congratulations!You’ve made it!
6. Container Port Mapping
Unfortunately, when you open up your brower ,and attempt to visit localhost:8080
,you only get an error page.That’s wierd,isn’t it?
Now I list the cmds that may interest you:
$ winpty docker run -it e92b580f4f9b sh
/ # ls
Dockerfile etc lib node_modules package.json run sys var
bin home media opt proc sbin tmp
dev index.js mnt package-lock.json root srv usr
/ #
You will find that package.json , index.js ,etc have been copied into the root directory.That is not the recommeneded practice ,as we usually place our own application into /usr/
or /home
directory. However ,there is no tremendous difference at all ,as long as you are not to place custome apps into the root directory .It is adivised that you refer to FHS on Linux for a little bit help.
So,we introduce the environment variable:WORKDIR
,which ,by analogy ,looks like PATH, LANG,etc
in Bash.There we go.
That is really a brief diagram, and i presume that you get it inside out.
We then rewrite the Docker file,and rebuid the project ,
First of all, the Docker file :
# specify a base image
FROM node:alpine
# FROM node:8.15.0-alpine
# specify a workdir
WORKDIR /usr/app
# install deps
COPY ./ ./
RUN npm install
# default cmd
CMD ["npm", "start"]
Then , build the project:
Terminal1:
$ docker build -t justinwins/simpleweb . 【. is assigned by WORKDIR --> /usr/app】
Sending build context to Docker daemon 4.096kB
Step 1/5 : FROM node:alpine
---> ebbf98230a82
Step 2/5 : WORKDIR /usr/app 【here ,the WORKDIR is reassigned 】
---> Running in 0a348b56e1c4
Removing intermediate container 0a348b56e1c4
---> 2701c9499413
Step 3/5 : COPY ./ ./
---> 9d5b5c9d4dc2
Step 4/5 : RUN npm install
.......(too long to list in detail)
$ docker build -t justinwins/simpleweb .
$ winpty docker run -p 8080:8080 a8cef003d48d
> @ start /usr/app
> node index.js
Listening on port 8080
【Here you refresh your brower page,and see what happens.】
Terminal2:
$ winpty docker run -it a8cef003d48d sh
/usr/app # ls
Dockerfile index.js node_modules package-lock.json package.json
/usr/app #
【Here you find that the work directory has been changed to /usr/app ,instead of / 】
7. Unnecessary Rebuilds
If we modify the index.js
,say ,just one line of it ,we still need to rebuild the entire project ,and that may take a few seconds. But when it comes to the real project for productivity ,it may taker a few minutes or longer.
However, it is not necessary to rebuild the whole project,since we do not change the dependencies.
# specify a base image
FROM node:alpine
# FROM node:8.15.0-alpine
# specify a workdir
# WORKDIR /usr/app
# install deps
COPY ./package.json ./ 【keep the necessary files miminum,thus using cache as much as possible 】
RUN npm install
COPY ./ ./ 【overwrite the whole WORKDIR 】
# default cmd
CMD ["npm", "start"]
8. Conclusions
Here are the cmd list mentioned before .
docker build -t repo-name/project-name .
【build the project with a tag attached, t is short for 'tag'】
docker run -it ContainerID sh
【run the container with the shell open】
docker exec -it ContainerID sh
【open the shell terminal within the Container】