typescript创建docker镜像

在使用typescript编写基于node.js的微服务项目时,需要将服务以docker形式进行发布,遇到了一些问题,现在记录一下。

docker镜像使用的node版本与开发版本不一致,会导致很多问题。在开发时,使用的是完整版本,而在部署时,希望使用简化版本以减小尺寸。版本不一致会使开发过程中npm module与创建容器时的版本不同,从而导致错误。有几点需要注意:

1、需要使用npm install 而不是npm ci,并且只复制package.json到容器。
这是因为npm ci会严格按照package-lock.json进行部署,而这是获取的npm modules是与开发环境相匹配的,不一定适合创建容器的简化版本。

2、使用相近的node简化版本,尽量减少开发与部署的版本差别。

3、可能需要在docker部署时安装python和其它辅助程序包。

简单部署时,可以将源代码拷入,直接生成,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 使用 Node.js 官方镜像作为基础镜像
FROM node:18-alpine

WORKDIR /app

# 复制 package.json 和 package-lock.json(如果存在)
COPY package.json ./

# 安装依赖
RUN npm install

# 复制源代码
COPY . .

# 构建 TypeScript 代码
RUN npm run build

# 暴露端口
EXPOSE 3000

CMD ["node", "dist/app.js"]

复杂情况下,可以先进行编译,然后创建部署容器。下面是复杂情况下的Dockerfile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 构建阶段:安装依赖并编译
FROM node:20.10.0 AS builder

WORKDIR /app

# 复制并安装依赖
COPY package.json ./
RUN npm install

# 复制源码并构建
COPY . .
RUN npm run build

# 生产阶段:仅保留必要内容
FROM node:20-alpine


# 启用仓库并安装工具链
RUN echo "https://dl-cdn.alpinelinux.org/alpine/v3.18/main" > /etc/apk/repositories && \
echo "https://dl-cdn.alpinelinux.org/alpine/v3.18/community" >> /etc/apk/repositories && \
apk update && \
apk add --no-cache build-base python3

WORKDIR /app

# 复制生产依赖清单
COPY package.json ./
COPY data ./data


# 安装生产依赖(不包含devDependencies)
RUN npm install --production

# 从构建阶段复制编译结果
COPY --from=builder /app/dist ./dist

# 暴露端口
EXPOSE 3000

# 启动命令
CMD ["node", "dist/app.js"]