如何在 Ubuntu 20.04 上使用 Docker 构建 Node.js 应用程序

简介

Docker](https://www.docker.com/)平台允许开发人员将应用程序打包成_容器_运行。容器是在共享操作系统上运行的隔离进程,是虚拟机的轻型替代品。虽然容器并不是新事物,但随着越来越多的开发人员使用分布式应用程序架构,容器所带来的好处(包括进程隔离和环境标准化)正变得越来越重要。

使用 Docker 构建和扩展应用程序时,起点通常是为应用程序创建映像,然后在容器中运行。映像包括应用程序代码、库、配置文件、环境变量和运行时。使用映像可确保容器中的环境是标准化的,并且只包含构建和运行应用程序所需的内容。

在本教程中,您将为一个使用 Express 框架和 Bootstrap 的静态网站创建一个应用程序映像。然后,您将使用该映像构建一个容器,并将其推送到 Docker Hub 以供将来使用。最后,您将从 Docker Hub 存储库中提取存储的映像并构建另一个容器,从而演示如何重新创建和扩展您的应用程序。

先决条件

要学习本教程,您需要

第 1 步 - 安装应用程序依赖项

要创建映像,首先需要创建应用程序文件,然后将其复制到容器中。这些文件将包括应用程序的静态内容、代码和依赖项。

首先,在您的非根用户的主目录中创建您的项目目录,我们将称之为node_project,但您可以自由地将其替换为其他东西:

1mkdir node_project

导航到此目录:

1cd node_project

这将是该项目的根目录。

接下来,创建一个 package.json 文件,包含您项目的依赖和其他识别信息。 使用 nano 或您最喜欢的编辑器打开该文件:

1nano package.json

添加有关项目的下列信息,包括名称、作者、许可证、入门点和依赖点,请确保将作者信息替换为自己的名字和联系信息:

 1[label ~/node_project/package.json]
 2{
 3  "name": "nodejs-image-demo",
 4  "version": "1.0.0",
 5  "description": "nodejs image demo",
 6  "author": "Sammy the Shark <[email protected]>",
 7  "license": "MIT",
 8  "main": "app.js",
 9  "keywords": [
10    "nodejs",
11    "bootstrap",
12    "express"
13  ],
14  "dependencies": {
15    "express": "^4.16.4"
16  }
17}

这个文件包括项目名称,作者和许可证,它是共享的。 Npm recommends使你的项目名称简短和描述性,并避免重复在 npm注册表. 我们已经列出了 MIT许可证在许可证领域,允许免费使用和分发应用程序代码。

此外,该文件规定:

  • 主要:应用程序的入口点, app.js. 您将创建这个文件接下来. * 依赖: 项目依赖 - 在这种情况下, Express 4.16.4 或以上。

虽然这个文件没有列出一个存储库,但你可以通过遵循这些指南来添加一个存储库(https://docs.npmjs.com/files/package.json# repository)。

保存并关闭文件,当您完成更改时。

若要安装项目的依赖,请运行以下命令:

1npm install

这将安装您在项目目录中列出的package.json文件中的包。

现在我们可以继续构建应用程序文件。

步骤2 - 创建应用文件

我们将创建一个网站,为用户提供关于鲨鱼的信息. 我们的应用程序将有一个主要入口点,app.js,以及一个包含项目静态资产的视图目录。 登陆页面,index.html,将为用户提供一些初步信息,并链接到一个具有更详细鲨鱼信息的页面,sharks.html。

首先,在主项目目录中打开app.js,以定义项目的路线:

1nano app.js

文件的第一个部分将创建 Express 应用程序和路由器对象,并将基础目录和端口定义为常数:

1[label ~/node_project/app.js]
2const express = require('express');
3const app = express();
4const router = express.Router();
5
6const path = __dirname + '/views/';
7const port = 8080;

要求函数加载了快递模块,然后我们使用它来创建应用路由器对象. 路由器对象将执行应用程序的路由功能,当我们定义HTTP方法路径时,我们将将它们添加到该对象中来定义我们的应用程序将如何处理请求。

该文件的这个部分还设置了一对常数,‘path’和‘port’:

  • path: 定义基础目录,该目录将是当前项目目录中的 view 子目录. * port: 告诉应用程序倾听并连接到 8080 端口。

接下来,使用路由器对象为应用程序设置路径:

 1[label ~/node_project/app.js]
 2...
 3
 4router.use(function (req,res,next) {
 5  console.log('/' + req.method);
 6  next();
 7});
 8
 9router.get('/', function(req,res){
10  res.sendFile(path + 'index.html');
11});
12
13router.get('/sharks', function(req,res){
14  res.sendFile(path + 'sharks.html');
15});

),该函数会记录路由器的请求并将其传递到应用程序的路径上。这些函数在后续函数中定义,这些函数规定,向基础项目 URL 发送的 GET 请求应返回 index.html 页面,而向 /sharks 路径发送的 GET 请求应返回 sharks.html

最后,安装路由器中间件和应用程序的静态资产,并告诉应用程序在端口8080上倾听:

1[label ~/node_project/app.js]
2...
3
4app.use(express.static(path));
5app.use('/', router);
6
7app.listen(port, function () {
8  console.log('Example app listening on port 8080!')
9})

完成的「app.js」檔案將看起來像這樣:

 1[label ~/node_project/app.js]
 2const express = require('express');
 3const app = express();
 4const router = express.Router();
 5
 6const path = __dirname + '/views/';
 7const port = 8080;
 8
 9router.use(function (req,res,next) {
10  console.log('/' + req.method);
11  next();
12});
13
14router.get('/', function(req,res){
15  res.sendFile(path + 'index.html');
16});
17
18router.get('/sharks', function(req,res){
19  res.sendFile(path + 'sharks.html');
20});
21
22app.use(express.static(path));
23app.use('/', router);
24
25app.listen(port, function () {
26  console.log('Example app listening on port 8080!')
27})

保存并关闭文件,当你完成。

接下来,让我们在应用程序中添加一些静态内容,开始创建视图目录:

1mkdir views

打开登陆页文件,index.html:

1nano views/index.html

将下列代码添加到文件中,将导入 Boostrap 并创建一个 jumbotron 组件,链接到更详细的 sharks.html 信息页面:

 1[label ~/node_project/views/index.html]
 2<!DOCTYPE html>
 3<html lang="en">
 4
 5<head>
 6    <title>About Sharks</title>
 7    <meta charset="utf-8">
 8    <meta name="viewport" content="width=device-width, initial-scale=1">
 9    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
10    <link href="css/styles.css" rel="stylesheet">
11    <link href="https://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css">
12</head>
13
14<body>
15    <nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md">
16        <div class="container">
17            <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
18            </button> <a class="navbar-brand" href="#">Everything Sharks</a>
19            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
20                <ul class="nav navbar-nav mr-auto">
21                    <li class="active nav-item"><a href="/" class="nav-link">Home</a>
22                    </li>
23                    <li class="nav-item"><a href="/sharks" class="nav-link">Sharks</a>
24                    </li>
25                </ul>
26            </div>
27        </div>
28    </nav>
29    <div class="jumbotron">
30        <div class="container">
31            <h1>Want to Learn About Sharks?</h1>
32            <p>Are you ready to learn about sharks?</p>
33            <br>
34            <p><a class="btn btn-primary btn-lg" href="/sharks" role="button">Get Shark Info</a>
35            </p>
36        </div>
37    </div>
38    <div class="container">
39        <div class="row">
40            <div class="col-lg-6">
41                <h3>Not all sharks are alike</h3>
42                <p>Though some are dangerous, sharks generally do not attack humans. Out of the 500 species known to researchers, only 30 have been known to attack humans.
43                </p>
44            </div>
45            <div class="col-lg-6">
46                <h3>Sharks are ancient</h3>
47                <p>There is evidence to suggest that sharks lived up to 400 million years ago.
48                </p>
49            </div>
50        </div>
51    </div>
52</body>
53
54</html>

这里的顶级 navbar允许用户在 Home 和** Sharks** 页面之间切换。在navbar-nav子组件中,我们正在使用 Bootstrap 的活跃类来向用户表示当前页面。我们还指定了通往我们的静态页面的路线,这些路线与我们在app.js中定义的路线相匹配:

 1[label ~/node_project/views/index.html]
 2...
 3<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
 4   <ul class="nav navbar-nav mr-auto">
 5      <li class="active nav-item"><a href="/" class="nav-link">Home</a>
 6      </li>
 7      <li class="nav-item"><a href="/sharks" class="nav-link">Sharks</a>
 8      </li>
 9   </ul>
10</div>
11...

此外,我们在jumbotron的按钮中创建了链接到我们的鲨鱼信息页面:

 1[label ~/node_project/views/index.html]
 2...
 3<div class="jumbotron">
 4   <div class="container">
 5      <h1>Want to Learn About Sharks?</h1>
 6      <p>Are you ready to learn about sharks?</p>
 7      <br>
 8      <p><a class="btn btn-primary btn-lg" href="/sharks" role="button">Get Shark Info</a>
 9      </p>
10   </div>
11</div>
12...

还有链接到标题中的自定义风格表:

1[label ~/node_project/views/index.html]
2...
3<link href="css/styles.css" rel="stylesheet">
4...

我们将在本步骤结束时创建此风格表。

保存并关闭文件,当你完成。

有了应用的登陆页面,我们可以创建我们的鲨鱼信息页面,‘sharks.html’,它将为感兴趣的用户提供更多关于鲨鱼的信息。

打开文件:

1nano views/sharks.html

添加以下代码,导入 Bootstrap 和自定义风格表,并为用户提供有关某些鲨鱼的详细信息:

 1[label ~/node_project/views/sharks.html]
 2<!DOCTYPE html>
 3<html lang="en">
 4
 5<head>
 6    <title>About Sharks</title>
 7    <meta charset="utf-8">
 8    <meta name="viewport" content="width=device-width, initial-scale=1">
 9    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
10    <link href="css/styles.css" rel="stylesheet">
11    <link href="https://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css">
12</head>
13<nav class="navbar navbar-dark bg-dark navbar-static-top navbar-expand-md">
14    <div class="container">
15        <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
16        </button> <a class="navbar-brand" href="/">Everything Sharks</a>
17        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
18            <ul class="nav navbar-nav mr-auto">
19                <li class="nav-item"><a href="/" class="nav-link">Home</a>
20                </li>
21                <li class="active nav-item"><a href="/sharks" class="nav-link">Sharks</a>
22                </li>
23            </ul>
24        </div>
25    </div>
26</nav>
27<div class="jumbotron text-center">
28    <h1>Shark Info</h1>
29</div>
30<div class="container">
31    <div class="row">
32        <div class="col-lg-6">
33            <p>
34                <div class="caption">Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
35                </div>
36                <img src="https://cdn.jsdelivr.net/gh/andsky/tutorials-images/assets/docker_node_image/sawshark.jpg" alt="Sawshark">
37            </p>
38        </div>
39        <div class="col-lg-6">
40            <p>
41                <div class="caption">Other sharks are known to be friendly and welcoming!</div>
42                <img src="https://cdn.jsdelivr.net/gh/andsky/tutorials-images/assets/docker_node_image/sammy.png" alt="Sammy the Shark">
43            </p>
44        </div>
45    </div>
46</div>
47
48</html>

请注意,在此文件中,我们再次使用活跃类来表示当前的页面。

保存并关闭文件,当你完成。

最后,创建您在index.htmlsharks.html中链接的自定义 CSS 风格表,首先在视图目录中创建一个css文件夹:

1mkdir views/css

打开风格页面:

1nano views/css/styles.css

添加以下代码,将为我们的页面设置所需的颜色和字体:

 1[label ~/node_project/views/css/styles.css]
 2.navbar {
 3    margin-bottom: 0;
 4}
 5
 6body {
 7    background: #020A1B;
 8    color: #ffffff;
 9    font-family: 'Merriweather', sans-serif;
10}
11
12h1,
13h2 {
14    font-weight: bold;
15}
16
17p {
18    font-size: 16px;
19    color: #ffffff;
20}
21
22.jumbotron {
23    background: #0048CD;
24    color: white;
25    text-align: center;
26}
27
28.jumbotron p {
29    color: white;
30    font-size: 26px;
31}
32
33.btn-primary {
34    color: #fff;
35    text-color: #000000;
36    border-color: white;
37    margin-bottom: 5px;
38}
39
40img,
41video,
42audio {
43    margin-top: 20px;
44    max-width: 80%;
45}
46
47div.caption: {
48    float: left;
49    clear: both;
50}

除了设置字体和颜色外,该文件还通过指定最大宽度为80%来限制图像的大小,这将防止它们占用比我们希望的页面更多的空间。

保存并关闭文件,当你完成。

有了应用程序文件并安装了项目依赖,您已经准备好启动应用程序。

如果您遵循初始服务器设置教程的先决条件,您将有一个活跃的防火墙,只允许SSH流量。

1sudo ufw allow 8080

要启动应用程序,请确保您位于项目的根目录:

1cd ~/node_project

使用node app.js启动应用程序:

1node app.js

请导航您的浏览器到 http://your_server_ip:8080. 您将加载以下目的地页面:

Application Landing Page

点击获取鲨鱼信息按钮,下面的信息页面将加载:

Shark Info Page

当您准备好时,请通过键入CTRL+C离开服务器,我们现在可以继续创建Dockerfile,这将使我们能够根据需要重新创建和扩展该应用程序。

步骤 3 – 编写 Dockerfile

您的 Dockerfile 指定了在执行时将包含在应用程序容器中的内容。 使用 Dockerfile 可以定义您的容器环境,并避免与依赖或运行时版本的差异。

按照这些关于构建优化容器的指南(https://andsky.com/tech/tutorials/building-optimized-containers-for-kubernetes),我们将通过最大限度地减少图像层的数量并将图像的功能限制在一个目的 - 重现我们的应用程序文件和静态内容。

在项目的根目录中,创建 Dockerfile:

1nano Dockerfile

Docker 图像是使用一系列相互依赖的层次图像创建的,我们的第一步是为我们的应用程序添加 base image 来构建应用程序构建的起点。

让我们使用'Node:10-alpine' image,因为在编写本报告时,这是[推荐的LTS版Node.js (https://nodejs.org/en/). " 高山 " 图像取自高山Linux项目,将帮助我们降低图像大小。 关于`阿尔卑斯山'图像是否是您项目的正确选择的更多信息,请在[Docker Hub Conte 图像页] (https://hub.docker.com/_/node/) Image Variats 一节下回顾全部讨论.

添加以下指令来设置应用程序的基本图像:

1[label ~/node_project/Dockerfile]
2FROM node:10-alpine

此图像包括 Node.js 和 npm. 每个 Dockerfile 都必须以FROM 命令开始。

默认情况下,多克节点图像包括一个可以用来避免以root 运行应用程序容器的非root** node ** 用户. 建议采用的一种安全做法是避免作为** root** 运行集装箱,并限制集装箱内的能力仅限于运行其程序所需的能力。 因此,我们将使用** 节点** 用户的家目录作为我们应用程序的工作目录,并将它们设定为容器内的用户。 关于与多克节点图像合作时的最佳做法的更多信息,请检查此[最佳做法指南] (https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md).

为了在容器中优化我们应用程序代码的权限,让我们在/home/node中创建node_modules子目录,以及app目录。创建这些目录将确保它们具有我们想要的权限,这在我们创建npm install容器中的本地节点模块时很重要。

1[label ~/node_project/Dockerfile]
2...
3RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app

有关整合)。

接下来,将应用程序的工作目录设置为 /home/node/app:

1[label ~/node_project/Dockerfile]
2...
3WORKDIR /home/node/app

如果没有设置WORKDIR,Docker 将默认创建一个,所以明确设置它是很好的想法。

接下来,复制):

1[label ~/node_project/Dockerfile]
2...
3COPY package*.json ./

在运行npm install或复制应用程序代码之前添加此COPY指令,使我们能够利用Docker的缓存机制。在构建的每个阶段,Docker会检查它是否有用于该特定指令的缓存层。

要确保所有应用程序文件都属于非根 node 的用户,包括node_modules目录的内容,请在运行npm install之前将用户切换为node** :

1[label ~/node_project/Dockerfile]
2...
3USER node

复制项目依赖并切换我们的用户后,我们可以运行npm install:

1[label ~/node_project/Dockerfile]
2...
3RUN npm install

接下来,将您的应用程序代码与相应的权限复制到容器上的应用程序目录:

1[label ~/node_project/Dockerfile]
2...
3COPY --chown=node:node . .

这将确保应用程序文件由非 root node 用户拥有。

最后,将端口8080暴露在容器上,并启动应用程序:

1[label ~/node_project/Dockerfile]
2...
3EXPOSE 8080
4
5CMD [ "node", "app.js" ]

「EXPOSE」不會發布端口,而是用來記錄容器上的哪個端口會在執行時間發布。「CMD」執行啟動應用程式的命令,在這種情況下, node app.js. 請注意,每個Dockerfile中只應該有一個「CMD」指令。

您可以使用 Dockerfile 做很多事情,如需完整的指示列表,请参阅 Docker 的 Dockerfile 参考文档

完整的Dockerfile看起来像这样:

 1[label ~/node_project/Dockerfile]
 2
 3FROM node:10-alpine
 4
 5RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
 6
 7WORKDIR /home/node/app
 8
 9COPY package*.json ./
10
11USER node
12
13RUN npm install
14
15COPY --chown=node:node . .
16
17EXPOSE 8080
18
19CMD [ "node", "app.js" ]

保存并关闭文件,当你完成编辑。

在构建应用程序图像之前,让我们添加一个 .dockerignore 文件. 与 .gitignore 文件相似的方式工作, .dockerignore 指定您项目目录中的哪些文件和目录不应该被复制到您的容器中。

打开.dockerignore 文件:

1nano .dockerignore

在文件中,添加本地节点模块、npm 日志、Dockerfile 和.dockerignore 文件:

1[label ~/node_project/.dockerignore]
2node_modules
3npm-debug.log
4Dockerfile
5.dockerignore

如果你正在使用 Git那么你也想添加你的 .git 目录和 .gitignore 文件。

保存并关闭文件,当你完成。

您现在准备使用 ['docker building' (https://docs.docker.com/engine/reference/commandline/build/]] 命令构建应用程序图像 。 使用 " t " 旗并用 " docker building " 使您能够用难忘的名字来标记图像。 因为我们要把图像推到Docker Hub, 让我们在标签中加入我们的Docker Hub用户名。 我们将把这个形象贴上nodejs-image-demo'的标签,但可以自行取而代之。 请记住将你的_dockkerhub_username`替换为自己的多克枢纽用户名:

1sudo docker build -t your_dockerhub_username/nodejs-image-demo .

. 指明构建背景是当前目录。

它需要一两分钟才能构建图像.一旦完成,请检查您的图像:

1sudo docker images

您将获得以下输出:

1[secondary_label Output]
2REPOSITORY TAG IMAGE ID CREATED SIZE
3your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 8 seconds ago 73MB
4node 10-alpine f09e7c96b6de 3 weeks ago 70.7MB

现在可以使用 docker run创建此图像的容器)。

  • 联合国 `-p': 这公布集装箱上的港口,并将其映射到我们东道主的港口. 我们将在主机上使用 " 80 " 号口,但如果在该口上运行另一个程序,你应随意修改。 欲了解如何运作,请在关于[港 的Docker文件(https://docs.docker.com/v17.09/engine/userguide/networking/default_network/binding/)中回顾这一讨论。
  • 联合国 `-d': 这个在背景中运行容器 。
  • `姓名 ' : 这让我们可以给容器一个难忘的名字. .

运行以下命令来构建容器:

1sudo docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

一旦您的容器启动并运行,您可以通过 [docker ps] 检查运行容器的列表(https://docs.docker.com/engine/reference/commandline/ps/):

1sudo docker ps

您将获得以下输出:

1[secondary_label Output]
2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3e50ad27074a7 your_dockerhub_username/nodejs-image-demo               "node app.js"       8 seconds ago Up 7 seconds 0.0.0.0:80->8080/tcp nodejs-image-demo

随着容器运行,您现在可以通过导航浏览器到您的服务器IP而访问您的应用程序,而无需端口:

1http://your_server_ip

您的应用程序登陆页面将再次加载。

Application Landing Page

现在你已经为你的应用程序创建了一个图像,你可以将其推到Docker Hub,以便在未来使用。

步骤4 — 使用存储库与图像工作

通过将您的应用程序图像推到Docker Hub等注册表中,您将其提供给后续使用,当您构建和扩展您的容器时。

推动图像的第一步是登录您在前提条件下创建的 Docker Hub 帐户:

1sudo docker login -u your_dockerhub_username

当被提示时,请输入您的 Docker Hub 帐户密码. 以此方式登录将创建一个 ~/.docker/config.json 文件,在您的用户主目录中与您的 Docker Hub 凭证。

现在,您可以使用您之前创建的标签,‘your_dockerhub_username/nodejs-image-demo’将应用程序图像推到 Docker Hub:

1sudo docker push your_dockerhub_username/nodejs-image-demo

让我们通过摧毁我们当前的应用程序容器和图像来测试图像注册表的实用性,并用我们库中的图像重建它们。

首先,列出您的运行容器:

1sudo docker ps

你会得到以下的输出:

1[secondary_label Output]
2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3e50ad27074a7 your_dockerhub_username/nodejs-image-demo   "node app.js"       3 minutes ago Up 3 minutes 0.0.0.0:80->8080/tcp nodejs-image-demo

使用输出中列出的CONTAINER ID,停止运行应用程序容器. 请确保以自己的CONTAINER ID替换下面的突出ID:

1sudo docker stop e50ad27074a7

列出你的所有图像与-a旗帜:

1docker images -a

您将收到以下输出和您的图像的名称, your_dockerhub_username/nodejs-image-demo,以及您的构建中的节点图像和其他图像:

 1[secondary_label Output]
 2REPOSITORY TAG IMAGE ID CREATED SIZE
 3your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 7 minutes ago 73MB
 4<none>                                               <none>              2e3267d9ac02 4 minutes ago 72.9MB
 5<none>                                               <none>              8352b41730b9 4 minutes ago 73MB
 6<none>                                               <none>              5d58b92823cb 4 minutes ago 73MB
 7<none>                                               <none>              3f1e35d7062a 4 minutes ago 73MB
 8<none>                                               <none>              02176311e4d0 4 minutes ago 73MB
 9<none>                                               <none>              8e84b33edcda 4 minutes ago 70.7MB
10<none>                                               <none>              6a5ed70f86f2 4 minutes ago 70.7MB
11<none>                                               <none>              776b2637d3c1 4 minutes ago 70.7MB
12node 10-alpine f09e7c96b6de 3 weeks ago 70.7MB

使用以下命令删除已停止的容器和所有图像,包括未使用或悬浮的图像:

1docker system prune -a

在输出中提示时键入y,以确认您希望删除已停止的容器和图像。

您现在已经删除了运行您的应用程序图像的容器和图像本身。 有关删除 Docker 容器、图像和卷的更多信息,请查看 如何删除 Docker 图像、容器和卷

删除所有图像和容器后,您现在可以从 Docker Hub 提取应用程序图像:

1docker pull your_dockerhub_username/nodejs-image-demo

再次列出你的图片:

1docker images

您的输出将有您的应用图像:

1[secondary_label Output]
2REPOSITORY TAG IMAGE ID CREATED SIZE
3your_dockerhub_username/nodejs-image-demo latest 1c723fb2ef12 11 minutes ago 73MB

您现在可以使用步骤 3 的命令重建您的容器:

1docker run --name nodejs-image-demo -p 80:8080 -d your_dockerhub_username/nodejs-image-demo

列出您的运行容器:

1docker ps
1[secondary_label Output]
2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3f6bc2f50dff6 your_dockerhub_username/nodejs-image-demo               "node app.js"       4 seconds ago Up 3 seconds 0.0.0.0:80->8080/tcp nodejs-image-demo

再次访问http://your_server_ip,查看正在运行的应用程序。

结论

在本教程中,您创建了一个静态的Web应用程序,使用Express和Bootstrap,以及这个应用程序的Docker图像。您使用这个图像创建一个容器,并将图像推到Docker Hub。

如果您有兴趣了解如何使用 Docker Compose 和 Docker Machine 等工具创建多容器设置,请参阅以下指南:

有关处理集装箱数据的一般提示,请参阅:

如果您对其他与 Docker 相关的主题感兴趣,请找到我们的完整库 Docker 教程

Published At
Categories with 技术
comments powered by Disqus