上下文
最近,我一直在尝试将我的Angular构建容器化,因为我将前端和后端一起部署在一个映像中。Dockerfile如下:
# Build frontend
FROM node:16 AS node-build
WORKDIR /app
COPY frontend/package.json frontend/package-lock.json ./
RUN npm install
COPY frontend .
RUN npm run build
# Build backend
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS dotnet-build
WORKDIR /app
COPY backend ./
RUN dotnet restore Api
RUN dotnet publish Api -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=dotnet-build /app/out .
COPY --from=node-build /app/dist/film-portal wwwroot/
ENTRYPOINT ["dotnet", "Api.dll"]
问题
上面的Dockerfile完美地构建了有问题的图像,部署后它就像一个魅力。然而,构建所花费的时间比我希望的要多。让我解释一下:
只有当package.json
或package-lock.json
发生更改时,才运行npm install
。这很好,节省时间
npm run build
。这当然是预期的行为,但它每次都会重新编译Angular库代码,而不是缓存编译后的结果(就像从本地shell执行npm run build
时的情况一样)我正在寻找一种方法来缓存编译angular库代码的结果,因此npm run build
只需要构建我自己的代码(完成时间更短)。在假想语法中,我需要在Dockerfile中为前端阶段提供以下内容:
FROM node:16 AS node-build
WORKDIR /app
COPY frontend/package.json frontend/package-lock.json ./
RUN npm install
RUN npm compile-angular
COPY frontend .
RUN npm run build
这里,npm compile-angular
将仅在package.json
或package-lock.json
改变时编译角度位,而不是每次我触摸前端代码中的某个文件时。
不幸的是,据我所知,Angular CLI中没有专门编译Angular库代码的命令,只剩下用户代码。此外,我阅读的所有教程都没有提到重新编译的问题,所以我可能在这里遗漏了一些东西。尽管如此,我很难想象我是第一个遇到这个问题的人,我想至少应该有一个变通办法。因此,总结一下:
- 有没有办法避免在像我这样的码头化设置中重新编译Angular库代码
- 如果没有,是否至少有一个变通方法,可能是在Docker之外执行构建步骤
经过长时间的搜索,我在angular cli存储库中找到了有关Issue 17017的信息。对此问题的一条评论提到,有一个黑客可以触发ESM编译:./node_modules/.bin/ngcc --properties es2015
。有了这些知识,我修改了我的Dockerfile,它就像一个魅力,不再在每次更改我自己的代码时重新编译Angular库代码:
# Build frontend
FROM node:16 AS node-build
WORKDIR /app
COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci
# Hack to make sure the angular modules are compiled at this stage
RUN ./node_modules/.bin/ngcc --properties es2015
COPY frontend .
RUN npm run build
# Build backend
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS dotnet-build
WORKDIR /app
COPY backend ./
RUN dotnet restore Api
RUN dotnet publish Api -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=dotnet-build /app/out .
COPY --from=node-build /app/dist/film-portal wwwroot/
ENTRYPOINT ["dotnet", "Api.dll"]