引言
GitHub Pages
纯静态托管
GitHub 集成
Vercel
静态托管, Node.js, Python, PHP, Java 等
GitHub 集成
免费有流量限制
免费有最大执行时长限制: 5s
支持配置 一键部署 按钮
Cloudflare Pages
静态托管
Node.js, 常见静态网页生成器
GitHub 集成
Netlify
静态托管, Node.js, Python, PHP, Java 等
GitHub 集成
支持配置 一键部署 按钮
Railway
静态托管, Node.js, Python, PHP, Java 等
Docker 支持
GitHub 集成
无需信用卡验证
不休眠, 每月 $5 免费额度
免费: 最大执行时长: 5分钟 或者 3分钟, 记不清了
支持配置 一键部署 按钮
Heroku
静态托管, Node.js, Python, PHP, Java 等
Docker 支持
GitHub 集成
休眠, 可以定时访问防止休眠, 每月近半月的免费时长
无需信用卡验证, 免费 500h/月, 使用信用卡验证后, 免费 1000h/月
支持配置 一键部署 按钮
Koyeb
静态托管, Node.js, Python, PHP, Java 等
Docker 支持 (来自 Docker Hub 的镜像)
CLI 部署
GitHub 仓库集成
Fly.io
静态托管, Node.js, Python, PHP, Java 等
Docker 支持
仅 CLI 部署
需 信用卡 验证
Render
静态托管, Node.js, Python, PHP, Java 等
Docker 支持
CLI 部署
GitHub 仓库集成
支持配置 一键部署
Kubernauts
k8s
Glitch - Pricing
[
Home - Replit ]
免费在线环境, 休眠, 类似 GitHub, 但可自定义环境运行项目
1. GitHub Pages
https://pages.github.com/
2. Vercel
https://vercel.com
这里 只能输入 公开的仓库地址
下面在 GitHub 私有仓库,利用 GitHub App 来安装 Vercel,
更新: 错误,GitHub Marketplace 没有 Vercel App, 通过下方来导入私有仓库
目测只能创建完后,修改分支
更新: 可以通过修改下方链接来创建 Project, 这样创建时就能自定义分支
1 https://vercel.com/new/clone?repository-url=https://github.com/yiyungent/yiyungent.github.io/tree/gh-pages
修改 branch 为 gh-pages
由于直接使用 gh-pages 构建好的结果,因此下方直接置空
现在流程,本地改完后,push 到 GitHub主分支 ( master ),然后触发 GitHub Actions 构建完成到 gh-pages,
然后这会触发两次 Vercel 的 Deployment , 第一次 来自 master, 第二次来自 GitHub Actions 推送到的 gh-pages,
第一次是不正确的,会导致 404, 第二次即可正常访问
完成
https://yiyungent.vercel.app/
https://yiyungent-yiyungent.vercel.app/
https://yiyungent-git-gh-pages-yiyungent.vercel.app/
3. Cloudflare Pages
https://pages.cloudflare.com/
完成
https://yiyungent.pages.dev/
4. Netlify
https://www.netlify.com/
完成
https://yiyungent.netlify.app
Q&A
补充
类似免费
参考:
建站资源|免费的(Docker)容器服务 - 简书
https://railway.app/
https://www.heroku.com/
railway
支持 Docker
https://railway.app/button
heroku
支持 Docker
自制 Heroku 模板
参考:
https://github.com/libsgh/PanIndex/blob/main/app.json
PanIndex/heroku.yml at main · libsgh/PanIndex
仓库根目录: app.json : 模板描述, 环境变量
仓库根目录: heroku.yml : 如何 build
heroku.yml 1 2 3 build: docker: web: docker/Dockerfile
app.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 { "name": "PanIndex", "description": "简易的网盘目录列表", "keywords": [ "PanIndex", "cloud.189.cn", "teambition" ], "env": { "TZ": { "description": "时区", "value": "Asia/Shanghai" }, "LANG": { "description": "编码格式", "value": "en_US.UTF-8" }, "PAN_INDEX_VERSION": { "description": "PanIndex版本,默认为最新版,查看:https://github.com/libsgh/PanIndex/releases", "required": false, "value": "" }, "PAN_INDEX_CONFIG": { "description": "程序配置,json格式,从后台获取复制到这里", "required": false, "value": "" }, "PAN_INDEX_DEBUG": { "description": "调试模式,设置为true将输出更多日志", "value": "false" } }, "website": "http://github.com/libsgh/PanIndex", "repository": "http://github.com/libsgh/PanIndex", "stack": "container", "features": [ "runtime-dyno-metadata" ] }
最后生成效果:
1 https://heroku.com/deploy?template=https://github.com/libsgh/PanIndex
koyeb
https://www.koyeb.com/
fly.io
https://fly.io/
支持 Docker
Render
https://render.com/
支持 Docker
Kubernauts
参考:
Deploy Ghost in a Spot Namespace on Kubernautic from your browser | by Arash | Kubernauts
Kubernauts GmbH | Pricing Managed Kubernetes Services with Rancher Dedicated as a Service
k8s 容器服务
部署 ASP.NET Core 到 Railway
参考:
Squidex/squidex: Headless CMS and Content Managment Hub
Running a .NET 5 web app on Railway - rendle.dev
Railway Docker 配置
若以仓库根目录为模板, 则 Dockerfile 必须位于仓库根目录
仓库根目录/Dockerfile
Dockerfile 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # Railway Dockerfile FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base # ... # for Railway WORKDIR /app ADD railway-entrypoint.sh ./railway-entrypoint.sh RUN chmod +x ./railway-entrypoint.sh # ... FROM base AS final WORKDIR /app COPY --from=publish /app/publish . #ENTRYPOINT ["dotnet", "WebScreenshot.dll"] ENTRYPOINT ["/bin/sh", "./railway-entrypoint.sh"]
仓库根目录/railway-entrypoint.sh
railway-entrypoint.sh 1 2 3 4 5 6 7 8 #!/bin/sh # 注意: $PORT 非常重要, Railway 必须监听此端口 export ASPNETCORE_URLS="http://+:$PORT" export ASPNETCORE_ENVIRONMENT="Production" export TZ="Asia/Shanghai" dotnet WebScreenshot.dll
部署 ASP.NET Core 到 Heroku
参考:
Deploy .Net Core App to Heroku. In this article, we will see how we can… | by Vikas Sharma | Null Exception | Medium
Deploying .NET Core to Heroku - DEV Community
Squidex/squidex: Headless CMS and Content Managment Hub
Building Docker Images with heroku.yml | Heroku Dev Center
Creating a 'Deploy to Heroku' Button | Heroku Dev Center
Heroku 基础配置
仓库根目录/app.json
app.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 { "name": "Squidex", "description": "Headless CMS and Content Managment Hub", "website": "https://squidex.io/", "repository": "https://github.com/Squidex/squidex", "logo": "https://avatars.githubusercontent.com/u/25371797?s=200&v=4", "success_url": "/", "env": { "DOMAIN": { "description": "The domain name under which your instance is available", "value": "https://[YOUR-HEROKU-APPNAME].herokuapp.com" }, "MONGO_USERNAME": { "description": "Mongo Username, follow https://devcenter.heroku.com/articles/ormongo#open-the-dashboard to create a database named Squidex and then edit the deployment to reflect the credentials you used", "value": "Squidex" }, "MONGO_PASSWORD": { "description": "Mongo Password (see MONGO_USERNAME)", "value": "Squidex123" } }, "formation": { "web": { "quantity": 1, "size": "standard-1x" } }, "addons": [ { "plan": "ormongo:2-mmap", "as": "MONGO" } ], "stack": "container" }
仓库根目录/heroku.yml
heroku.yml 1 2 3 build: docker: web: packer/heroku/squidex/Dockerfile
PS:
heroku.yml: If you don’t include a run section, Heroku uses the CMD specified in the Dockerfile.
Heroku Docker 配置
需要注意 2 点:
- Heroku Docker 容器内部应用需要监听 $PORT 端口
- Heroku 对 ENTRYPOINT [ "dotnet", "HerokuApp.dll" ] 支持不好, 建议 CMD [ "dotnet", "HerokuApp.dll" ], 或则在 ENTRYPOINT 运行 bash
方式1
Dockerfile 1 2 3 4 5 # Heroku Dockerfile # ENTRYPOINT [ "dotnet", "HerokuApp.dll" ] # Use the following instead for Heroku CMD ASPNETCORE_URLS=http://*:$PORT dotnet HerokuApp.dll
方式2
在程序中写死监听端口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); // For running in Railway var portVar = Environment.GetEnvironmentVariable("PORT"); if (portVar is {Length: >0} && int.TryParse(portVar, out int port)) { webBuilder.ConfigureKestrel(options => { options.ListenAnyIP(port); }); } });
Dockerfile 1 2 3 # Heroku Dockerfile CMD [ "dotnet", "HerokuApp.dll" ]
方式3
heroku.yml
heroku.yml 1 2 3 build: docker: web: deploy/heroku/Dockerfile
deploy/heroku/Dockerfile
Dockerfile 1 2 3 4 5 6 7 8 9 # Heroku Dockerfile FROM yiyungent/webscreenshot:latest ADD heroku-entrypoint.sh /heroku-entrypoint.sh RUN chmod +x /heroku-entrypoint.sh ENTRYPOINT ["/bin/sh", "/heroku-entrypoint.sh"]
deploy/heroku/heroku-entrypoint.sh
heroku-entrypoint.sh 1 2 3 4 5 #!/bin/sh export ASPNETCORE_URLS="http://+:$PORT" dotnet WebScreenshot.dll
方式4
heroku.yml
注意: 此种方法, Docker build context 位于 src/WebApi/, 而不是 仓库根目录
heroku.yml 1 2 3 4 5 build: docker: web: src/WebApi/Dockerfile run: web: cd /app && dotnet WebApi.dll --urls="http://*:$PORT"
部署 ASP.NET Core 到 Render
参考:
Squidex/squidex: Headless CMS and Content Managment Hub
Deploy Docker — How to Use Docker | Render
部署 ASP.NET Core 到 fly.io
参考:
Installing flyctl
fly.io 与其它不一样,没有 Web 可视化面板,只能用 CLI 来创建 App
1. 安装 fly.io
Windows: PowerShell
1 iwr https://fly.io/install.ps1 -useb | iex
2. 登录 到 fly.io
3. 开始
参考:
Working with Fly Applications
1 2 flyctl status flyctl logs
4. Deploy Your Application via Dockerfile
参考:
Deploy Your Application via Dockerfile
在 Dockerfile 目录执行
部署 ASP.NET Core 实例
Railway
注意: 这里 Railway 的 Dockerfile 没有放在仓库根目录,因此 template 需指定为子目录
https://github.com/yiyungent/Dragonfly/tree/main/deploy/railway
Dockerfile
Dockerfile 1 2 3 4 5 6 7 8 9 10 # Railway Dockerfile # 注意: yiyungent/dragonfly:latest railway 会一直使用缓存,不会更新镜像 FROM yiyungent/dragonfly:v0.1.1 ADD railway-entrypoint.sh ./railway-entrypoint.sh RUN chmod +x ./railway-entrypoint.sh ADD railway-PluginCore.Config.json ./railway-PluginCore.Config.json ENTRYPOINT ["/bin/sh", "./railway-entrypoint.sh"]
railway-entrypoint.sh
railway-entrypoint.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #!/bin/sh # region env export ASPNETCORE_URLS="http://+:$PORT" export ASPNETCORE_ENVIRONMENT="Production" export TZ="Asia/Shanghai" # endregion env # region PluginCore echo {{hbeSeoContent}}#123;PLUGINCORE_ADMIN_USERNAME} echo {{hbeSeoContent}}#123;PLUGINCORE_ADMIN_PASSWORD} mkdir App_Data touch /app/App_Data/PluginCore.Config.json cat '/app/railway-PluginCore.Config.json' | sed "s/PLUGINCORE_ADMIN_USERNAME/{{hbeSeoContent}}#123;PLUGINCORE_ADMIN_USERNAME}/g" | tee '/app/App_Data/PluginCore.Config.json' cat '/app/App_Data/PluginCore.Config.json' | sed "s/PLUGINCORE_ADMIN_PASSWORD/{{hbeSeoContent}}#123;PLUGINCORE_ADMIN_PASSWORD}/g" | tee '/app/App_Data/PluginCore.Config.json' # endregion PluginCore dotnet WebApi.dll
railway-PluginCore.Config.json
railway-PluginCore.Config.json 1 {"Admin":{"UserName":"PLUGINCORE_ADMIN_USERNAME","Password":"PLUGINCORE_ADMIN_PASSWORD"},"FrontendMode":"LocalEmbedded","RemoteFrontend":"https://cdn.jsdelivr.net/gh/yiyungent/plugincore-admin-frontend@0.3.0/dist-cdn","PluginWidgetDebug":false}
Heroku
Dockerfile
Dockerfile 1 2 3 4 5 6 7 8 9 # Heroku Dockerfile FROM yiyungent/dragonfly:v0.1.1 ADD heroku-entrypoint.sh ./heroku-entrypoint.sh RUN chmod +x ./heroku-entrypoint.sh ADD heroku-PluginCore.Config.json ./heroku-PluginCore.Config.json ENTRYPOINT ["/bin/sh", "./heroku-entrypoint.sh"]
heroku-entrypoint.sh
heroku-entrypoint.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #!/bin/sh # region env export ASPNETCORE_URLS="http://+:$PORT" export ASPNETCORE_ENVIRONMENT="Production" export TZ="Asia/Shanghai" # endregion env # region PluginCore echo {{hbeSeoContent}}#123;PLUGINCORE_ADMIN_USERNAME} echo {{hbeSeoContent}}#123;PLUGINCORE_ADMIN_PASSWORD} mkdir App_Data touch /app/App_Data/PluginCore.Config.json cat '/app/heroku-PluginCore.Config.json' | sed "s/PLUGINCORE_ADMIN_USERNAME/{{hbeSeoContent}}#123;PLUGINCORE_ADMIN_USERNAME}/g" | tee '/app/App_Data/PluginCore.Config.json' cat '/app/App_Data/PluginCore.Config.json' | sed "s/PLUGINCORE_ADMIN_PASSWORD/{{hbeSeoContent}}#123;PLUGINCORE_ADMIN_PASSWORD}/g" | tee '/app/App_Data/PluginCore.Config.json' # endregion PluginCore dotnet WebApi.dll
heroku-PluginCore.Config.json
heroku-PluginCore.Config.json 1 {"Admin":{"UserName":"PLUGINCORE_ADMIN_USERNAME","Password":"PLUGINCORE_ADMIN_PASSWORD"},"FrontendMode":"LocalEmbedded","RemoteFrontend":"https://cdn.jsdelivr.net/gh/yiyungent/plugincore-admin-frontend@0.3.0/dist-cdn","PluginWidgetDebug":false}
app.json
app.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 { "name": "Dragonfly", "description": "Web 自动化平台 - Heroku Deploy", "keywords": ["yiyungent", "Dragonfly"], "website": "https://github.com/yiyungent/Dragonfly", "repository": "https://github.com/yiyungent/Dragonfly", "success_url": "/", "env": { "PLUGINCORE_ADMIN_USERNAME": { "description": "PluginCore Admin 用户名", "value": "admin", "required": true }, "PLUGINCORE_ADMIN_PASSWORD": { "description": "PluginCore Admin 密码", "value": "Dragonfly", "required": true } }, "stack": "container" }
heroku.yml
heroku.yml 1 2 3 build: docker: web: deploy/heroku/Dockerfile
参考
感谢帮助!
Freepaas | MJJ手册