news 2026/10/28 6:18:29

Ubuntu 22.04部署.NET Core应用Docker化实践指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu 22.04部署.NET Core应用Docker化实践指南

1. 项目概述

最近在帮团队把一个.NET Core项目部署到Ubuntu 22.04虚拟机的Docker环境中,整个过程踩了不少坑,也积累了一些实战经验。不同于Windows环境下的部署,Linux+Docker的组合需要特别注意运行时兼容性、权限管理和网络配置等问题。这篇文章将详细记录从环境准备到最终部署的全过程,特别适合那些需要将.NET应用容器化部署到Linux环境的开发者参考。

.NET Core的跨平台特性让我们可以在Linux服务器上运行原本基于Windows开发的应用程序,而Docker则进一步简化了部署和扩展的复杂度。Ubuntu 22.04作为长期支持版本,提供了稳定的基础环境。这种组合在中小型项目中特别实用,既能利用Linux服务器的性能优势,又能保持开发环境的灵活性。

2. 环境准备

2.1 虚拟机基础配置

首先需要准备Ubuntu 22.04的虚拟机环境。我使用的是VMware Workstation 17 Pro,分配了4核CPU、8GB内存和50GB磁盘空间。安装时选择最小化安装(Minimal Installation),这样可以减少不必要的软件包,保持系统干净。

安装完成后,有几个基础配置需要立即进行:

# 更新软件包列表 sudo apt update && sudo apt upgrade -y # 安装基础工具 sudo apt install -y curl wget git net-tools

注意:在虚拟机中建议启用SSH服务,方便后续通过终端连接操作:

sudo apt install -y openssh-server sudo systemctl enable --now ssh

2.2 Docker环境安装

Ubuntu 22.04官方仓库中的Docker版本可能不是最新的,建议使用Docker官方提供的安装方式:

# 卸载旧版本(如果有) sudo apt remove docker docker-engine docker.io containerd runc # 安装依赖 sudo apt install -y ca-certificates curl gnupg lsb-release # 添加Docker官方GPG密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 设置仓库 echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装Docker引擎 sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # 验证安装 sudo docker run hello-world

安装完成后,建议将当前用户加入docker组,避免每次都要使用sudo:

sudo usermod -aG docker $USER newgrp docker # 立即生效

3. 项目容器化

3.1 准备.NET Core项目

假设我们有一个ASP.NET Core Web API项目,项目结构如下:

MyApiProject/ ├── Controllers/ ├── Models/ ├── Program.cs ├── appsettings.json └── MyApiProject.csproj

首先需要在本地开发环境发布项目:

dotnet publish -c Release -o ./publish

这会在项目目录下生成一个publish文件夹,包含所有运行时需要的文件。

3.2 编写Dockerfile

在项目根目录创建Dockerfile,内容如下:

# 使用官方.NET运行时镜像作为基础 FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 EXPOSE 443 # 使用SDK镜像构建项目 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src COPY ["MyApiProject/MyApiProject.csproj", "MyApiProject/"] RUN dotnet restore "MyApiProject/MyApiProject.csproj" COPY . . WORKDIR "/src/MyApiProject" RUN dotnet build "MyApiProject.csproj" -c Release -o /app/build # 发布项目 FROM build AS publish RUN dotnet publish "MyApiProject.csproj" -c Release -o /app/publish # 最终阶段 FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "MyApiProject.dll"]

这个Dockerfile采用了多阶段构建,可以显著减小最终镜像的体积。关键点说明:

  1. 使用官方.NET镜像,确保运行时环境一致
  2. 分阶段构建:SDK阶段用于编译,运行时阶段只包含必要组件
  3. 暴露80和443端口,对应HTTP和HTTPS
  4. ENTRYPOINT指定容器启动时运行的命令

3.3 构建Docker镜像

将项目文件(包括Dockerfile)上传到Ubuntu虚拟机后,在项目根目录执行:

docker build -t myapi:1.0 .

构建过程可能会花费几分钟时间,取决于项目复杂度和网络速度。构建完成后,可以用以下命令查看镜像:

docker images

4. 运行容器

4.1 基本运行

最简单的运行方式是直接启动容器:

docker run -d -p 8080:80 --name myapi_container myapi:1.0

参数说明:

  • -d: 后台运行
  • -p 8080:80: 将容器内部的80端口映射到主机的8080端口
  • --name: 为容器指定一个名称

4.2 生产环境配置

对于生产环境,建议添加以下配置:

docker run -d \ -p 80:80 \ -p 443:443 \ --name myapi_prod \ --restart unless-stopped \ -e ASPNETCORE_ENVIRONMENT=Production \ -e ASPNETCORE_URLS=http://+:80 \ -v /path/to/appsettings.Production.json:/app/appsettings.Production.json \ myapi:1.0

关键配置项:

  • --restart unless-stopped: 容器意外退出时自动重启
  • -e: 设置环境变量
  • -v: 挂载配置文件,方便修改配置而无需重建镜像

5. 网络与存储配置

5.1 自定义网络

为了提高安全性和可管理性,建议为容器创建自定义网络:

docker network create myapi_network

然后运行容器时指定网络:

