Hugo を導入する過程で go の環境とか作る(2022版)

github の hugo を clone して docker build すれば docker の環境は出来るので、書くまでもないと言えば書くまでもない。

2022 April に再構築しようと思って自分の記事を見てる。

# TL;DR
正式版と Draft 版の二つの Hugo サーバを立ち上げ、Draft でうまくいったら git をつかって、正式版から pull して反映するという環境を作りたい。

そのために hugo + git の docker 環境 + ホスト側に同じバージョンの hugo が必要になった。go の環境はあまり関係なかった、、、

# まずは出来た Docker のイメージを使う
sinby/hugo-git:0.97.3-extended で公開しているので

```
% sudo docker run --rm -v =0/site:/site 0.97.3-extended new site .
```

こんな感じでまずは site を構築する。=0 は tcsh の機能なので、bash 使っている人とかは $(pwd) とかに置き換えることになるでしょう。(2022 に入って bash 派に転校しました)

ところで、いったいこれはなにをしているのか？

## /site を構築したのだ
docker 内の /site に hugo の source が設定されている（というかカレントディレクトリが /site になるみたい）。参考までに書くと hugo でこのディレクトリを変えるには --source string で変更する。

/site は docker の中にあるのでアクセスできないと一切何もできない。なので、-v で docker のホストの site ディレクトリを /site にするように設定している。

sinby/hugo-git:0.97.3-extended  は docker 内の hugo を起動するので引数に new site . を指定する。これは docker 内に login して 

```
( cd /site ; hugo new site . )
```

としたのと同じだ。run で --rm 指定しているのでコマンドの実行が終了すると（つまり hugo コマンドが終了すると）docker 自身もコンテナとして終了し、そしてイメージを消去する。

これ(--rm ね)をつけないと山のように終了したイメージの残骸が docker が管理するディスク上のどっかに蓄積していくことになる。

## hugo 実行しただけじゃん
ってことはこれ hugo 実行しただけじゃん。例えば version 。

```
% sudo docker run --rm -v =0/site:/site sinby/hugo-git:0.80.0 version
```

これ docker 起動して hugo version 実行して　docker 終了して、イメージを消すというかなり簡単なことを大げさに実行する。だとしたら、手元に hugo 0.80.0 があれば

```
% hugo new site site
```
とと下のほぼ等価。まぁ最新の hugo をインストールするのにちょっとこつがいるんだけどね(後述)。

## つづけて hugo をサーバーとして起動

```
% sudo docker run --rm -v =0/site:/site -p 1313:1313 sinby/hugo-git:0.97.3-extended  server -D --watch  --bind 0.0.0.0
```

-D と --watch で draft も表示させつつつデバッグ用として起動。これで Docker のホストからは 1313 で hugo をみることができる。が、まだ何も設定してないので、エラー表示されるでしょう。

## docker の中に入って設定をする
いや～これおかしいけどね。docker ps であらかじめ調べておいた Container ID で exec で中に入る。login みたいなもんだね。

手順は https://gohugo.io/getting-started/quick-start/　とほぼ同じ

```
sudo docker exec -it　<ContainerID> /bin/ash
/site #
/site # git init
/site # git clone https://github.com/budparr/gohugo-theme-ananke.git themes/ananke
/site # echo 'theme = "ananke"' >> config.toml
```

ついでにちょっとコンテンツも追加

```
/site # hugo new posts/0212-0.md
/site/content/posts/0212-0.md created
```

折角 /site がホストに出ているのに、docker の中に入って作業するのおかしいけど、とりあえず、ここまででいろいろできるということで。あと、config.toml の中の baseURL も変更しておきましょう。

```
baseURL = "http://192.168.0.XXX:1313/"

```
あれ？うまくいかないな、立ち上げの時に -b で指定するとうまくいく。う～ん。まぁいいや。これで回避。

```
% sudo docker run --rm -v =0/site:/site -p 1313:1313 sinby/hugo-git:0.80.0 server -D --watch  --bind 0.0.0.0 -b 192.168.0.XXX:1313
```


ブラウザーで動作確認出来たらここで最初のミッション完了。

# ドラフトなサーバとして仕上げる
折角、Docker のホストから /site が見えているのに、わざわざ exec で docker 内に入った理由は site のすべてのファイルのオーナが root だからです。さっきつくった posts/0212-0.md も vim で編集するのに sudo が必要になったりして、大変回りくどくなります。

そこで、ホスト側で編集できるように chown してしまいます(<user> と <group> には適切な名称を入れてください)。そして draft なサーバとして再度立ち上げます。そのためディレクトリ名を site から draft に変更します。ポートも 31313 にします(--appendPort=false とするみたい。~~なんか直感的には逆なんだけど~~ URL にかいてある port を無視するという意味みたいね)

