这个例子的目的是向你展示如何将一个Node.js应用程序放入Docker容器。本指南旨在用于开发,而不是用于生产部署。本指南还假设你有一个工作的Docker安装,并对Node.js应用程序的结构有基本的了解。
在本指南的第一部分,我们将在Node.js中创建一个简单的Web应用程序,然后我们将为该应用程序构建一个Docker镜像,最后我们将从该镜像中实例化一个容器。
Docker允许你将一个应用程序及其环境和所有的依赖关系打包成一个 “盒子”,称为容器。通常情况下,一个容器由一个运行在剥离到基本版本的Linux操作系统中的应用程序组成。一个镜像是一个容器的蓝图,一个容器是一个镜像的运行实例。
首先,创建一个新的目录,所有的文件都在其中。在这个目录中创建一个 package.json
文件,描述你的应用程序及其依赖性:
{
"name": "docker_web_app",
"version": "1.0.0",
"description": "Node.js on Docker",
"author": "First Last <first.last@example.com>",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.16.1"
}
}
用你新建的 package.json
文件,运行 npm install
。如果你使用的是npm 5或更高版本,这将产生一个 package-lock.json
文件,它将被复制到你的Docker镜像中。
然后,创建一个 server.js
文件,定义一个使用Express.js框架的网络应用:
'use strict';
const express = require('express');
// Constants
const PORT = 8080;
const HOST = '0.0.0.0';
// App
const app = express();
app.get('/', (req, res) => {
res.send('Hello World');
});
app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);
在接下来的步骤中,我们将看看你如何使用官方的Docker镜像在Docker容器内运行这个应用。首先,你需要为你的应用程序建立一个Docker镜像。
创建一个名为 Dockerfile
的空文件。
touch Dockerfile
用你喜欢的文本编辑器打开 Dockerfile
我们需要做的第一件事是定义我们要从什么镜像中构建。这里我们将使用Docker Hub提供的最新的LTS(长期支持)版本16的node。
FROM node:16
接下来我们创建一个目录来存放镜像中的应用代码,这将是你的应用的工作目录:
# Create app directory
WORKDIR /usr/src/app
这个镜像已经安装了Node.js和NPM,所以我们需要做的下一件事是使用npm安装你的应用程序的依赖项。请注意,如果你使用的是npm第4版或更早的版本,将不会生成 package-lock.json
文件。
# 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
注意,我们不是复制整个工作目录,而是只复制 package.json
文件。这使我们能够利用缓存的Docker层。bitJudo在这里对此有一个很好的解释。此外,注释中指定的 npm ci
命令,有助于为生产环境提供更快的、可靠的、可重复的构建。你可以在这里阅读更多关于这个的内容。
要在Docker镜像中捆绑你的应用程序的源代码,请使用 COPY
指令:
# Bundle app source
COPY . .
你的应用程序绑定了 8080
端口,所以你将使用 EXPOSE
指令让它被docker守护程序映射:
EXPOSE 8080
最后但并非最不重要的是,使用定义运行时的 CMD
来定义运行你的应用程序的命令。这里我们将使用 node server.js
来启动你的服务器:
CMD [ "node", "server.js" ]
你的Docker文件现在应该看起来像这样:
FROM node:16
# 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 . .
EXPOSE 8080
CMD [ "node", "server.js" ]
在与你的 Dockerfile
相同的目录下创建一个 .dockerignore
文件,内容如下:
node_modules
npm-debug.log
这将防止你的本地模块和调试日志被复制到你的Docker镜像上,并可能覆盖你镜像中安装的模块。
进入存放 Dockerfile
的目录,运行以下命令来构建Docker镜像。-t
标志可以让你标记你的镜像,以便以后使用 docker images
命令更容易找到它:
$ docker build . -t <your username>/node-web-app
你的镜像现在将被Docker列出:
$ docker images
# Example
REPOSITORY TAG ID CREATED
node 16 3b66eb585643 5 days ago
<your username>/node-web-app latest d64d3505b0d2 1 minute ago
用 -d
运行你的镜像,以分离模式运行容器,让容器在后台运行。-p
标志将一个公共端口重定向到容器内的一个私有端口。运行你之前构建的镜像:
$ docker run -p 49160:8080 -d <your username>/node-web-app
打印你的应用程序的输出:
# Get container ID
$ docker ps
# Print app output
$ docker logs <container id>
# Example
Running on http://localhost:8080
如果你需要进入容器内部,你可以使用 exec
命令:
# Enter the container
$ docker exec -it <container id> /bin/bash
为了测试你的应用程序,获取Docker映射的你的应用程序的端口:
$ docker ps
# Example
ID IMAGE COMMAND ... PORTS
ecce33b30ebf <your username>/node-web-app:latest npm start ... 49160->8080
在上面的例子中,Docker将容器内的8080端口映射到你机器上的49160端口。
现在你可以用curl调用你的应用程序(如果需要的话,可以通过以下方式安装:sudo apt-get install curl
):
$ curl -i localhost:49160
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 12
ETag: W/"c-M6tWOb/Y57lesdjQuHeB1P/qTV0"
Date: Mon, 13 Nov 2017 20:53:59 GMT
Connection: keep-alive
Hello world
我们希望这个教程能帮助你在Docker上建立并运行一个简单的Node.js应用程序。
你可以在以下地方找到更多关于Docker和Node.js在Docker上的信息:
Node 官方给的docker化一个node应用教程。
参考链接: