构建自己的docker镜像node.js

学习资源:

构建自己的 Docker 镜像_哔哩哔哩_bilibili

针对其中的一些比较困难的点写篇文章。

以下是对app.js的注释:

复制代码
// 使用 Koa 框架搭建 Node.js 应用的示例代码

// 这两行代码引入了 koa 模块,并创建了一个新的 Koa 应用实例,在node_modules文件夹中已经安装了koa库
// 正常自己创建一个项目时,运行npm install命令后,npm会查看package.json文件,然后下载所有需要的包到node_modules目录中。
// 一般不会分享node_modules文件夹(因为很大),一般会给出package.json文件,使用者自己npm install安装依赖
let Koa = require('koa');
let app = new Koa();

// 引入redis日志库(注释部分)
// const redis = require('redis');
// let rds = redis.createClient({url: "redis://redis:6379"});
// rds.on('connect', ()=> console.log('redis connect ok'))
// rds.connect();

// log4js用于配置日志
let log4js = require('log4js');
// 从log4js.json文件中读取配置信息
log4js.configure('./log4js.json');
// 所有级别为DEBUG或以上的日志都会被记录
log4js.level = 'DEBUG';
let logger = log4js.getLogger('app');

// 引入路由
let Router = require('koa-router');
let router = new Router;


// 定义路由
// 根路径 (/) 的所有 HTTP 方法 (GET, POST, PUT, DELETE 等) 的请求,都会执行这个异步函数
router.all('/', async ctx =>{
	// 记录一条日志信息,表示收到对根路径的请求
    logger.info('on index page')
	ctx.body = `index page`
});

// 对于 /hello/:name 路径的所有 HTTP 方法的请求,都会执行这个异步函数
router.all('/hello/:name', async ctx =>{
	let name = ctx.params.name
    logger.info('on hello page')
	ctx.body = `hello ${name ? name : 'world'}`
});
///

// router.all('/redis', async ctx =>{
// 	let count = await rds.incr("count")
// 	logger.info(`on test redis page, count ${count}`)
// 	ctx.body = `on test redis page, 44 count ${count} `
// });

app.use(router.routes());

let port = process.env.PORT || 8080;
try{
	app.listen(8080);
	logger.info('Server started successfully and listened on '+ port +'\n'+'http://localhost:'+port);
}catch(err){
	console.error(err);
}

使用了JavaScript的koa库框架搭建web服务器。从作者的github网站上下载项目后,之所以能直接在本地运行,是因为作者已经把node_modules文件夹(依赖安装)也一同放在了github的项目中了,因此不需要本地电脑上额外npm安装koa库,也可以直接在app.js中require库web框架koa。

整体代码比较简单,重点就是定义两个http方法的函数,检测到"/"任意http方法(GET, POST, PUT, DELETE 等),都将执行一个异步函数。最后就是容器的端口号为8080。

再看一下dockerfile:

复制代码
#FROM:指定基础镜像。基础镜像是构建新镜像的基础,它包含了运行应用程序所需的操作系统和环境。
FROM node:11

#维护者信息
MAINTAINER easydoc.net

# 复制代码,将文件或目录添加到镜像中。
ADD . /app

# 设置容器启动后的默认运行目录
WORKDIR /app

# EXPOSE:指定容器对外暴露的端口。
# ENV:设置环境变量。

# 运行命令,安装依赖
# RUN 命令可以有多个,但是可以用 && 连接多个命令来减少层级。
# 例如 RUN npm install && cd /app && mkdir logs
RUN npm install --registry=https://registry.npmmirror.com

# CMD:指定容器启动后要执行的命令。
# CMD 指令只能一个,是容器启动后执行的命令,算是程序的入口。
# 如果还需要运行其他命令可以用 && 连接,也可以写成一个shell脚本去执行。
# 例如 CMD cd /app && ./start.sh,切换到app目录,./表明在当前目录下执行start.sh
CMD node app.js

FROM指定基础镜像,ADD将文件添加到镜像中,代码里的"."是添加了全部的文件,也可用COPY。其次WORKDIR设置默认运行目录。

由于是docker镜像,因此需要让docker安装依赖,RUN命令npm install安装package.json文件中的全部依赖,--registry指定国内镜像源加速。作者视频的taobao云证书过期,此处换成国内npm镜像站。

正常普通的js项目中,发布者一般不会把node_modules文件夹一并上传,因为依赖很大。一般会给出一个package.json文件,执行npm install命令就会自动安装package.json文件中的全部依赖,在dockerfile文件中的RUN npm install就已经实现了这一功能。

最后CMD指令执行文件运行。CMD 指令只能一个,指定容器启动后要执行的命令。例如 CMD cd /app && ./start.sh,切换到app目录,./表明在当前目录下执行start.sh。

看一下package.json文件中的依赖:

复制代码
{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "dependencies": {
    "koa": "^2.13.1",
    "log4js": "^3.0.6",
    "redis": "^4.0.0-rc.3",
    "mongodb": "^3.6.9",
    "koa-websocket": "^6.0.0",
    "koa-router": "^7.4.0"
  },
  "scripts": {
    "start": "cross-env PORT=8080 node app"
  },
  "author": "",
  "license": "ISC"
}

可以看到koa等依赖包的版本都被写入。

看到docker-compose.yml文件中:

