Windows 10下使用Dockerfile快速部署IIS+ASP.NET网站的完整指南
1. 环境准备Windows 10下的Docker配置在Windows 10上玩转Docker部署IISASP.NET首先得把游乐场搭建好。我强烈推荐使用Docker Desktop for Windows这是微软官方优化的容器运行时环境。安装时有个关键细节要注意必须开启Hyper-V虚拟化支持。如果你的系统是Windows 10家庭版需要先升级到专业版或企业版这个坑我当年踩过。安装完成后别急着操作建议做三个基础检查在PowerShell输入docker --version确认版本建议2.3执行docker run hello-world测试基础功能检查任务栏Docker图标是否显示Engine running注意如果遇到WSL 2报错需要先安装Windows Subsystem for Linux更新包这个在微软官网有详细指引。我习惯把工作目录设在非系统盘比如D:\DockerProjects这样可以避免权限问题。创建专用文件夹时路径最好不要包含中文和空格这是很多新手容易忽视的细节。建议目录结构如下/MyWebApp ├── Dockerfile └── Publish/ ├── bin/ ├── Content/ └── Web.config2. 编写高效的DockerfileDockerfile就像烹饪食谱决定了最终容器的味道。对于IISASP.NET组合我推荐使用微软官方镜像作为基础。经过多次实测下面这个配方最稳定# 使用微软官方镜像作为基底 FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019 # 切换到PowerShell环境 SHELL [powershell, -Command, $ErrorActionPreference Stop;] # 配置IIS应用池 RUN Import-Module WebAdministration; \ Set-ItemProperty -Path IIS:\AppPools\DefaultAppPool -Name processModel.identityType -Value 2; \ Set-ItemProperty -Path IIS:\AppPools\DefaultAppPool -Name processModel.loadUserProfile -Value $true # 设置工作目录 WORKDIR C:/inetpub/wwwroot # 复制发布文件 COPY ./Publish/_PublishedWebsites/MyWebApp/. ./这个配置有几个精妙之处使用LTS长期支持版本的基础镜像ltsc2019比普通版本更稳定通过SHELL指令统一错误处理策略避免静默失败应用池配置了特定用户身份解决部分权限问题复制路径考虑了Visual Studio的发布目录结构实用技巧在COPY指令前添加RUN Remove-Website -Name Default Web Site可以清理默认站点避免端口冲突。3. 项目发布与构建技巧很多教程没讲清楚的是ASP.NET项目的正确发布方式。在Visual Studio中我推荐使用文件系统发布方式并勾选这两个关键选项删除所有现有文件避免残留旧版本预编译期间合并输出减少文件数量发布完成后建议手动检查Publish文件夹是否包含这些必要文件Web.config含正确连接字符串bin目录含所有程序集静态资源CSS/JS/图片构建镜像时有个效率技巧在项目根目录打开终端执行这个增强版命令docker build -t mywebapp:v1 --build-arg HTTP_PROXYhttp://your-proxy:8080 .参数说明--build-arg适合企业内网环境设置代理--no-cache需要彻底重建时使用--progressplain调试时查看完整构建日志我习惯给镜像打两个标签版本号v1和latest方便后续回滚docker build -t mywebapp:v1 -t mywebapp:latest .4. 容器运行与调试运行容器不是简单docker run就完事了对于ASP.NET应用这个优化过的命令组合更可靠docker run -d --name webapp -p 8080:80 --restart unless-stopped -v C:\logs:C:\inetpub\logs mywebapp:v1参数解析--restart设置自动重启策略避免服务中断-v挂载日志目录方便排查问题-p第一个端口是主机端口第二个是容器端口遇到网站打不开时我常用的排查三板斧检查容器状态docker ps -a查看实时日志docker logs -f webapp进入容器检查docker exec -it webapp powershell在容器内可以运行这些诊断命令Get-Website | Select-Object Name, State, PhysicalPath Test-NetConnection -ComputerName localhost -Port 80 Get-ChildItem C:\inetpub\wwwroot5. 生产环境部署方案开发环境测试通过后镜像部署到生产环境有几种方案。对于中小型项目我推荐使用Docker Registry私有仓库本地打标签docker tag mywebapp:v1 registry.yourcompany.com/webapps/mywebapp:v1推送到仓库docker push registry.yourcompany.com/webapps/mywebapp:v1生产服务器拉取docker pull registry.yourcompany.com/webapps/mywebapp:v1对于没有私有仓库的情况可以用docker save方案# 本地导出 docker save -o mywebapp_v1.tar mywebapp:v1 # 生产环境导入 docker load -i mywebapp_v1.tar性能优化建议在Docker Desktop设置中分配至少4GB内存使用--cpuset-cpus参数限制CPU使用考虑使用Windows Server Core镜像减小体积6. 常见问题解决方案问题1端口被占用错误现象Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use解决方案# 查找占用进程 netstat -ano | findstr :80 # 停止相关服务或改用其他端口 docker run -p 8080:80 ...问题2文件权限不足错误现象Access to the path C:\inetpub\wwwroot\web.config is denied解决方法# 在Dockerfile中添加 RUN icacls C:\inetpub\wwwroot /grant IIS_IUSRS:(OI)(CI)F问题3镜像体积过大优化方案使用.dockerignore文件排除无用文件多阶段构建分离编译环境和运行时环境定期运行docker system prune清理缓存7. 进阶技巧与自动化对于团队协作我建议把Docker构建集成到CI/CD流程。这里分享一个实用的Azure Pipelines配置片段steps: - task: Docker2 inputs: containerRegistry: MyDockerRegistry repository: mywebapp command: buildAndPush Dockerfile: **/Dockerfile tags: | $(Build.BuildNumber) latest本地开发时可以用docker-compose.yml管理多容器version: 3.8 services: web: image: mywebapp:v1 ports: - 8080:80 volumes: - ./appdata:C:\appdata db: image: mcr.microsoft.com/mssql/server:2019-latest environment: SA_PASSWORD: YourStrongPassw0rd对于需要HTTPS的场景可以通过反向代理处理或者直接在IIS容器中配置证书RUN Import-Module WebAdministration; \ New-WebBinding -Name Default Web Site -Protocol https -Port 443; \ $cert New-SelfSignedCertificate -DnsName localhost -CertStoreLocation cert:\LocalMachine\My; \ $thumb $cert.Thumbprint; \ New-Item -Path IIS:\SslBindings\0.0.0.0!443 -Value $thumb这些年在Windows容器方面踩过的坑让我明白定期备份镜像和数据库卷非常重要。建议设置定时任务执行docker exec sqlserver sqlcmd -Q BACKUP DATABASE [MyDB] TO DISK/var/opt/mssql/backup/MyDB.bak docker commit webapp webapp_backup_$(date %Y%m%d)