前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >再遇 Docker,容器化 Node 应用

再遇 Docker,容器化 Node 应用

作者头像
Innei
发布2021-12-28 10:40:47
4400
发布2021-12-28 10:40:47
举报
文章被收录于专栏:静之森

首先声明,这不是一个教程贴,更多的是遇到的问题和解决方式。内容仅供参考。

一直以来就想把 Node 应用容器化,奈何一直没有精力去捣鼓。今天下午捣鼓了一下午,终于捣鼓出来了。说说遇到坑还有怎么去解决吧。至于 docker 这玩意怎么去用网上内容一搜一大把。没有必要再去描述了。

编写 Dockerfile

首先,我们这次要做的容器首先肯定是要摆脱 node_modules 的,不能我 build 完 image 之后 push 到 docker hub,用户 pull 来之后还要再 npm install 一下的。这肯定是不行的。具体怎么实现摆脱 node_modules ,我在上一篇文章中讲述过了,可以参考一下

使用 GitHub CI 云构建和自动部署

在项目根目录新建一个 dockerfile,编写如下。

bash

代码语言:javascript
复制
1FROM node:16 as builder
2WORKDIR /app
3COPY . .
4RUN npm i -g pnpm
5RUN pnpm install
6RUN pnpm bundle # 可以参考 rimraf out && yarn run build && cd dist/src && npx ncc build main.js -o ../../out -m
7
8FROM node:16
9WORKDIR /app
10COPY --from=builder /app/out .
11EXPOSE 2333
12CMD node index.js

COPY

这里用了两个 worker 去构建,第一个先 build 项目,生成构建产物,然后在第二个 worker copy 第一个中的构建产物,最后生成的 image 仅仅只有第二个的,第一个 builder 不会封装进去,可以大大减少 image 的体积。

这样 build 出来的 image 最终是 1G 左右,用户可以直接 pull 就直接跑的。这个体积算大吗,除了自带的 node、Debian 环境没有引入其他的包甚至 node_modules。再体积方面,可以用 node:16-alpine 这个 image 继续做优化,apline 是最小化的 Linux 镜像了(大概),整个 image 只有 200M 左右,应经测试,用 apline 构建出来的 image 体积只有 250M。可以对比一下。但是为什么我最终没有用 apline 呢,原因还是他太小了,ncc build 项目的时候缺了一堆库,就算用 apk 把缺的库全部补上之后,在生产中依旧跑不起来,可能还是摆脱不了 node_modules,多次尝试后,以失败告终。如有好的办法请联系我。

我的项目中用到了 MongoDB 和 Redis,那么就需要再去编写 docker-compose。这个就没啥好说了,网上一搜一大把。给个参考吧。而我想说的是,我遇到的坑。

yaml

代码语言:javascript
复制
1version: '3.8'
2
3services:
4  app:
5    container_name: mx-server
6    image: innei/mx-server:latest
7    restart: 'on-failure'
8    ports:
9      - '2333:2333'
10    depends_on:
11      - mongo
12      - redis
13    links:
14      - mongo
15      - redis
16    networks:
17      - app-network
18
19  mongo:
20    container_name: mongo
21    image: mongo
22    volumes:
23      - ./data:/data/db
24    ports:
25      - '3344:27017'
26    networks:
27      - app-network
28
29  redis:
30    image: redis
31    container_name: redis
32
33    ports:
34      - '3333:6379'
35    networks:
36      - app-network
37networks:
38  app-network:
39    driver: bridge

COPY

首先是,在项目中,mongo 和 redis 连得都是 127.0.0.1 但是在 docker-compose up 之后,连不上,怎么回事,后来知道是要改成 service 的名字。就比如

yaml

代码语言:javascript
复制
1services:
2  mongo:       # 这里的 name 是啥 到时候连的时候 host 就要填这个
3    container_name: mongo
4    image: mongo
5    volumes:
6      - ./data:/data/db
7    ports:
8      - '3344:27017'
9    networks:
10      - app-network

COPY

上面的案例,在项目中的连接地址必须是 mongodb://mongo:27017。然后原先项目中的 host 定义都是通过 argv 传递的,如

typescript

代码语言:javascript
复制
1export const MONGO_DB = {
2  collectionName: (argv.collection_name as string) || 'mx-space',
3  get uri() {
4    return `mongodb://${argv.db_host || '127.0.0.1'}:${
5      argv.db_port || '27017'
6    }/${process.env.TEST ? 'mx-space_unitest' : this.collectionName}`
7  },
8}

COPY

然后就一直再找,怎么在 run 的时候 pass argument,最后也是找了一圈没找到。说是可以在 dockerfile 中。加上这两行可以读到 argument。

代码语言:javascript
复制
1FROM node:16
2ARG redis_host # 这个
3ARG mongo_host # 这个

COPY

但是,这好像实在 build 的时候就要传递的,那还不如写死算了。所有就变成了这样,也是最后的样子。

docker

代码语言:javascript
复制
1FROM node:16 as builder
2WORKDIR /app
3COPY . .
4RUN npm i -g pnpm
5RUN pnpm install
6RUN pnpm bundle
7
8FROM node:16
9ARG redis_host
10ARG mongo_host
11RUN apt update
12RUN apt install zip unzip mongo-tools -y # 因为业务需要额外的 command tools
13
14WORKDIR /app
15COPY --from=builder /app/out .
16EXPOSE 2333
17CMD node index.js --redis_host=redis --db_host=mongo # 直接 pass argument

COPY

GitHub CI 自动化构建发布

这一步倒是很简单的,官方有自己的 github action 给你用了,直接去 docker hub 先生成一个 token,填入 secrets。就没什么问题了。关于 GitHub workflow 的 yaml 可以贴一下。可以参考。

yaml

代码语言:javascript
复制
1name: Docker build
2
3on:
4  push:
5    # Sequence of patterns matched against refs/tags
6    tags:
7      - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
8    # branches:
9    #   - 'master'
10
11jobs:
12  docker:
13    runs-on: ubuntu-latest
14    steps:
15      - name: Set up QEMU
16        uses: docker/setup-qemu-action@v1
17      - name: Set up Docker Buildx
18        uses: docker/setup-buildx-action@v1
19      - name: Login to DockerHub
20        uses: docker/login-action@v1
21        with:
22          username: ${{ secrets.DOCKERHUB_USERNAME }}
23          password: ${{ secrets.DOCKERHUB_TOKEN }}
24      - name: Build and push
25        id: docker_build
26        uses: docker/build-push-action@v2
27        with:
28          push: true
29          tags: innei/mx-server:latest

COPY

然后现在的话,

mx-server

可以上 docker hub 了,可以直接跑在 docker 了。单用户可以直接用一下命令跑起服务。奈斯。

bash

代码语言:javascript
复制
1cd
2mkdir -p mx/server
3cd mx/server
4wget https://cdn.jsdelivr.net/gh/mx-space/server-next@master/docker-compose.yml
5docker-compose up -d
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-09-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 编写 Dockerfile
  • GitHub CI 自动化构建发布
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档