复制代码
version: "3.7"

services:
  app:
    build: ./
    ports:
      - 80:8080
    volumes:
      - ./:/app
    environment:
      - TZ=Asia/Shanghai
  redis:
    image: redis:5.0.13
    volumes:
      - redis:/data
    environment:
      - TZ=Asia/Shanghai

volumes:
  redis:

port端口从本机80映射到容器8080,这与作者最后的命令相违背,可是也能运行成功:

复制代码
 docker run -p 9090:8080 --name test-hello2 test:v1

可见作者是将本机9090端口映射到容器8080端口上。而这样也能成功的原因是:当你访问主机的9090端口时,请求将被转发到容器的8080端口上,因为已经指定了,因此没有影响。

再举个例子详细讲解端口的这一问题:

复制代码
docker run -p 8080:80 my-node-app

此代码8080端口为宿主机端口,80端口为docker容器端口。

外部设备想访问docker容器上构建的应用,需要访问的是http://<宿主机IP地址>:8080,在通过宿主机上的配置,宿主主机将自己的8080端口映射到docker容器的80端口。

下面开始部署:

builid镜像,test是镜像的名字,v1是版本号:

复制代码
docker build -t test:v1 .

可在docker中看到新的镜像test:

执行结果如下:

复制代码
PS D:\docker project\javascript-json\test-docker-main> docker build -t test:v1 .
[+] Building 41.5s (9/9) FINISHED                                                                        docker:default
 => [internal] load build definition from dockerfile                                                               0.0s
 => => transferring dockerfile: 1.02kB                                                                             0.0s
 => [internal] load metadata for docker.io/library/node:11                                                        24.4s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 74B                                                                                   0.0s
 => [internal] load build context                                                                                  0.0s
 => => transferring context: 2.13kB                                                                                0.0s
 => CACHED [1/4] FROM docker.io/library/node:11@sha256:67ca28addce8ae818b144114a9376a6603aba09069b7313618d37b3858  0.0s
 => [2/4] ADD . /app                                                                                               0.0s
 => [3/4] WORKDIR /app                                                                                             0.1s
 => [4/4] RUN npm install --registry=https://registry.npmmirror.com                                               16.3s
 => exporting to image                                                                                             0.4s
 => => exporting layers                                                                                            0.4s
 => => writing image sha256:aaca618375e243ff3d75204c585bd3039d844af9c9ac0441dc922b5aca7d474c                       0.0s
 => => naming to docker.io/library/test:v1                                                                         0.0s

View build details: docker-desktop://dashboard/build/default/default/rn5hv5c0x6m0r72ku001izv57

What's Next?
  View a summary of image vulnerabilities and recommendations → docker scout quickview
PS D:\docker project\javascript-json\test-docker-main>其次执行命令:

其次执行命令:

复制代码
docker run -p 9090:8080 --name test-hello2 test:v1

原作者一开始忽略了8080:8080端口占用的情况,以及test-hello与自己上传的docker镜像相冲突名字重复的情况。

运行结果如下:

复制代码
PS D:\docker project\javascript-json\test-docker-main> docker run -p 9090:8080 --name test-hello2 test:v1
[2024-05-08T11:34:15.500] [INFO] app - Server started successfully and listened on 8080
http://localhost:8080
[2024-05-08T11:35:44.270] [INFO] app - on index page
[2024-05-08T11:36:22.788] [INFO] app - on index page
[2024-05-08T11:36:59.060] [INFO] app - on index page
[2024-05-08T11:36:59.285] [INFO] app - on index page
[2024-05-08T11:36:59.491] [INFO] app - on index page
[2024-05-08T11:36:59.717] [INFO] app - on index page
[2024-05-08T11:37:00.425] [INFO] app - on index page
[2024-05-08T11:37:01.006] [INFO] app - on index page
[2024-05-08T11:37:01.504] [INFO] app - on index page

最后的很多条:[2024-05-08T11:37:01.504] [INFO] app - on index page是因为我不断在本地地址上访问localhost:9090并且不断刷新。在docker中也会被记录。

docker中的logs记录:

powershell中的记录:

docker搭建自己的镜像上传成功,使用成功。

相关推荐
小张是铁粉44 分钟前
docker学习二天之镜像操作与容器操作
学习·docker·容器
abigale031 小时前
webpack+vite前端构建工具 -11实战中的配置技巧
前端·webpack·node.js
烟雨书信1 小时前
Docker文件操作、数据卷、挂载
运维·docker·容器
IT成长日记1 小时前
【Docker基础】Docker数据卷管理:docker volume prune及其参数详解
运维·docker·容器·volume·prune
这儿有一堆花1 小时前
Docker编译环境搭建与开发实战指南
运维·docker·容器
LuckyLay1 小时前
Compose 高级用法详解——AI教你学Docker
运维·docker·容器
Uluoyu1 小时前
redisSearch docker安装
运维·redis·docker·容器
IT成长日记5 小时前
【Docker基础】Docker数据持久化与卷(Volume)介绍
运维·docker·容器·数据持久化·volume·
热爱生活的猴子5 小时前
阿里云服务器正确配置 Docker 国内镜像的方法
服务器·阿里云·docker
FrankYoou9 小时前
Jenkins 与 GitLab CI/CD 的核心对比
java·docker