构建博客网站

Hugo 

Posted by 谌中钱 on 2026-01-15

1 技术选型

由于博客网站主要用来记录博主的文章和日常,这里选择使用静态框架 Hugo 进行搭建, 访问速度更快, 维护成本更低。

  • 静态框架:Hugo
    • 框架主题:Clean White
  • 部署方式:Docker + Nginx + GitHub Actions

2 使用 Hugo 静态框架

Hugo 是最受欢迎的开源静态网站生成器之一。凭借其惊人的速度和灵活性,Hugo 让搭建网站重新变得有趣。

2.1 本地化开发

2.1.1 Window 11 环境

 1# 1 安装 Hugo
 2
 3# 查询本地是否已经安装
 4winget list | findstr Hugo
 5# Hugo   Hugo.Hugo   0.153.0   0.159.0   winget
 6
 7# 搜索远程仓库 Hugo 最新版本
 8winget search Hugo
 9# Name            Id                    Version  Match         Source
10# -------------------------------------------------------------------
11# Hugo            Hugo.Hugo             0.159.0                winget
12# Hugo (Deploy)   Hugo.Hugo.Deploy      0.150.0  Command: hugo winget
13# Hugo (Extended) Hugo.Hugo.Extended    0.159.0                winget
14# 希沃集控        Seewo.SeewoHugo       1.4.5.57               winget
15# 掌上看班        Seewo.SeewoHugoKanban 1.4.5.68               winget
16
17# 安装/更新指定版本 Hugo
18winget install --id Hugo.Hugo --version 0.159.0
19
20# 查询认证一下
21winget list | findstr Hugo
22# Hugo   Hugo.Hugo   0.159.0   winget
23hugo version
24# hugo v0.159.0-2ed7d193cfdfcf11808fb2a921a9429423b0ebe9 windows/amd64 BuildDate=2026-03-23T18:16:59Z VendorInfo=gohugoio
25
26
27
28# 2 使用 Hugo 创建站点
29
30# 创建站点
31hugo new project D:\dev\workspace\blog && cd /d D:\dev\workspace\blog
32
33# 下载主题 hugo-theme-cleanwhite
34git clone --depth 1 https://github.com/zhaohuabing/hugo-theme-cleanwhite.git themes/hugo-theme-cleanwhite
35# 删除主题 git 相关信息
36cd themes\hugo-theme-cleanwhite && rd /s /q .git & del /f /q .gitignore
37# 修改站点主题为 hugo-theme-cleanwhite
38cd ..\.. && echo theme = 'hugo-theme-cleanwhite' >> hugo.toml
39
40
41
42# 3 启动站点的服务器测试模式
43# --bind 0.0.0.0 是为了监听 IPv4 所有网络地址,让 手机 等设备可以通过 局域网 (同一 WiFi 下) 访问 电脑 的站点,进行移动端测试
44hugo server --bind 0.0.0.0

2.1.2 macOS 环境

