当前位置: 首页 > news >正文

[Node + Docker] 聊聊怎么把 nodeclub 构建成 Docker 镜像

14年毕业后开始接触node,15年来帝都找了份工作,一直默默的在cnode社区晃悠,灌过几次水,今天就想发个处女贴,跟大家聊聊怎么把nodeclub项目源码构建成一个镜像。话说Docker是今年刚接触的,还在入门中/(ㄒoㄒ)/~~,下面我简单介绍下Docker、Dockerfile的语法以及如何把nodeclub源码构建成镜像。(已经对Docker比较熟悉的小伙伴可以直接跳到第三个)

1.什么是docker?

Docker allows you to package an application with all of its dependencies into a standardized unit for software development.
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架包括系统。

Docker 的目标是实现轻量级的操作系统虚拟化解决方案。Docker 的基础是 Linux 容器(LXC)等技术。在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。

下面的图片比较了 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。
container-1024x510.png
(图片来自Docker官方网站)

2.Dockerfile简单入门

Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands you would normally execute manually in order to build a Docker image. By calling docker build from your terminal, you can have Docker build your image step by step, executing the instructions successively.
Docker通过读取Dockerfile文件中的指令自动构建镜像。Dcokerfile是一个文本文件,它包含了构建镜像所需要执行的全部命令。执行docker build命令,Docker就会按照文档执行并最终创建一个镜像。(这段话是翻译上面那段话的%>_<%)。 Dockerfile支持支持的语法命令如下:

INSTRUCTION argument

指令不区分大小写。但是,命名约定为全部大写。
Dockerfile都必须以FROM命令开始。 FROM命令会指定镜像基于哪个基础镜像创建,接下来的命令也会基于这个基础镜像(译者注:CentOS和Ubuntu有些命令可是不一样的)。FROM命令可以多次使用,表示会创建多个镜像。具体语法如下:

FROM <image name>

例如:

FROM google/nodejs

上面的指令告诉我们,新的镜像将基于google的Node.js的镜像来构建。

继FROM命令,DockefFile还提供了一些其它的命令以实现自动化。在Dockerfile文件中这些命令的顺序就是它们被执行的顺序。 下面我们就了解下这些有趣的Dockerfile命令吧。 1.MAINTAINER:设置该镜像的作者。语法如下:

MAINTAINER <author name>

2.RUN:在shell或者exec的环境下执行的命令。RUN指令会在新创建的镜像上添加新的层面,接下来提交的结果用在Dockerfile的下一条指令中。语法如下:

RUN <command>

3.ADD:复制文件指令。它有两个参数和。destination是容器内的路径。source可以是URL或者是启动配置上下文中的一个文件。语法如下:

ADD <src> <destination>

4.CMD:提供了容器默认的执行命令。 Dockerfile只允许使用一次CMD指令。 使用多个CMD会抵消之前所有的指令,只有最后一个指令生效。 CMD有三种形式:

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1

5.EXPOSE:指定容器在运行时监听的端口。语法如下:

EXPOSE <port>;

6.ENTRYPOINT:配置给容器一个可执行的命令,这意味着在每次使用镜像创建容器时一个特定的应用程序可以被设置为默认程序。同时也意味着该镜像每次被调用时仅能运行指定的应用。类似于CMD,Docker只允许一个ENTRYPOINT,多个ENTRYPOINT会抵消之前所有的指令,只执行最后的ENTRYPOINT指令。语法如下:

ENTRYPOINT ["executable", "param1","param2"]
ENTRYPOINT command param1 param2

7.WORKDIR:指定RUN、CMD与ENTRYPOINT命令的工作目录。语法如下:

WORKDIR /path/to/workdir

8.ENV:设置环境变量。它们使用键值对,增加运行程序的灵活性。语法如下:

ENV <key> <value>

9.USER:镜像运行时,设置一个UID。语法如下:

USER <uid>

10.VOLUME:授权访问从容器内到主机上的目录。语法如下:

VOLUME ["/data"]

3. 把nodeclub构建成一个镜像

先把我写的Dockerfile贴出来:

# Dockerfile to create a nodeclub image
FROM google/nodejs
MAINTAINER Carrotzpc

# Add files to the image
RUN mkdir -p /opt/nodejs
ADD . /opt/nodejs
WORKDIR /opt/nodejs

# Install the dependencies modules
RUN npm install

# Run make build
RUN make build

# Expose environment variables
ENV MONGO_CARROT_ADDR **LinkMe**
ENV MONGO_CARROT_PORT **LinkMe**
ENV MONGO_CARROT_DATABASE admin
ENV MONGO_CARROT_USER **ChangeMe**
ENV MONGO_CARROT_PASS **ChangeMe**

# Expose the container port
EXPOSE 5000

ENTRYPOINT ["node", "app.js"]

这么简单的几行命令,就可以构建出一个nodeclub镜像。下面我重点聊一下环境变量ENV,nodeclub的源码我用的是node + mongo(无redis)的版本,mongo配置信息通过环境变量传递,这就需要我们简单修改一下nodeclub的配置文件,我在配置文件中增加了以下代码(不过直接在配置文件里边这样写不太好),用来获取mongo数据库连接字符串:

