docker构建.net core运行的镜像
在docker很火的今天,越来越多的应用现在都在往docker上迁移,.net core怎么能落后?
项目要运行在docker上,我们需要先制作镜像,可以基于centos来制作,当然也可以基于Ubuntu,这里以centos为例。
首先,拉取centos的镜像:
sudo docker pull centos
#如果是Ubuntu,则拉取ubuntu的镜像
sudo docker pull ubuntu
接着下载.net core的SDK,或者是.net core的runtime包,地址:https://dotnet.microsoft.com/download/dotnet-core,这里我选择的.net core 3.1的SDK。
新建一个目录,比如叫dotnetcore,将SDK放在这个目录下,然后复制你本机的 /usr/share/zoneinfo/Asia/Shanghai 文件到dotnetcore目录(也可以是 /usr/share/zoneinfo/Asia/Chongqing ),然后创建一个名称是Dockerfile的文件,目录展示如下:
说明一下,Shanghai这个文件一个时区标识,无论是centos还是ubuntu,默认采用的都是UTC时间,而在国内我们习惯于用北京时间
Dockerfile是镜像的构建说明文件,注意,默认文件名就是Dockerfile,大小写要一致,如果不是这个文件名,那么在docker build时需要使用 -f 参数指定的构建文件
Dockerfile的内容如下:
FROM centos:latest WORKDIR . ADD dotnet-sdk-3.1.302-linux-x64.tar.gz /opt COPY Shanghai /usr/share/zoneinfo/Asia/Shanghai RUN ln -s /opt/dotnet /usr/local/bin/dotnet && \ rm -f /etc/localtime && \ ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ yum update -y && \ yum install epel-release -y && \ yum update -y && \ yum install libgdiplus-devel -y && \ yum install glibc -y && \ yum install curl -y && \ yum install icu -y ARG user=root USER $user CMD [ "/bin/bash" ]
如果采用的是其他的dotnet的SDK或runtime包,这需要将上面的ADD部分改成对应的包就可以了
RUN命令执行创建了一些软连接以及修改时区配置,同时安装了一些常用的依赖包(其中 libgdiplus-devel是.net core 绘图所需的依赖包),如果还有其它依赖包,可以参照上面的例子添加。
尽量不要安装没用的包,避免生成的镜像过大,最好是根据自己的项目去定制。
开始构建
sudo docker build -t dotnetcore:v3.1 .
注意,这个命令是在Dockerfile文件所在目录下执行的,如果构建说明文件名不是Dockerfile,需要使用 -f 参数进行执行。-t 参数指定生成镜像的名称及版本,两者使用冒号(:)隔开,这里是 dotnetcore:v3.1
另外,命令最后面有一个点号, 它是构建执行的上下文路径,docker build时会将这个路径所有内容打包,上面的Dockerfile中的ADD和COPY命令相对的目录也就是这个上下文目录。
执行后稍等片刻,输出类似下面的内容则表示已经构建成功了
现在可以使用下面的命令查看生成的镜像:
sudo docker images
使用镜像运行一个.net core应用
创建一个.net core应用,比如我创建一个叫DemoApi的webapi应用,然后publish得到发布后的文件,放到一个demo目录下:
执行下面的命令即可创建一个容器了
sudo docker run -d -w /publish -v /home/feng/temp/demo/publish:/publish --expose 5000 -p 5000:5000 dotnetcore:v3.1 dotnet DemoApi.dll --urls http://*:5000
说明:
docker run:使用指定的镜像创建一个容器,然后启动容器,等于docker create + docker start
-d:在后台启动容器
-w:容器的工作目录,容器启动会,会切换到这个目录下
-v:数据卷,可以理解为容器路径与主机路径的一个映射,比如上面的命令中,将主机的 /home/feng/temp/demo/publish 与容器的 /publish 路径建立映射,那么进入容器的 /publish 路径就可以看到主机 /home/feng/temp/demo/publish 下的文件了
--expose:容器对外(主机或者其他容器)暴露的端口,一般就是应用的所绑定的端口
-p:端口绑定,将容器的端口与主机的端口做一个绑定,如果访问主机的这个端口会被转发到容器的对应端口,格式:主机端口:容器端口
dotnetcore:v3.1:所使用的的镜像及版本
dotnet DemoApi.dll --urls http://*:5000:应用启动命令
上面的命令执行后,使用下面的命令可以查看命令是否启动:
sudo docker ps -a
其中STATUS下面的UP就表示已经启动了,如果是Exited,表示容器挂了。
容器运行起来了,访问主机的5000端口,就会被转发到容器的5000端口去了。
比如我的linux主机IP是:192.168.209.132,而我的DemoApi项目有个/Home地址的路由,于是我访问http://192.168.209.132:5000/Home 就可以了
构建应用镜像
虽然上面我们已经使用自己构造的.net core的镜像将项目运行起来了,它使用了数据卷将容器路径与主机路径耦合起来了,这对容器迁移其它主机造成了不利。
我们可以将应用所需的所有文件打包到镜像中,构建一个应用程序的镜像,这样容器就与主机彻底没有耦合了。
上面的例子中,我们将DemoApi的发布文件放在demo目录下,然后我们在demo目录下执行打包
tar -cf publish.tar publish
#tar包生成之后,可以执行 rm -rm publish/ 删除原来的文件目录
执行完成之后会生成一个tar包,然后同样的创建一个Dockerfile文件,内容如下:
FROM dotnetcore:v3.1 ADD publish.tar /app/ EXPOSE 5000 HEALTHCHECK --interval=5m --timeout=3s --retries=3 \ CMD curl -f http:/localhost:5000/Home || exit 1 WORKDIR /app/publish CMD [ "dotnet", "DemoApi.dll", "--urls", "http://*:5000" ]
其中HEALTHCHECK是健康检查,会定时的去执行CMD后的命令,具体效果可以看后面的截图
最后结构如下:
执行下面的命令构建应用镜像:
sudo docker build -t demo:v1 .
注意,上面的命令后面有一个点号,它是上下文路径,点号表示当前目录
当提示类似下面的内容,表示构建成功了
可以执行 下面的命令查看生成的镜像:
sudo docker images
运行镜像只需执行下面的命令即可:
sudo docker run -d -p 5000:5000 demo:v1
这就比上面的例子启动简单多了,而且,我们只需要将这个镜像push & pull,在任何一个安装有docker的主机上都可以运行了
提示,上图的STATUS栏下面有个(health: starting)的显示,这是因为我们的Dockerfile中添加了HEALTHCHECK,它是健康检查的意思,它的CMD命令是访问本地的一个url,容器会定时去访问这个地址,如果这个url不可访问,就会显示(unhealthy)
其实,上面的Dockerfile类似于执行下面的命令启动容器:
sudo docker run -id -w /publish -v /home/feng/temp/demo/publish:/publish --expose 5000 -p 5000:5000 \
--health-cmd "curl -f http:/localhost:5000/Home || exit 1" --health-interval 5m --health-retries 3 --health-timeout 3s \
dotnetcore:v1 dotnet DemoApi.dll --urls http://*:5000
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY