免费静态托管 等 | 笔记

引言 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

自制 Railway Button

https://railway.app/button Deploy on Railway

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

1
flyctl auth login

3. 开始

参考: Working with Fly Applications
1
flyctl info
1
2
flyctl status
flyctl logs

4. Deploy Your Application via Dockerfile

参考: Deploy Your Application via Dockerfile 在 Dockerfile 目录执行
1
fly launch

部署 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手册