"Part 1" Introduction to Docker for Javascript developers (based on Node.js)

Posted by eddie_twoFingers on Wed, 05 Jan 2022 16:13:53 +0100

Docker is an open source application container engine. If you are a back-end developer, you should know or be familiar with this technology. For many front-end developers, you may just stay at the stage of listening to it, or even don't know what it is? Or I think this is a back-end technology. I don't need to know. For example, I really don't know what it is, but if I want to become a senior front-end, this part of the vacancy needs to be filled. Salted fish should also have a dream. Maybe one day they can jump the dragon's gate!

This article will build a full stack node with web front-end code and mongoDB database JS application to further understand Docker and its purpose.

What is Docker

Docker is an open source application container engine, which is based on Go language and complies with Apache 2.0 0 protocol is open source. Docker allows developers to package their applications and dependency packages into a lightweight and portable container, and then publish them to any popular Linux and Window machine. It can also realize virtualization.

I don't understand. Can you explain Docker's past and present life?

In 2010, several young people engaged in IT established a company called dotcloud (engaged in container technology) in San Francisco. As a result, I couldn't hold on, so I opened the source. As a result, I was so angry that I had to start a new name, so Docker appeared.

Before Docker appeared, how to simulate an isolated system environment? The answer is the virtual machine. Everyone should be familiar with it. VMWare is installed in many developers' computers. Through it, we can change several sub computers, one with windows11 and one with CentOS, and install my favorite QQ, wechat and other software. Multiple sub computers are separated from each other and do not affect each other! However, there are only a few G's or dozens of G's. the disk can't afford it, and it starts slowly.

As mentioned earlier, before the advent of docker, virtual machines were popular in the industry in environmental isolation, but the disadvantages are serious. Docker container technology is also a virtualization technology, which is light, fast and integrated. It only needs MB level or even KB level. Unlike virtual machines, it needs to simulate an operating system, Docker only needs to virtualize a small-scale environment (similar to "sandbox").

No, I need to see the data comparison before I believe it. Arrange

Docker core concepts

In the previous section, we learned that Docker is a container virtualization technology, which is lighter, faster and easier to integrate. Next, we quickly understand its core concepts, and then go to today's topic to better understand it when writing code.

Docker's three core concepts:

  • Mirror (Image)
  • Container
  • Repository

The above diagram can reflect the relationship between the three. It should be noted here that Docker is a container technology, but Docker itself is not a container. It is a tool for creating containers and an application container engine.

Image, that is, Docker image, is a special file system. In addition to providing programs, libraries, resources, configuration files, etc. required by the container runtime, it also contains some configuration parameters (such as environment variables) prepared for runtime. At the same time, the image does not contain any dynamic data.

We can have many images. We want to save them, and then we can use them anywhere to create a container environment. Then we need a warehouse to store them, that is, the Docker warehouse.

How does a warehouse exist, so can everyone store images in it? No, if a problematic image is stored, won't it hang up when the container is created? Therefore, there needs to be a role responsible for managing Docker images, that is, Docker Registry service (similar to warehouse administrator). The official also provides a public Registry service, Docker Hub (a bit like our npm market), which stores many high-quality official images.

At the same time, we can customize our image through the Dockfile file, which will be introduced later

Through the above introduction, I believe you should also have a general understanding of Docker. Here are some common Docker commands,

# container
$ docker run  // Create and start the container
$ docker start // Start container
$ docker ps // View container
$ docker stop // Terminate container
$ docker restart // View container
$ docker attach // Enter container
$ docker exec // View container
$ docker export // Export container
$ docker import // Import container snapshot
$ docker rm // Delete container
$ docker log // view log

# image
$ docker search // Retrieve image
$ docker pull // Get image
$ docker images // List mirrors
$ docker image ls // List mirrors
$ docker rmi // delete mirror
$ docker image rm // delete mirror
$ docker save // Export mirror
$ docker load // Import mirror

# Dockfile custom image and common instructions

$ docker build // Build mirror
$ docker run // Run mirror

COPY // Copy file
ADD // Advanced replication
CMD // Container start command
ENV // environment variable
EXPOSE // Exposed interface


# service
$ docker -v // View brief information about docker
$ docker -version // View details of docker version
$ systemctl start docker // Start docker
$ systemctl stop docker // Close docker
$ systemctl enable docker // Set startup
$ service docker restart // Restart docker service
$ service docker stop // Close docker service

Create a hello world container

First, you need to download Docker Download address , I downloaded the Window Docker Desktop. Next, check whether the version information was downloaded successfully,

I downloaded version 20.10.11

Then pull the official Hello world image of Docker Hub,

Create and execute containers,

In this way, the first container is created. You can use the above command line docker image ls / docker image prune to view or delete the useless image (it will not be deleted when the container is stopped, which will help speed up the download and installation next time). You can try more commands!

Create Node program

Next, we will create a Node program, which will be used in the following tutorial. The specific code details will not be introduced. You can view the following server JS and package json:

const express = require("express");
const app = express();
const port = 8080;

app.get("/", async (req, res) => {
  res.setHeader("Content-Type", "text/html");
  res.status(200);
  res.send("<h1>How do you do! Front end evening class</h1>");
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});
{
  "name": "docker-example",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "start": "nodemon server.js"
  },
  "author": "Front end evening class",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.2"
  },
  "devDependencies": {
    "nodemon": "^2.0.15"
  }
}