```
> sudo chown -R <user>:<group> site
> mv site draft
> sudo docker run --rm -v =0/draft:/site -p 31313:1313 0.97.3-extended  server -D --bind 0.0.0.0 -b 192.168.0.XXX:31313 --appendPort=false
Start building sites …
```

## ホスト側で編集
これでホスト側で編集できるはずです。お！できました。

# ホストに同じバージョンの hugo をいれる
ここが難しかった。

実は、この方法は hugo の Dockefile をホストで実行しているだけです。

## まずは最新の go を導入
apt とかで入れると古めの go が入るので、とりあえず apt でいれた golang も remove して、本家から tar.gz をとってきて /usr/local に解凍。/usr/local/go/bin を path についかしておきます。これで go コマンドが実行可能になりました。



```
> go version
go version go1.18.1 linux/amd64
```
[2022] ついでに 1.15.8 から 1.18.1 にバージョンアップ!! 

```
$ ls -l /usr/local
...
lrwxrwxrwx  1 root root    9  4月 22 13:53 go -> go-1.18.1/
drwxr-xr-x 10 root root 4096  2月  5  2021 go-1.15.8/
drwxr-xr-x 10 root root 4096  4月 13 00:42 go-1.18.1/
...
```

参考までに書くとこの /usr/local/go の環境(SDK?) が GOROOT になるようです。（ここでは必要がなかったので特に環境変数は設定していません）

## mage のインストール
hugo の build に mage が必要です。~~そこで mage を get します。~~ install になったようです。ここではクリーンに作りたいので GOPATH を ~/Hugo/go に設定しておきます。

```
> setenv GOPATH ~/Hugo/go
> go get github.com/magefile/mage
```

[2022 bash版]
```
$ go install github.com/magefile/mage@latest
go: downloading github.com/magefile/mage v1.13.0
```

これで ~/Hugo/go/bin に mage というコマンドが追加されました。path に追加しておきましょう。

## hugo の build(2021古い情報)
get は deprecated なので installを使います(後述)ここでは歴史的経緯を残す意味で削りません。

~~ソースを持ってくるのに go get を使うと途中でいくつかエラーになります。なぜだかはわかりません。依存関係がおかしな具合になっているように見えます。~~

~~そこで、Docker ファイルにあるように clone してコピーします。そして mage でビルド・インストールします。~~

```
> cd ~/Hugo/go/src/github.com
> mkdir gohugoio
> cd gohugoio
> git clone https://github.com/gohugoio/hugo.git
> cd hugo
> mage hugo
> mage install
```

~~うまくいけば hugo が ~/Hugo/go/bin にインストールされます。~~

```
> ~/Hugo/go/bin/hugo version
Hugo Static Site Generator v0.80.0-792EF0F4 linux/amd64 BuildDate: 2021-02-12T12:35:21+0900
```
# hugo の build どうする？[2022版]
get は deprecated になったのでどうすればいいの？

https://github.com/gohugoio/hugo
をみると

```
mkdir $HOME/src
cd $HOME/src
git clone https://github.com/gohugoio/hugo.git
cd hugo
go install
```
らしいので、おもむろに release-0.97.3 で install

```
$ cd hugo
$ git checkout -b release-0.97.3 
$ go install
go: downloading github.com/alecthomas/chroma v0.10.0
go: downloading github.com/bep/overlayfs v0.6.0
go: downloading github.com/fsnotify/fsnotify v1.5.1
go: downloading github.com/spf13/afero v1.8.2
go: downloading github.com/spf13/cobra v1.4.0
go: downloading golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
go: downloading golang.org/x/sys v0.0.0-20220209214540-3681064d5158
...途中略
go: downloading github.com/go-openapi/swag v0.19.5
go: downloading github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e
```

うまくいけば hugo が ~/Hugo/go/bin にインストールされます。あれ？なぜか v0.98.0-DEV。なぞ。

```
$~/Hugo/go/bin/hugo version
hugo v0.98.0-DEV-41cc4e4ba3bd849cee7dcb691504ebebbfce680f linux/amd64 BuildDate=2022-04-18T18:01:38Z
sunra:hugo$ git branch
  master
* release-0.97.3
  v0.80.0
```

# ホスト側でコンテンツを登録して編集
できるかな～

```
> cd draft
> hugo new posts/0212-1.md
> vim content/posts/0212-1.md
```
お～できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99921/01696901-3459-7653-dfb2-a0220c6eb1c1.png)

とりあえず draft で git commit しておきます。

```
> git add archetypes/ config.toml  content/
> git commit
```

# ドラフトじゃないサーバを立ち上げる