// Get mongodb connec string from env
function _getMongoUrl(){
  var db_addr = process.env.MONGO_CARROT_ADDR;
  var db_port = process.env.MONGO_CARROT_PORT;
  var db_user = process.env.MONGO_CARROT_USER;
  var db_pass = process.env.MONGO_CARROT_PASS;
  var db_database =  process.env.MONGO_CARROT_DATABASE;
  var db_url  = 'mongodb://';
  if (db_user && db_pass) {
    db_url += (db_user + ':' + db_pass + '@');
  }
  db_url += (db_addr? db_addr: 'localhost');
  db_url += ':' + (db_port? db_port: 27017);
  db_url += '/' + (db_database? db_database: 'admin');
  console.log('Connect to MongoStore Use this url:' + db_url);
  return db_url;
}

(不知道还有木有童鞋有耐心看到这里)到这里我们完成了源码的修改,其中Dockerfile是放在源代码根目录的。现在可以开始构建nodeclub镜像了,Windows安装Docker比较蛋疼,我本地没有安装Docker环境,我用的是TenxCloud时速云的本地客户端tce,安装配置都比较简单,这里就不说了,大家可以参考官方文档。 在命令行中输入tce login填写用户名、密码后完成登录,然后进入到源代码根目录,执行tce push nodeclub命令,tce会自动将Dockerfile及引用的本地文件打包成zip,并上传到TenxCloud,由TenxCloud的容器引擎构建Docker 镜像,我们可以看到Docker构建镜像的相关日志:

1f1e08ca27ed71469636105676067cb2.png

完成构建后打开时速云网站,进入镜像市场>我的镜像就可以看到我们刚刚构建的镜像nodeclub:

8d5eac3c8b8800ae5196cccb24a6ef3f-1024x352.png

在镜像详情页可以上传镜像图标、修改镜像信息、服务接口等,我们把Dockerfile中的ENV增加到服务接口中,用于在部署镜像时填写mongo的相关配置信息:

84d542485b07aa05892681cf4b329d75.png

万事具备,只欠一个mongo了,正好时速云有提供mongo的镜像,于是我部署了一个mongo,然后在部署nodeclub时填写这个mongo的地址、端口等信息,这样就完成了nodeclub的部署:

22456ab3cc99c8daacdbcfa6b61a1713-1024x487.png

还有一种方式就是把mongo也集成到我们的镜像中,这就涉及到了mongo的安装以及启动,我们留在下一次讨论。我把源代码上传到了github,大家有兴趣的话可以自己构建试试:

还有一种方式就是把mongo也集成到我们的镜像中,这就涉及到了mongo的安装以及启动,我们留在下一次讨论。我把源代码上传到了github,大家有兴趣的话可以自己构建试试:https://github.com/Carrotzpc/docker-nodeclub。

示例网站:http://nodeclub-k9nmf.q1.tenxcloud.net:46141/。

PS:由于部署镜像前host并不可知,所以我把源码改成了通过req.headers.host来获取host,这样激活邮件中的链接就可用了。

参考资料

  • what is docker ?
  • 什么是容器服务(Container as a Service)
  • Dockerfile reference
  • Docker入门教程(三)Dockerfile
  • google / nodejs
  • How to use MongoDB & NodeJS with Docker (video included)
  • 使用 tce 客户端

相关文章:

  • AS3编码规范(转)
  • 我的Android进阶之旅------ListView中android:cacheColorHint,android:listSelector属性作用 .
  • 技术人员在客户现场工作的注意事项
  • HDU 1520 Anniversary party
  • Android 计时应用 之 爱相随 V0.25
  • 杭电3790--最短路径问题(双权Dijkstra)
  • iostream迭代器的使用(11.18)
  • delphi 图像处理 二值化
  • 6个简单的解决方案解决Internet Explorer中的透明度问题
  • Atom飞行手册翻译: 3.5 创建主题
  • RMAN的基本概念和常用命令
  • 《go语言程序设计》学习(七)
  • Android NDK revision 7 Host 'awk' tool is outda...
  • VLAN的Hybrid和Trunk端口有何区别
  • 运行时库链接错误的修复方法
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • [译] React v16.8: 含有Hooks的版本
  • 【5+】跨webview多页面 触发事件(二)
  • 【前端学习】-粗谈选择器
  • angular组件开发
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • Java方法详解
  • JS基础之数据类型、对象、原型、原型链、继承
  • React中的“虫洞”——Context
  • Ruby 2.x 源代码分析:扩展 概述
  • SpriteKit 技巧之添加背景图片
  • TCP拥塞控制
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 分类模型——Logistics Regression
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 记一次删除Git记录中的大文件的过程
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 前端学习笔记之观察者模式
  • 如何解决微信端直接跳WAP端
  • 新书推荐|Windows黑客编程技术详解
  • 学习HTTP相关知识笔记
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 主流的CSS水平和垂直居中技术大全
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 翻译 | The Principles of OOD 面向对象设计原则
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (转)Linux整合apache和tomcat构建Web服务器
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .sh文件怎么运行_创建优化的Go镜像文件以及踩过的坑
  • /etc/fstab和/etc/mtab的区别
  • @staticmethod和@classmethod的作用与区别
  • [ 蓝桥杯Web真题 ]-Markdown 文档解析
  • [ 隧道技术 ] 反弹shell的集中常见方式(四)python反弹shell
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [ai笔记4] 将AI工具场景化,应用于生活和工作
  • [Android]Android P(9) WIFI学习笔记 - 扫描 (1)