Run npm run start and run successfully

Problems with different Node versions

For the above server JS file, we add the following code:

 // ...
 const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("good");
  }, 300);
  reject("bad");
});

myPromise.then(() => {
  console.log("this will never run");
});

Then run on node < 15 and node > = 15 respectively, and two different results will be obtained,

Node < 15

(node:764) UnhandledPromiseRejectionWarning: something happened
(Use `node --trace-warnings ...` to show where the warning was created)
(node:764) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:764) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Node >= 15

node:internal/process/promises:218
          triggerUncaughtException(err, true /* fromPromise */);
          ^

[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "recipe 
could not be generated".] {
  code: 'ERR_UNHANDLED_REJECTION'
}

It will be found that the execution results of the two versions are inconsistent. The higher version (node > = 15) will directly cause the program crash (ERR_UNHANDLED_REJECTION). This is Unhandled rejected Promise Error.

Now suppose that for some reason, this application must run on Node v14 or earlier to work (ignore try...catch). Every developer in the team must be ready to develop and run in this environment, but our company has a new application to run on Node v17!

Then how should we solve this problem? Answer: Docker

Create Dockerfile

In the previous section, we introduced the problem of unprocessed rejected Promise caused by two different versions of nodes. We introduced how to use Docker to solve this problem. In fact, it is very simple, that is, we need a running environment with Node < 15 to ensure that our program will not collapse,
We can search the image of the Node in the Docker Hub, and there are many version information available.

Of course, we don't need to directly use docker pull node to pull the node image. We mentioned earlier that Dockerfile can be used to customize and customize the image. It automatically determines whether there is a node image on the current machine. If not, we can automatically pull it from the Docker Hub. Take a look at our Dockerfile file:

# First, select the image you need. The node version running on alpine is the most popular at present
FROM node:14-alpine3.12

# working directory
# This is where you will be in the container
WORKDIR /usr/src/app

# Wildcards are used to ensure that package JSON and package lock JSON is copied
# COPY the working directory of the source directory container
COPY package*.json ./

# Install app dependencies
RUN npm install

# If you're building code for production
# RUN npm ci --only=production

# Bundle application source
COPY . .

# Configure this port to be accessible from outside the container
# Required for the browser to send HTTP requests to Node applications
EXPOSE 8080

# CMD runs when docker run s
# Is to execute shell npm run start
CMD [ "npm", "run", "start"]

ok, our Dockerfile file has been created successfully, and the comments on the Dockerfile instruction in the above code are also briefly introduced. You can search Google for more detailed instruction usage, but you may be curious about the above configuration file, why COPY needs to be executed twice, and the last COPY Instead of copying the entire directory, why do I need to COPY package * json?

Docker layer and cache

It is necessary to COPY twice because Docker has layers (layer characteristics). Each instruction will create another layer based on the layer created by the last instruction. The created layer will be cached and will be re created only when it is changed. Let's look back at the Dockerfile file.

COPY package*.json ./ We create a layer based on the contents of the file, and then run npm install, which means that unless we change the package JSON, otherwise the next time we build Docker, we will use npm install to install the running cache layer. We don't have to install all dependencies docker build every time we run. This will save us a lot of time.

COPY . . Each file in our project directory will be viewed, so the layer will be rebuilt when any file changes (except package*.json). That's what we want.

Build application container

Let's add another one Docker ignore file, similar to ours gitignore, because we don't want to copy these files.

node_modules
npm-debug.log

When everything is ready, we begin to build our own image,

# Take the current project directory as the source directory and give the image a name called qianduanwanjianke
$ docker build . -t qianduanwanjianke

Check whether the image we created exists?

After creating the image, we are now ready to build a container from the image to run our application:

# --Name we gave the container a name called qianduanwanjianke container
# -The p flag maps the port from port 3001 of our host (our computer) environment to port 8080 of the container environment. Of course, it can also be 8080:8080.
docker run -p 3001:8080 --name qianduanwanjianke-container qianduanwanjianke

It's done. Let's visit http://localhost:3001/ See if it works,

epilogue

Here, we introduce Docker through a Node application entry, create our first custom Docker image and container, and run our application in it! This is an introduction to Docker for Javascript developers. It is cut in by the Node program. The content of this article may be quite easy for back-end developers who are familiar with Docker, and it should be a good introductory tutorial for our front-end developers. Due to the long space, I decided to introduce Docker Volume("connect" the program copy inside the container and the copy in the project directory, update and synchronize) and to analyze the difference between the database hosting server. How to create separation and Docker composition will be introduced in the next chapter.

Pit stepped in the process

1. error during connect: This error may indicate that the docker daemon is not running

terms of settlement:

# Lifting access in Powershell solves this problem
cd "C:\Program Files\Docker\Docker"
./DockerCli.exe -SwitchDaemon

2. When creating an application container, execute docker build- T my node app, error message: no matching manifest for windows/amd64 10.0.18363 in the manifest list entries?

terms of settlement:
Open Docker Devlop software, setting - > Docker engine, set experimental to true, and restart Docker

Topics: node.js Docker