```
sudo docker run --rm -v =0/site:/site sinby/hugo-git:0.80.0 new site .
sudo docker run --rm -v =0/site:/site -v =0/draft:/draft -p 1313:1313 sinby/hugo-git:0.80.0 server --bind 0.0.0.0 --baseURL=192.168.0.X
```

## いいかげん docker-compose で便利にしよう

```
version: '3'

services:
    server:
        image: sinby/hugo-git:0.80.0
        command: server --bind 0.0.0.0 --baseURL=192.168.0.X
        volumes:
            - "./site:/site"
            - "./draft:/draft"
        ports:
            - "1313:1313"
```

## draft から clone 
なんかうまくいかなかったのでかなり無理矢理。

```
/site # git clone /draft
/site # mv draft/.git .git
/site # git remote -v
origin  /draft (fetch)
origin  /draft (push)
/site # git fetch
/site # git log

commit b1fc9f11d960c5ae604e88e89ce976747288a085 (HEAD -> master, origin/master,
origin/HEAD)
Author: RS
Date:   Fri Feb 12 08:57:02 2021 +0000

    submodule をやめた

commit 2270efcb1a56bf68f864322797ee011ba303557b
Author: RS
Date:   Fri Feb 12 08:36:48 2021 +0000

    コンテンツ増えた。
/site # git reset --hard
/site # ls -R content
content:
posts

content/posts:
0212-0.md  0212-1.md

/site # git clone /draft/themes/ananke/ themes/ananke
/site # ls themes/
ananke

```

reset --hard がかなり無理矢理感がありますが、まぁわかってやっているので良しとしましょう。ananke も clone しておきます。

なんか、とちゅうごちゃごちゃになって、docker を再立ち上げとかしましたが、、、なんとか目的通りのことが出来ました。

# 一通り確認
1. 1313 で正式版立ち上げ
2. 31313 でdraft 版立ち上げ
3. draft の content を編集 => draft 版のサーバで変更がリアルタイムに確認できる。draft の行が入ったものも見ることができる。
4. content の編集と draft の行を削る。
5. git commit する。
6. 1313 に git pull を exec => 正式版のサーバで変更がリアルタイムに確認できる。draft の行が入ったものは見ることができない。

```
sudo docker exec -it <containerID> git pull
```

最後の手順で sudo を必要とするけど、まぁいいんじゃないって感じ。

# おまけ。hugo-fresh を使う [2022]
Bulma という CSS がよさそうです。bootstrap よりわかりやすくシンプルかな。hugo-fresh という theme で使われています。ananke はちょっと(私には)大げさだった。

https://github.com/StefMa/hugo-fresh

# おまけ。reveal も使う[2022]
スライドを使うなら reveal 。超便利。フォントの大きさも変えられる。hugo-fresh と共存できます。

```
theme = ["hugo-fresh-asagao", "reveal-hugo"]
```

# おまけ。ananke をちょっと使いやすく？する
たぶん thema は ananke を拝借しながら、今後は独自に発展すると思われるので意図的に clone にしました(submodule にしなかった。submodule にすると clone 先で本家を参照するから)。

ananke 以外の themes が必要な時は適宜 docker を立ち上げればいいでしょう。例えばスライド用に slide.example.com で、 themes をスライドから拝借、docs.example.com で themes は docsy にするとか。

## i18n を追加して
ソースの一番上(/draft とか) でi18n を追加して ja.toml も追加(en.toml からコピー)。そして Recent を最近のに read more を続きはこちらに変更

```
> mkdir i18n
y> diff i18n/ja.toml  themes/ananke/i18n/en.toml
8c8
< other = "最近の {{.Title }}"
---
> other = "Recent {{.Title }}"
11c11
< other = "続きはこちら"
---
> other = "read more"
```

config.toml に DefaultContentLanguage を追加

```
DefaultContentLanguage = "ja"
```
## メニューも追加
config.toml にメニューも追加

```
[[menu.main]]
identifier = "posts"
name = "posts"
url = "/posts/"
```

なんとなくですが、WordPress の themes とはちがい、自分でどっかから themes を clone してそれを変えていた方がよさそう。複数の themes からその機能が欲しいときは自分でコピペする。そうすると、どんどん最初の themes とは違うものになっていくでしょう。

ということは themes にとらわれる（こだわる）のではなく clone して独自スタイルに成長させる(各自がテーマを持つ)という風になる気がしますよ。

# 感想
よくできているような、難しいような。hugo-fresh を読んででだいぶ理解が進みました。Hugo で range はできるけど foreach 的なことはできないみたいなので、結局、最後は lisp に戻るかも。デザイン上の良し悪しは結局ツールじゃなくて HTML5 CSS JS に集約されるから。それをうまく組み合わせることを助けてくれるツールがいいよね。

いまのところ WordPress にしても Hugo にしても助けてくれるというよりはその Theme を使え的なところがある。