2.2 目录结构

  • archetypes:存放新内容的模板(优先级高于主题的模版)
    • default.md:命令新建 新内容 的默认模板(hugo new test.md
    • post.md:命令新建 文章 的模板(hugo new post/20260115-building-blog-site.md
  • assets:存放需要 Hugo 处理压缩的文件,需要通过代码管道调用
  • content:存放构成网站内容的文章、页面等文件(可 手动 或 命令 创建)
    • post:存放文章文件
    • 其他目录:存放页面文件
  • data:存放数据文件
  • i18n:存放多语言网站的翻译表
  • layouts:存放新内容的各种布局模板(优先级高于主题的模版,主题二次开发的文件一般放这里)
    • baseof.html:所有内容基础结构模板
      • _partials
        • head.html:元数据、脚本等信息模版
        • nav.html:头部导航模板
        • footer.html:尾部信息模板
    • home.html:首页模板
      • _partials:
        • portfolio.html:首页内容容器模板
          • posts.html:文章列表容器模板
            • post_list.html:文章列表模板
            • pagination.html:文章分页模板
            • sidebar.html:右侧信息模板
    • post.html:文章内容模板
      • _partials:
        • reward.html:赞赏模板
        • comments.html:评论模板
    • taxonomy:
      • category.html:分类页面模板
      • tag.html:标签页面模板
      • _partials:
        • category.html:分类,标签列表模板
        • posts.html:文章列表容器模板
          • post_list.html:文章列表模板
          • pagination.html:文章分页模板
          • sidebar.html:右侧信息模板
    • archive.html:归档模板
      • _partials:
        • sidebar.html:右侧信息模板
    • about.html:关于我模板
      • _partials:
        • comments.html:评论模板
        • sidebar.html:右侧信息模板
    • search/list.html:搜索结果模板
      • _partials:
        • search-algolia.html:Algolia 搜索结果模板
        • search-pagefind.html:Pagefind 搜索结果模板
        • sidebar.html:右侧信息模板
  • public:存放项目构建结果文件
  • static:存放项目构建时将被复制到 public 目录的静态文件
    • img:存放图片资源
  • theme:存放主题文件
    • hugo-theme-cleanwhite
      • exampleSite:主题作者提供的参考站点,可以参考配置
  • hugo.toml:项目配置文件

2.3 项目配置

2.3.1 配置文件

  • 作者配置 ./hugo.toml
  1# 生产构建时,生成所有正式链接的唯一基础地址
  2# sitemap.xml(网站地图)、robots.txt(爬虫协议)、页面 canonical 标签 等 SEO 核心文件必依赖它
  3baseURL = 'https://templechann.com'
  4# locale = 'en-us'
  5locale = 'zh-cn'
  6title = 'Temple Blog'
  7theme = 'hugo-theme-cleanwhite'
  8
  9buildFuture = true # 构建包含未来日期的文章
 10hasCJKLanguage = true # 自动处理中日韩文字,解决默认配置下的排版、摘要、字数统计 BUG
 11enableRobotsTXT = true # 自动在你的网站根目录生成 robots.txt 文件
 12cleanDestinationDir = true # 构建时清空历史文件
 13
 14[markup]
 15  [markup.highlight]
 16    style = "nord" # 代码块高亮,https://xyproto.github.io/splash/docs/all.html
 17    lineNos = true # 显示行号
 18    lineNumbersInTable = false
 19  [markup.goldmark]
 20    [markup.goldmark.renderer]
 21      unsafe = true # markdown 中使用 html
 22    [markup.goldmark.extensions]
 23      [markup.goldmark.extensions.passthrough]
 24        enable = true
 25        [markup.goldmark.extensions.passthrough.delimiters]
 26          block = [['\[', '\]'], ['$$', '$$']]
 27          inline = [['\(', '\)']]
 28
 29[pagination]
 30  pagerSize = 10 # frontpage pagination
 31
 32[mediaTypes]
 33  [mediaTypes.'font/woff']
 34    suffixes = ['woff']
 35  [mediaTypes.'font/woff2']
 36    suffixes = ['woff2']
 37
 38[outputs]
 39# home = ["HTML", "RSS", "Algolia"]
 40home = ["HTML", "RSS"]
 41
 42[services]
 43  # Enable comments by entering your Disqus shortname
 44  [services.disqus]
 45    shortname = ""
 46  [services.googleAnalytics]
 47    id = ""
 48
 49[outputFormats.Algolia]
 50# baseName = "algolia"
 51# isPlainText = true
 52# mediaType = "application/json"
 53# notAlternative = true
 54
 55[params]
 56  header_image = "img/home-bg.png"
 57  slogan = "山高自有客行路,水深自有渡船人"
 58  SEOTitle = "谌中钱的博客 | Temple Blog"
 59  description = "谌中钱(言戈,Temple Chan),男,29岁,179cm,65kg,摩羯座,ESTJ,汉族,中共团员,1996年1月14日出生于湖北省武汉市黄陂区,祖籍河南洛阳一带,始祖春秋时期郑国大夫裨谌。理学学士学位,主修计算机科学,中国内地不知名程序员,腾讯、Coupang、阿里云 前搬砖人,爬界科技 创始人、首席执行官。"
 60  keyword = "谌中钱, 言戈, 在下言戈, Temple Chan, Temple, templechan, templechann, templechannn, 谌中钱的博客, 博客网站, 博客, 编程技术"
 61  
 62  image_404 = "img/post-bg-404.png"
 63  title_404 = "你页面不存在"
 64  omit_categories = false # 隐藏分类菜单
 65  upstreamAttribution = false # 显示主题作者信息
 66  dark_mode_toggle = false # 是否开启暗黑模式
 67  isSearch = false # 是否显示搜索图标
 68
 69  # 备案信息
 70  isBeian = true # 是否显示备案信息
 71  icp = "鄂ICP备2025165689号-1"
 72  gongan = "鄂公网安备42018502008405号"
 73  gongan_num = "42018502008405"
 74  
 75  # Sidebar settings
 76  sidebar_avatar = "img/templechan.jpg"      # use absolute URL, seeing it's used in both `/` and `/about/`
 77  sidebar_about_description = "谌中钱(言戈,Temple Chan),男,29岁,179cm,65kg,摩羯座,ESTJ,汉族,中共团员,1996年1月14日出生于湖北省武汉市黄陂区,祖籍河南洛阳一带,始祖春秋时期郑国大夫裨谌。理学学士学位,主修计算机科学,中国内地不知名程序员,腾讯、Coupang、阿里云 前搬砖人,爬界科技 创始人、首席执行官。"
 78  about_me = true
 79  bookmarks = true
 80  featured_tags = true 
 81  featured_condition_size = 0
 82  friends = true
 83
 84  # Last posts
 85  last_posts = true
 86  #last_posts_title = "LAST POSTS"
 87  #last_posts_count = 5
 88
 89  #Enable wechat pay & alipay to allow readers send reward money if they like the articles 
 90  reward = false 
 91  reward_guide = "您的咖啡能让我写出少 Bug 的代码 ☕️ ~" 
 92
 93  # Twikoo comments
 94  # Follow https://twikoo.js.org/ to set up your own env_id
 95  twikoo_env_id = ""
 96
 97  # Artalk comments
 98  # Follow https://artalk.js.org/ to set up your own server
 99  artalk_enable = false
100  artalk_server = "https://xxx.xxx.com"
101  artalk_site = "xxx blog"
102
103  # We need a proxy to access Disqus api in China
104  # Follow https://github.com/zhaohuabing/disqus-php-api to set up your own disqus proxy
105  disqus_proxy = ""
106  disqus_site = ""
107
108  # algolia site search
109  algolia_search = false
110  algolia_appId = ""
111  algolia_indexName = ""
112  algolia_apiKey = ""
113
114  # leancloud storage for page view counter
115  page_view_counter = false
116  leancloud_app_id = ""
117  leancloud_app_key = ""
118
119  # Baidu Analytics
120  ba_track_id = ""
121
122  # Include any custom CSS and/or JS files, url or relative to /static folder
123  #custom_css = ["css/lightbox.css", "https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.2/animate.min.css", "css/main.css"]
124  #custom_js = ["js/lightbox.js", "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js", "js/main.js"]
125  
126  [params.algolia]
127  vars = ["title", "summary", "date", "publishdate", "expirydate", "permalink"]
128  params = ["categories", "tags"] 
129
130  [params.social]
131  rss                    = true
132
133  email                  = "templechan@126.com"
134  github                 = "https://github.com/templechan"
135#   linkedin               = "https://www.linkedin.com/in/templechan"
136  wechat                 = "img/social/social-wechat.png"
137  qq                     = "img/social/social-qq.png"
138  whatsapp               = "img/social/social-whatsapp.jpg"
139  messenger              = "img/social/social-messenger.jpg"
140  telegram               = "img/social/social-telegram.jpg"
141  line                   = "img/social/social-line.jpg"
142  kakaotalk              = "img/social/social-kakaotalk.png"
143  zalo                   = "img/social/social-zalo.jpg"
144
145  tiktok                 = "https://www.douyin.com/user/MS4wLjABAAAA84o70K2c9LEZXJ9fHp0deVyvxMudni7rQgAahjtoWIX34SCg61Gbf6H4HYKneZsW"
146  wechatChannels         = "img/social/social-wechat-channels.jpg"
147  bilibili               = "https://space.bilibili.com/3546602247555636"
148  rednote                = "https://www.xiaohongshu.com/user/profile/658fc18d0000000022017e5a"
149  wechatPublicPlatform   = "img/social/social-wechat-public-platform.jpg"
150  csdn                   = "https://blog.csdn.net/2301_82344373"
151  juejin                 = "https://juejin.cn/user/3617844579024624"
152  zhihu                  = "https://www.zhihu.com/people/templechan"
153  weibo                  = "https://weibo.com/templechan1024"
154  facebook               = "https://www.facebook.com/templechann"
155  instagram              = "https://www.instagram.com/templechann"
156  tiktokInternational    = "https://www.tiktok.com/@templechan"
157  x                      = "https://x.com/templechann"
158  snapchat               = "https://www.snapchat.com/@templechann"
159  vk                     = "https://vk.com/templechan"
160  youtube                = "https://www.youtube.com/@templechann"
161  threads                = "https://www.threads.com/@templechann"
162
163  [[params.bookmark_link]]
164  title =  "爬界科技"
165  href =  "https://climbtw.com"
166
167  [[params.friend_link]]
168  title = "赵华冰的博客"
169  href =  "https://www.zhaohuabing.com"
170  [[params.friend_link]]
171  title = "Beyond the Void"
172  href =  "https://byvoid.com/zhs"
173
174  [[params.additional_menus]]
175  title =  "ARCHIVE"
176  href =  "/archive"
177  [[params.additional_menus]]
178  title =  "ABOUT"
179  href =  "/about"

2.3.2 内容元数据配置

配置于 Markdown 文件头部。

作者配置:

 1---
 2layout: post
 3title: 构建博客网站
 4subtitle: 
 5description: 涉及 Hugo 静态框架,自动化部署,评论服务,SEO 等。
 6author: 谌中钱
 7date: 2026-01-15
 8lastMod: 
 9image: img/post-bg-default.png
10categories: 
11- programming
12tags: 
13- 解决方案
14slug: building-blog-site
15metadata:
16- text: Hugo
17  link: https://gohugo.io
18weight: 2
19showtoc: true
20draft: false
21---

2.3.3 命令新建文章模板

  • 命令:hugo new post/20260115-building-blog-site.md

  • 作者文章模版 ./archetypes/post.md

     1---
     2layout: post
     3title: 
     4subtitle: 
     5description: 涉及  等。
     6author: 谌中钱
     7date: 2026-01-15
     8lastMod: 
     9image: img/post-bg-default.png
    10categories: 
    11- 
    12tags: 
    13- 
    14slug: 
    15metadata:
    16- text: 
    17  link: 
    18weight: 2
    19showtoc: true
    20draft: false
    21---
    22
    23<br />
    24
    25<!-- @import "[TOC]" {cmd="toc" depthFrom=1 depthTo=6} -->
    

2.4 自动化部署

实现推送代码到 Github 上的 main 分支时,会自动部署到 云服务器。

2.4.1 云服务器 SSH 配置

让 Github 可以用 云服务器的私钥 去连接 云服务器。

 1# 云服务器上生成 公钥(id_ed25519.pub) 和 私钥(id_ed25519)
 2ssh-keygen -t ed25519 -C "templechan@126.com"
 3# 将 公钥(id_ed25519.pub) 添加到云服务器的 ~/.ssh/authorized_keys 文件中
 4cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
 5
 6# 查看 私钥
 7cat ~/.ssh/id_ed25519
 8# 登录 GitHub -> 站点仓库下的 Settings -> Secrets and variables -> Actions -> New repository secret 中添加 3 个常量:
 9
10# Name: BLOG_SSH_PRIVATE_KEY
11# Value: 你的私钥内容(注意不要添加换行符,可以直接从文件复制)
12
13# Name: BLOG_SERVER_IP
14# Value: 部署服务器的 IP
15
16# Name: BLOG_USER
17# Value: 部署服务器的 user

2.4.2 编写脚本

  • ./.github/workflows/blog_deploy.yml:工作流文件,用来连接云服务器,执行云服务器的部署脚本
  • ./deploy.sh:云服务器的部署脚本
  • ./Dockfile:镜像构建文件
  • ./docker-compose.yml:容器构建文件
2.4.2.1 工作流文件
  • .github/workflows/blog_deploy.yml:
 1name: Deploy to Server
 2
 3on:
 4  push:
 5    branches:
 6      - main
 7 
 8jobs:
 9  deploy:
10    runs-on: ubuntu-latest
11    steps:
12    - name: Checkout code
13      uses: actions/checkout@v2
14 
15    - name: Install SSH key
16      uses: webfactory/ssh-agent@v0.5.3
17      with:
18        ssh-private-key: ${{ secrets.BLOG_SSH_PRIVATE_KEY }}
19 
20    - name: Adding Known Hosts
21      run: ssh-keyscan ${{ secrets.BLOG_SERVER_IP }} >> ~/.ssh/known_hosts
22 
23    - name: Deploy to Server
24      run: ssh ${{ secrets.BLOG_USER }}@${{ secrets.BLOG_SERVER_IP }} 'bash -s' < ./deploy.sh
2.4.2.2 部署脚本
  • ./deploy.sh:
 1cd /usr/local/src
 2rm -rf /usr/local/src/blog
 3
 4if ! command -v git &> /dev/null; then
 5    dnf install -y git
 6    git config --global user.email "templechan@126.com"
 7    git config --global user.name "templechan"
 8fi
 9
10# 设置 GitHub 国内镜像源
11git config --global url."https://bgithub.xyz/".insteadOf https://github.com/
12# 如果失效,则删除旧的,设置的新的,记得先测试下是否有效
13# git config --global --unset url."https://bgithub.xyz/".insteadOf https://github.com/
14# git config --global url."https://kkgithub.com/".insteadOf https://github.com/
15git clone -b main https://github.com/templechan/blog.git
16
17if [ -d /usr/local/src/blog ] && [ -n "$(ls -A /usr/local/src/blog)" ]; then
18    cd /usr/local/src/blog
19    if ! command -v mogrify &> /dev/null; then
20        # 安装图片压缩包 ImageMagick
21        dnf install -y ImageMagick bc parallel
22        # 配置ImageMagick策略文件
23        sed -i '/<policy domain="coder" rights=".*" pattern="PNG,JPG,JPEG,WEBP"/d;/<policymap>/a \  <policy domain="coder" rights="read|write" pattern="PNG,JPG,JPEG,WEBP" />;s/<policy domain="resource" name="memory" value="[^"]*"/<policy domain="resource" name="memory" value="256MiB"/;s/<policy domain="resource" name="disk" value="[^"]*"/<policy domain="resource" name="disk" value="1GiB"/;s/<policy domain="resource" name="width" value="[^"]*"/<policy domain="resource" name="width" value="8KP"/;s/<policy domain="resource" name="height" value="[^"]*"/<policy domain="resource" name="height" value="8KP"/;s/<policy domain="resource" name="thread" value="[^"]*"/<policy domain="resource" name="thread" value="2"/;s/<policy domain="resource" name="throttle" value="[^"]*"/<policy domain="resource" name="throttle" value="1"/;s/<policy domain="resource" name="map" value="[^"]*"/<policy domain="resource" name="map" value="256MiB"/' /etc/ImageMagick-7/policy.xml
24    fi
25
26    # 手动压缩图片资源(会覆盖源文件,注意保留源文件)
27    # 1 图片大小判断 >100KB 才压缩
28    # 2 动态质量计算算法 75 - 20*l(...)
29    # 3 质量限制 15~60
30    # 4 PNG / JPG / WebP 压缩参数
31    # 5 统计节省空间算法
32    # 6 并行数 -j 2
33    
34    # 进度交互版
35    # start=$SECONDS; find ./static/img/ \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" -o -name "*.webp" \) -type f -print0 | parallel -0 -j 2 --bar 'f="{}";old_size=$(stat -c %s "$f");if [ $old_size -gt 102400 ]; then q=$(echo "scale=0;80-40*l($old_size/102400)/l(10)" | bc -l | awk "{print int(\$1+0.5)}");q=$((q<15?15:q>60?60:q));ext="${f##*.}";case "$ext" in png) mogrify -strip -quality $q -define png:compression-level=9 -colors 128 "$f" 2>/dev/null ;; jpg|jpeg) mogrify -strip -quality $q -sampling-factor 4:2:0 -density 72x72 "$f" 2>/dev/null ;; webp) mogrify -strip -quality $((q-5)) -define webp:method=6 "$f" 2>/dev/null ;; esac;new_size=$(stat -c %s "$f");save=$((old_size-new_size));echo "$save" >> /tmp/img_save.txt;fi'; total_save=$(awk '{sum+=$1}END{print sum}' /tmp/img_save.txt 2>/dev/null||0); count=$(wc -l </tmp/img_save.txt 2>/dev/null||0); rm -f /tmp/img_save.txt; cost=$((SECONDS - start)); min=$((cost / 60)); sec=$((cost % 60)); echo -e "\n\033[1;32m=== 压缩完成 ===\033[0m"; echo "✅ 压缩数量:$count 张"; echo "✅ 节省空间:$((total_save/1024)) KB ($((total_save/1024/1024)) MB)"; echo -e "✅ 耗时:${min}分${sec}秒"; echo -e "\033[1;32m================\033[0m"
36    # GitHub Actions 不支持交互专用
37    start=$SECONDS; find ./static/img/ \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" -o -name "*.webp" \) -type f -print0 | parallel -0 -j 2 'f="{}";old_size=$(stat -c %s "$f");if [ $old_size -gt 102400 ]; then q=$(echo "scale=0;80-40*l($old_size/102400)/l(10)" | bc -l | awk "{print int(\$1+0.5)}");q=$((q<15?15:q>60?60:q));ext="${f##*.}";case "$ext" in png) mogrify -strip -quality $q -define png:compression-level=9 -colors 128 "$f" 2>/dev/null ;; jpg|jpeg) mogrify -strip -quality $q -sampling-factor 4:2:0 -density 72x72 "$f" 2>/dev/null ;; webp) mogrify -strip -quality $((q-5)) -define webp:method=6 "$f" 2>/dev/null ;; esac;new_size=$(stat -c %s "$f");save=$((old_size-new_size));echo "$save" >> /tmp/img_save.txt;fi' 2>/dev/null; total_save=$(awk '{sum+=$1}END{print sum}' /tmp/img_save.txt 2>/dev/null||0); count=$(wc -l </tmp/img_save.txt 2>/dev/null||0); rm -f /tmp/img_save.txt; cost=$((SECONDS-start)); min=$((cost/60)); sec=$((cost%60)); echo -e "\n=== 图片压缩完成 ==="; echo "压缩数量:$count 张"; echo "节省空间:$((total_save/1024)) KB ($((total_save/1024/1024)) MB)"; echo "耗时:${min}${sec}秒"; echo "===================="
38
39    if ! command -v docker &> /dev/null; then
40        # 卸载旧版 Docker
41        dnf remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
42        # 自动启用仓库
43        sed -i 's/enabled=0/enabled=1/g' /etc/yum.repos.d/OpenCloudOS.repo
44        # 保存后,清除重建缓存
45        dnf clean all && dnf makecache
46
47        # 设置 Docker 国内软件源
48        dnf install -y dnf-plugins-core
49        # dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
50        dnf config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
51
52        # 安装 Docker
53        dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
54
55        # 启动 Docker
56        systemctl start docker
57        # 设置 Docker 自启
58        systemctl enable docker
59    fi
60    # 设置 Docker 国内镜像代理
61    tee /etc/docker/daemon.json <<EOF
62    {
63    "registry-mirrors": [
64        "https://docker.1ms.run",
65        "https://dockerproxy.net",
66        "https://proxy.vvvv.ee",
67        "https://dockerproxy.link"
68    ]
69    }
70EOF
71    systemctl daemon-reload
72
73    docker rm -f blog >/dev/null 2>&1
74    docker rmi -f blog >/dev/null 2>&1
75
76    docker compose up -d --build
77fi
2.4.2.3 镜像构建文件
  • ./Dockfile:
 1# 阶段1:Hugo 构建环境(临时镜像,用完丢弃)
 2FROM hugomods/hugo:std-base-0.159.0 AS builder
 3WORKDIR /src
 4COPY . .
 5RUN hugo --minify
 6
 7# 阶段2:生产运行环境(仅保留静态文件 + Nginx,超小体积)
 8FROM nginx:alpine
 9COPY --from=builder /src/public/ /usr/share/nginx/html/
10EXPOSE 80
2.4.2.4 容器构建启动文件
  • ./docker-compose.yml:
 1version: '3.8'
 2
 3services:
 4  blog:
 5    # 等价于 docker build -t blog . (自动构建当前目录的Dockerfile)
 6    build: .
 7    # 容器名称
 8    container_name: blog
 9    # 端口映射 主机81 → 容器80
10    ports:
11      - "81:80"
12    # 开机/崩溃自动重启
13    restart: always

2.5 部署云服务器 Nginx 服务

部署一个 Nginx 服务监听 云服务器 的 80 端口,然后通过端口转发到各种服务,参考 《Nginx 使用手册》

2.6 Twikoo 评论服务

Twikoo 是一个简洁、安全、免费的静态网站评论系统。

2.6.1 云函数部署

2.6.1.1 Docker 方式
1# 1 创建文件夹,用来存放 数据文件
2mkdir -p /usr/local/src/twikoo/data && cd /usr/local/src/twikoo
3
4# 2 创建启动容器
5docker compose up -d
6
7# 3 修改云服务器 nginx.conf 配置,让 二级域名 xxx.templechann.com 反向代理到 twikoo 容器映射的 宿主机端口 82,重启 nginx 容器
2.6.1.1.1 容器构建文件

./docker-compose.yml:

 1version: '3'
 2
 3services:
 4  twikoo:
 5    image: imaegoo/twikoo:1.6.42
 6    container_name: twikoo
 7    restart: always
 8    ports:
 9      - "82:8080"
10    environment:
11      - TWIKOO_THROTTLE=1000
12    volumes:
13      - ./data:/app/data

2.6.2 站点修改

2.6.1 修改站点配置

./hugo.toml:

1# Twikoo comments
2# Follow https://twikoo.js.org/ to set up your own env_id
3twikoo_env_id = "https://xxx.templechann.com/" # 云函数部署的地址
2.6.2 修改主题代码
  • 修改 前端引用的 twikoo.js,与 云函数版本 保持一致,这里用的 1.6.42:

./layouts/_partials/comments.html:

1<!-- <script src="https://cdn.jsdelivr.net/npm/twikoo@1.4.14/dist/twikoo.all.min.js"></script> -->
2<script src="https://registry.npmmirror.com/twikoo/1.6.42/files/dist/twikoo.all.min.js"></script>
  • 主题 的 bootstrap.min.css 对 上传图像 样式有覆盖
  • 主题 hugo-theme-cleanwhite 的样式对 头像 div 有覆盖
  • 需要修改:

./layouts/_partials/comments.html:

1<style>
2.twikoo .tk-input-image {
3    display: none;
4}
5.twikoo img {
6    margin: 0;
7}
8</style>
9<div id="twikoo-tcomment"></div>

2.6.3 Twikoo 设置

在 站点文章 下方会有 Twikoo 评论组件,组件右下侧有 设置 按钮,第一次打开 设置 需要 配置密码。

2.6.3.1 头像配置

Weavatar,多端多元化的统一头像服务。

  • Weavatar 官网: https://weavatar.com
  • 配置方法:
    • 去 Weavatar 官网 用 邮箱 注册 和 上传 自定义头像。
    • 在 Twikoo 设置 -> 配置管理 -> 通用,按如下配置:
GRAVATAR_CDN: weavatar.com
2.6.3.2 Server酱 (ServerChan) 评论推送

Server酱,英文名 ServerChan,是一款 手机 和 服务器、智能设备 之间的通信软件。

  • Server酱 官网: https://sct.ftqq.com
  • 配置方法:
    • 去 Server酱 官网 注册,获取 SendKey,然后在 通道配置 里面设置 通知方式,我使用的 方糖的微信服务号。
    • 在 Twikoo 设置 -> 配置管理 -> 即时通知,按如下配置:
PUSHOO_CHANNEL: serverchan
PUSHOO_TOKEN: 填写获取的 SendKey
  • 注意:
    • ServerChan 目前由于用户量比较大,免费的通知额度只有 5 条。
    • 自己发布的评论 (按邮箱判断),不会通知。

2.7 SEO