文章

从 0 到 1 搭建 Jekyll + Chirpy 博客:系统踩坑、容器构建与 Arch 本机环境实录

从 0 到 1 搭建 Jekyll + Chirpy 博客:系统踩坑、容器构建与 Arch 本机环境实录

从 0 到 1 搭建 Jekyll + Chirpy 博客:系统踩坑、容器构建与 Arch 本机环境实录

本文记录我从 CentOS 服务器到本机 Arch Linux 搭建 Jekyll + Chirpy 的全过程,包含踩坑与解决方案:Ruby/Jekyll 安装、Docker 自建镜像、Chirpy 主题配置(头像与备案)、一键部署脚本、Nginx 反代等。文末有完整命令清单和常见错误处理。

1. 背景与目标

  • 博客框架:Jekyll(静态站点)
  • 主题:cotes2020/jekyll-theme-chirpy(通过 starter 使用主题 gem)
  • 部署形态:

    • 服务器(曾用 CentOS,后转容器)
    • 本机开发环境(Arch Linux)
  • 需求点:本地写作、容器构建、站点打包到 Web 根目录、主题头像与 ICP 备案信息、Nginx 反代。

2. CentOS 服务器踩坑纪要(为什么后面改用容器)

2.1 Ruby 版本过旧导致 Jekyll 无法安装

  • 系统自带 Ruby 2.5.x,而:

    • bundler >= 2.7 需要 Ruby ≥ 3.2
    • 多个依赖 gem(如 rouge)也要求更高版本 Ruby
  • 通过 RVM/Ruby 源码编译升级时,CentOS 8 的仓库和依赖(glibc-devel、openssl-devel 等)经常冲突或缺失,安装失败。

结论:在 CentOS 侧不再纠结本机 Ruby,改用 Docker 容器 固化构建环境,避免系统依赖地狱。


3. 容器化:自建 Jekyll 镜像 + Chirpy Starter

官方 jekyll/jekyll 镜像较旧(Ruby 版本低),我用 ruby:3.3 为基底,自己装依赖和 bundler,再在容器中构建项目。

3.1 目录结构(项目根)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.
├── Dockerfile
├── docker-compose.yml
├── Gemfile
├── Gemfile.lock        # 可选;若冲突可先删掉再安装
├── _config.yml
├── _posts/             # 你的文章
├── _data/
├── assets/
├── _plugins/
├── _includes/          # 可放自定义 footer 覆盖文件
├── _tabs/
├── index.html
└── tools/              # 自定义脚本

推荐从 chirpy-starter 初始化(而不是直接 clone 主题仓库):

1
2
3
git clone https://github.com/cotes2020/chirpy-starter myblog
cd myblog
# 修改 _config.yml、Gemfile 等

3.2 Dockerfile(关键点:安装系统依赖 + bundler)

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
FROM ruby:3.3

WORKDIR /srv/jekyll

