publish dotnet core angular spa app to docker

时间:2021-07-04 18:44:50

公司一个使用Angular开发的应用准备下个版本使用.Net Core开发后台, 刚好可以用到.Net Core Angular Spa模板, 而且最近也在学习Docker, 于是就想把它融汇贯通, 之前往Docker上部署过.Net Core MVC的应用, 那个比较简单, 使用微软官方文档的示例即可.

于是在使用.Net Core Angular Spa的时候, 我依葫芦画瓢发现这是走不通的, 因为Angular应用在构建的时候除了依赖.Net Core SDK还依赖于Node, 直接使用原来的Dockerfile作为模板行不通.

在原来的木板上需要加上安装Node的命令:

RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt-get install -y nodejs

整个完整示例如下:

FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt-get install -y nodejs
WORKDIR /app
COPY src/. ./src/
WORKDIR /app/src/WebApp
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 AS runtime
WORKDIR /app
COPY --from=build /app/src/WebApp/out ./
EXPOSE 5000
ENTRYPOINT ["dotnet", "WebApp.dll"]

上面的示例也是我总结出来的, 我实际的操作其实是这样的:

因为在家网络环境有那么点你懂的, 每次一到这一句‘RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -’就会卡在他的第五个小步骤, 我也猜到了是网络问题, 来来回回倒腾了好几次依然卡在那里. 因为已经凌晨了, 想想, 这么做无用功不行啊, 于是我去睡觉(失眠了)了, 折腾了半天睡不着索性爬起来敲代码, 这次我换了条思路, 我不纠结于Dockerfile了, 我要做一个镜像:

微软倒是有build专用的镜像: microsoft/aspnetcore-build, 她同时包含了以下几个环境:

  • Node.js
  • NET Core SDK
  • Bower
  • Gulp

呵呵, 不幸的是, 他的SDK的版本是2.2的, 不支持3.0.

那我就在SDK3.0的基础上装一个Node:

  • 首先创建一个SDK容器然后进入容器:
docker run -it mcr.microsoft.com/dotnet/core/sdk:3.0 /bin/bash

这里我专门测试了该容器能不能支持yum或者apt-get:

yum -v
apt-get -v

测试的结果是支持apt-get而不支持yum, 因此我猜测微软的SDK镜像是基于Ubuntu构建的(当然这里只是猜测).

  • 然后安装Node:
curl -sL https://deb.nodesource.com/setup_12.x | bash -
apt-get install -y nodejs
node -v
npm -v

很神奇, 这次安装特别顺利, 按道理网络不过不通, 那这里也应该会卡住啊, 可能是上天眷顾想让我早点睡觉吧!

制作了镜像放在本地那天弄丢了咋办, 于是我就想着上传到Docker Hub上去, 还能供需要的朋友使用.

# 首先退出容器
exit
# 然后把容器使用commit命生成镜像
docker commit -a "jerryqi" -m "dotnet core build image which contains dotnet core 3.0 and node 12.13" d78d728c6d46  dotnet-build:1.0

生成镜像的命令这里做一个说明:

  • -a: 作者
  • -m: 描述
  • d78d728c6d46: 容器Id
  • dotnet-build:1.0: 生成的镜像名和tag
    然后使用docker login命令登陆Docker Hub, 当然前提是你已经注册了账号.

然后就可以push到Docker Hub了:

docker push dotnet-build:1.0

你已经这样就完事了吗? 并没有, 报错了:

denied: requested access to the resource is denied

查其原因, 是因为这样直接推送是推送到了官方名下镜像(这是我个人的一个描述), 很明显我这里是个人的镜像只能是在我个人的名下.

打个比方, 哪天官方或者其他人也Push一个名字为dotnet-build:1.0的镜像那岂不混乱了.

所以这个镜像必须在我的名下, 那么就需要给他打一个tag:

docker tag dotnet-build:1.0 jerryqi/dotnet-build:1.0

那么现在推送就OK了:

docker push jerryqi/dotnet-build:1.0

上面走了不少弯路, 而实际上不用这么麻烦的, 直接在生成镜像的时候就可以把上面的全给干了:

# 镜像名直接加上你的用户名:jerryqi/dotnet-build:1.0
docker commit -a "jerryqi" -m "dotnet core build image which contains dotnet core 3.0 and node 12.13" d78d728c6d46  jerryqi/dotnet-build:1.0

这样我就可以简化我的Dockerfile如下了:

FROM jerryqi/dotnet-build:1.0 AS build
WORKDIR /app
COPY src/. ./src/
WORKDIR /app/src/WebApp
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0 AS runtime
WORKDIR /app
COPY --from=build /app/src/WebApp/out ./
EXPOSE 5000
ENTRYPOINT ["dotnet", "WebApp.dll"]

终于总结好了, 我该去吃午饭了!