docker run -d \ --network myapi_network \ --name myapi \ myapi:1.0

5.2 数据持久化

如果应用需要保存数据,可以使用Docker卷:

# 创建卷 docker volume create myapi_data # 使用卷 docker run -d \ -v myapi_data:/app/data \ myapi:1.0

6. 常见问题与解决方案

6.1 权限问题

在Linux上运行.NET Core应用可能会遇到文件权限问题,特别是在尝试写入文件时。解决方法:

  1. 确保Dockerfile中设置了正确的用户:
FROM mcr.microsoft.com/dotnet/aspnet:6.0 USER app WORKDIR /app
  1. 或者在运行时指定用户:
docker run -u 1000:1000 myapi:1.0

6.2 时区设置

容器内默认使用UTC时间,如果需要使用本地时区:

ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

6.3 性能调优

对于高负载应用,可以调整以下参数:

docker run -d \ --cpus 2 \ --memory 2g \ --memory-swap 4g \ myapi:1.0

7. 监控与日志

7.1 查看日志

查看容器日志:

docker logs -f myapi_container

7.2 资源监控

查看容器资源使用情况:

docker stats myapi_container

7.3 健康检查

在Dockerfile中添加健康检查:

HEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost/health || exit 1

8. 使用Docker Compose

对于更复杂的部署,建议使用Docker Compose。创建docker-compose.yml文件:

version: '3.8' services: myapi: image: myapi:1.0 build: context: . dockerfile: Dockerfile ports: - "80:80" - "443:443" environment: - ASPNETCORE_ENVIRONMENT=Production networks: - myapi_network volumes: - myapi_data:/app/data restart: unless-stopped volumes: myapi_data: networks: myapi_network: driver: bridge

启动服务:

docker-compose up -d

9. CI/CD集成

可以将这个流程集成到CI/CD管道中。以下是GitHub Actions的示例:

name: Build and Deploy on: push: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Build and push uses: docker/build-push-action@v3 with: context: . push: true tags: yourusername/myapi:latest

10. 安全最佳实践

  1. 定期更新基础镜像:
FROM mcr.microsoft.com/dotnet/aspnet:6.0@sha256:具体sha值
  1. 使用非root用户运行容器

  2. 扫描镜像中的漏洞:

docker scan myapi:1.0
  1. 限制容器权限:
docker run --read-only --security-opt=no-new-privileges myapi:1.0

在实际部署中,我发现这种组合特别适合中小型项目的部署。它结合了.NET Core的开发效率、Linux的运行效率和Docker的部署便利性。最大的优势是一旦配置完成,后续的部署和扩展就变得非常简单。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/28 6:17:53

TinyImageNetTorch:64×64小图预训练微调实战

简介:面向深度学习初学者与图像分类实践者的 TinyImageNet 预训练模型微调示例工程,基于 Python 与 PyTorch 实现,用规模适中的 6464 像素、约 200 类图像数据走通从加载预训练权重到微调的完整流程,适合显存与算力有限、希望快速…

作者头像 李华
网站建设 2026/10/28 6:17:38

DFMEA、PFMEA与FTA逻辑缝合:一张结构化画布实现失效分析闭环

1. 为什么一张画布能同时承载DFMEA、PFMEA和FTA——不是工具堆砌,而是逻辑缝合“DFMEA做完了,PFMEA也跑通了,FTA图也画出来了,可问题还是反复发生。”这是我在某制造类模拟项目X中,听某导师在复盘会上说的第一句话。当…

作者头像 李华
网站建设 2026/10/28 6:16:56

context-mode设计模式:用上下文对象优雅管理多模式行为

1. 从“context-mode”这个命名说起:它到底在解决什么问题第一次看到context-mode这个词,很多人会下意识地把它当成某个库里的配置项,或者某个框架的开关参数。但如果你真的在工程里跟“上下文”打过交道,就会明白这个词背后藏着一…

作者头像 李华
网站建设 2026/10/28 6:16:37

Cloudflare-OS:不是操作系统,而是边缘计算的OS级抽象

1. “Cloudflare-OS”不是操作系统,而是开发者对 Workers 运行时抽象层的戏称式命名“Cloudflare-OS”这个词在近期技术社区中高频出现,但它根本不是一个真实发布的操作系统产品,也没有任何官方文档、GitHub 仓库或安装镜像与之对应。它本质上…

作者头像 李华
网站建设 2026/10/28 6:16:35

链表节点两两交换:迭代与递归实现详解

1. 题目解析与需求理解力扣(LeetCode)第128题"两两交换链表中的节点"是一道经典的链表操作题目,属于hot100高频面试题库。题目要求给定一个链表,将相邻的两个节点进行交换,并返回交换后的链表头节点。例如&a…

作者头像 李华
网站建设 2026/10/28 6:16:09

Cisco IOS隐藏命令ponytail:网络排障中的历史命令追溯利器

“ponytail”这词,搜索引擎上第一屏通常都是扎马尾辫的美妆教程。可在网络设备运维这个圈子里,它还藏着另一重身份:Cisco IOS里一条用于查看完整命令历史的隐藏命令。刚接手公司核心网络那段时间,我闹过一个笑话:核心交…

作者头像 李华