RUN apt-get update && apt-get install -y \
    build-essential libffi-dev libyaml-dev zlib1g-dev git \
    && rm -rf /var/lib/apt/lists/*

RUN gem install bundler

# 先复制 Gemfile(和可选的 Gemfile.lock),以利用 Docker 层缓存
COPY Gemfile ./
COPY Gemfile.lock* ./

RUN bundle install

# 再复制其余站点文件
COPY . .

# 可选:避免 git 权限告警(容器中 git 操作会用到)
RUN git config --global --add safe.directory /srv/jekyll

EXPOSE 4000

CMD ["bundle", "exec", "jekyll", "serve", "--host", "0.0.0.0", "--port", "4000", "--livereload"]

3.3 docker-compose.yml

1
2
3
4
5
6
7
8
9
services:
  jekyll:
    build: .
    container_name: myblog
    ports:
      - "4000:4000"
    volumes:
      - .:/srv/jekyll   # 开发期热更新;若仅为构建可去掉
    command: bundle exec jekyll serve --host 0.0.0.0 --port 4000 --livereload

3.4 构建与运行

1
2
3
docker compose build --no-cache
docker compose up -d
# 访问 http://127.0.0.1:4000

常见错误 1There was an error while trying to write to /srv/jekyll/Gemfile.lock

  • 容器内对挂载目录没有写权限。解决:确保宿主目录可写,或先在镜像里 bundle install 成功,再挂载只做读。

常见错误 2There are no gemspecs at /srv/jekyll

  • 你用了 主题仓库 而非 starterjekyll-theme-chirpy 作为 gem 使用,应使用 chirpy-starter 初始化站点。

4. Arch Linux 本机开发环境(Ruby 3.4 的“erb”问题)

Arch 滚动较快,目前 Ruby 3.4 把 erblogger 等从标准库分拆为独立 gem。Jekyll 4.4.1 仍在引用它们,导致:

1
cannot load such file -- erb (LoadError)

4.1 解决方案 A(快速可用)

在你的 项目 Gemfile 中显式加入依赖:

1
2
3
gem "erb"
gem "webrick"
gem "logger"

安装并运行:

1
2
bundle install
bundle exec jekyll s

4.2 解决方案 B(更稳妥)

使用 rbenv 切到 Ruby 3.2.x/3.3.x

1
2
3
4
5
6
sudo pacman -S rbenv ruby-build
rbenv install 3.2.4
rbenv global 3.2.4
gem install bundler
bundle install
bundle exec jekyll s

我最后采用方案 A:在 Gemfile 中加 erb/logger/webrick,即可在 Arch + Ruby 3.4 成功运行。


5. Chirpy 主题配置要点

5.1 头像(avatar)

_config.yml 设置:

1
avatar: "/assets/commons/avatar.jpg"

并将图片放到项目的 assets/commons/avatar.jpg。构建后它会出现在 _site/assets/commons/avatar.jpg,URL 即 https://你的域名/assets/commons/avatar.jpg

也可直接用外链:

1
avatar: "https://example.com/path/to/avatar.png"

5.2 页脚添加 ICP 备案信息(保留原始信息,再追加)

做法:覆盖主题同名 include。将下述文件保存为 _includes/footer.html(相当于复制主题原始 footer 并插入 ICP 段落):

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
<!-- _includes/footer.html -->

<footer
  aria-label="Site Info"
  class="
    d-flex flex-column justify-content-center text-muted
    flex-lg-row justify-content-lg-between align-items-lg-center pb-lg-3
  "
>
  <p>©
    <time>2025</time>

    
      <a href="https://x.com/ding3399">Eric</a>.
    

    
  </p>

  <!-- ✅ 在原始两段之间插入 ICP 段落 -->
  
    <p class="mb-2 mb-lg-0">
      

      
    </p>
  

  <p>
  </p>
</footer>

然后在 _config.yml 增加配置(把示例值换成你的):

1
2
3
4
5
6
7
icp:
  number: 粤ICP备12345678号

psc:   # 公安备案(可选)
  number: 粤公网安备 44010002000001 号
  link: "https://www.beian.gov.cn/portal/registerSystemInfo?recordcode=44010002000001"
  badge: "/assets/commons/police.png"  # 可选图标,放到 assets/commons 下

覆盖机制:Jekyll 会优先使用你项目下的 _includes/footer.html,从而“原样保留 + 中间插入 ICP”。


6. 一键构建与发布

6.1 简单部署脚本(容器构建→导出静态文件→退出容器)

保存为 deploy.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env bash
set -euo pipefail

# 1) 构建镜像
docker compose build

# 2) 用容器构建静态站点(不常驻)
docker run --rm \
  -v "$(pwd)":/srv/jekyll \
  -w /srv/jekyll \
  jekyll-docker-jekyll \
  bash -lc 'bundle install && bundle exec jekyll build'

# 3) 将 _site 同步到 Web 根目录(自行按需修改目标路径)
# 例:Nginx 根目录 /opt/1panel/www/sites/850899.xyz/index
rsync -av --delete _site/ /opt/1panel/www/sites/850899.xyz/index/

echo "✅ 构建并发布完成:/opt/1panel/www/sites/850899.xyz/index"

如果希望构建前自动启动 compose 并在完成后关闭,也可把第 2 步改为:

1
2
3
docker compose up -d
docker exec -it myblog bundle exec jekyll build
docker compose down

6.2 Nginx 反向代理(可选)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
  listen 80;
  server_name blog.example.com;

  root /opt/1panel/www/sites/850899.xyz/index;
  index index.html;

  location / {
    try_files $uri $uri/ =404;
  }

  location /assets/ {
    expires 7d;
    access_log off;
  }
}

7. 常见错误与快速修复

  • There was an error writing Gemfile.lock 容器对挂载目录无写权限。给予写权限或先在镜像层 bundle install,再挂载开发目录。

  • There are no gemspecs at /srv/jekyll 误用主题仓库。请使用 chirpy-starter 初始化站点,再把内容拷进来。

  • fatal: detected dubious ownership in repository 容器中 Git 安全策略:git config --global --add safe.directory /srv/jekyll

  • Downloading kramdown-2.5.1 revealed dependencies not in the API... (rexml ...) 运行 bundle update kramdown 或删 Gemfile.lock 重新 bundle install

  • Arch 下 cannot load such file -- erb Gemfile 添加 gem "erb"(以及 loggerwebrick),bundle install;或用 rbenv 切到 Ruby 3.2/3.3。


8. 完整命令清单(可抄走)

8.1 使用 chirpy-starter 初始化

1
2
git clone https://github.com/cotes2020/chirpy-starter myblog
cd myblog

8.2(可选)本机 Arch 安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 方案 A:在 Gemfile 添加
# gem "erb"
# gem "webrick"
# gem "logger"
bundle install
bundle exec jekyll s

# 方案 B:rbenv 切 Ruby 3.2/3.3
sudo pacman -S rbenv ruby-build
rbenv install 3.2.4
rbenv global 3.2.4
gem install bundler
bundle install
bundle exec jekyll s

8.3 容器构建

1
2
3
docker compose build --no-cache
docker compose up -d
# 本地预览 http://127.0.0.1:4000

8.4 一键发布(deploy.sh)

1
bash deploy.sh

9. 小结

  • 在 CentOS 服务器上,Ruby 版本与依赖冲突频发,容器化是最稳妥方案。
  • 在 Arch 本机开发,Ruby 3.4 需要在 Gemfile 中显式声明 erb/logger/webrick,或降到 3.2/3.3。
  • Chirpy 的模板采用 gem 主题,定制 footer 这类结构化内容时,_includes/xxx.html 覆盖是最佳实践。
  • 结合 deploy.sh,可以将容器构建的 _site 一键同步到 Web 目录,配合 Nginx 即可上线。
本文由作者按照 CC BY 4.0 进行授权