Skip to content

Latest commit

 

History

History

image

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

使用 Docker 构建一个容器应用(一)

Docker 是一个可以将应用容器化的工具,可以简单的把容器理解为一个和羽毛一样轻的虚拟机,和传统的虚拟机不同,它并不会给系统带来太大的负担,并且有更高的可移植性和扩展性。在容器中应用将享有独立的文件系统,容器内的操作将不会影响到自身的主机系统,有点类似于三体中的小宇宙空间,在里面可以有高度的自由操作空间,并且已经预设了你喜欢的装修风格(应用运行所需的环境)!

我们将使用 Docker 来搭建一个最简单的 Node 容器化应用,这个镜像将会被我们打包,上传到自己的 Docker 仓库,并且可以开箱即用。想象这么一个场景,你的开发机器将这个应用进行容器化以后,在自己的服务器上将这个容器化的镜像下载后,使用一个命令就可以使你的应用在另一个完全不同的环境运行起来,节约下来的这些时间可以让我们做更多自己喜欢的事情,而不是钻研一个我们可能搞不定的 “Linux 环境问题”!

第一步:下载并安装 Docker

下载地址,希望这一步没有难倒你。

第二步:编写一个简单的 Node 应用

为了保持足够简单,我使用了 Express,它只有一个功能,在主页输出一个 Hello Docker,如果你对此有疑惑,可以参考 源码仓库,也可以参考下面的代码:

const express = require('express');

const app = express();

app.get("/", (req, res) => {
  res.end("Hello Docker!")
});

app.listen(8000, () => {
  console.log("server is starting in http:https://localhost:8000");
});

保险起见,我们最好使用 node app.js 测试一下这个应用是健康的,启动后浏览器打开 http:https://localhost:8000,我们可以顺利看到 Hello Docker! 被输出在屏幕上,看来一切在朝着我们期望的方向发展着。

第三步:将 Node 应用装箱打包成镜像

这一步可能会接触到你的知识盲区了,所以我们用一个比较简单轻松的风格来剖析每一步需要做的事情,将复杂的事情分解成多个简单的步骤,这是我们解决复杂问题的一贯方式。

我们在应用的同级目录下新建一个 Dockerfile 文件,让这个记录员帮我们记录我们接下来要做的事情。你的目录应该看起来跟我的基本一致:

目录结构

我们的应用需要什么?

我们第一个需要思考的问题是,我们的应用需要什么,我们可能知道,它需要一台计算机来运行,这个倒是不用担心,Docker 也需要计算机,它能有的我们都可以有。那我们的应用还需要什么呢,众所周知,Docker 是用 Go 语言实现的,那他会有 Node 的运行环境吗?

不,它没有,所以我们第一步是构建一个支持 Node 应用运行的环境,那我们就需要先在这个容器中放进去一个 Node,怎么放进去呢,一个简单的命令就可以了,在 Dockerfile 中新增一行:

# 这句命令的作用是让我们的镜像在 node:10.16-alpine 镜像的基础上开始
# alpine 的包会比较小一点,功能也会少一点,但是已经可以满足我们的需求了
# 站在巨人的肩膀上
FROM node:10.16-alpine

我们需要在容器里做什么?

我们的记录员 Dockerfile 已经帮我们记录了第一步要做的事情,我们可以在第一步的基础上思考第二步要做的事情了。

在前面我们提到过,在容器中有一个自己的小宇宙,这个小宇宙虽然我们不常来,但是我们也应该希望它能够和大宇宙一样井井有条,所以呢,我们要在这个容器单独的文件系统中指定一个工作目录,以便我们将来能够在容器中尽快找到我们的应用,所以让我们的记录员加上一句:

# 这句命令的作用是指定应用在容器中的工作目录
# 为我们的应用找到了一个干净的房间,它将在这里开始它的一生
WORKDIR /usr/src/app

指定了工作目录之后,我们希望把我们的应用在里面运行,这一步我们需要把我们的核心 app.js 挪到我们在 docker 中的工作目录中,一般来说我们会将整个应用放进去,所以我们需要加上一句命令:

COPY . .

这样就可以了吗?如果你熟悉 Node 项目的话,你就会知道把所有文件都挪进去是不太明智的,至少要把 node_modules 留下,我们不需要亲自将这个“庞大笨重的机器”艰难的挪进去,我们只需要放进去“芯片(app.js)”和“使用说明(package.json)”就可以了,然后让我们的 docker 容器完成对依赖的安装。

所以我们在当前目录下新建一个 .dockerignore 文件,填入 node_modules,就像 .gitignore 那样!

既然我们已经把应用放进了容器,那么我们只需要像运行一个普通 Node 项目那样运行我们的项目就可以了,回忆一下,我们怎么运行我们的 Node 项目呢?第一步安装依赖,第二步 Run it!

那我们需要在 package.json 中的 script 选项中加入一行 "start": "node app.js",为我们的项目指定一个启动入口。然后我们就可以让记录员记录最后的两句命令了:

# 安装依赖
RUN npm install

# 定义应用的启动指令
CMD [ "npm", "start" ]

最终的完整版应该是这样的:

FROM node:10.16-alpine

WORKDIR /usr/src/app
COPY . .
RUN npm install

CMD [ "npm", "start" ]

怎么将我们的应用打包成 Docker 镜像?

进入你的项目目录,运行一行命令

# 根据 Dockerfile 配置文件信息将应用打包成镜像
# 执行记录员记录的所有命令
docker image build -t myapp:1.0 .

在打包完成后,我们用 docker image ls 命令来看看这孩子长啥样

myapp 镜像文件

它只有 79.6M,相对于一个 VM 系统来说,它轻的像一根羽毛,而且还可以更小!

运行你的 Docker 容器!

实践是检验真理的唯一标准,我们来测试一下我们的容器,它能跑吗?

(如果你想要模拟在另一台电脑上运行,此刻你可以重启电脑了,重启后你得到的将会是一台全新的电脑!)

我们现在使用一行命令来运行我们的容器:

docker container run --publish 8888:8000 --detach --name app myapp:1.0

在打开浏览器之前,我们先剖析一下上面的这行命令:

  • docker container run: 运行一个 docker 容器
  • --publish: 将主机上的 8888 端口所接收的网络流量转发到容器内部的 8000 端口处理;(我们容器内的 8000 端口上运行着我们的应用)
  • --detach: 在后台运行这个容器;
  • --name: 为你的容器指定一个名称,以便你区分不同的容器;

解析完成后,我们此刻应该信心百倍,打开浏览器,输入 http:https://localhost:8888,我们成功了!

它来了

原文地址,欢迎收录

源码地址,欢迎收录