コンテナのzoneinfoとGoのLocationについて

以前書いたAlpine Linuxで時刻をJSTに設定する(Dockerfile)で、コンテナ内の時刻をJSTとして扱えるようにした。

しかし、以下が気になった。

  • コンテナのイメージ作成においてタイムゾーンを変更するような記述を見かけたことがなかった
  • コンテナのタイムゾーンを変更しなくても、アプリ内でJSTとして扱うことはできるので、不要なセットアップではないか

ということでアプリケーション(Go)の方で対処できないか、検証してみた。

結論

結果、以下のような挙動となった。

  • time.LoadLocationはコンテナの中に該当するzoneinfoがないと失敗する
    • Alpine LinuxのデフォルトではAsia/Tokyoなどは存在しないため確実に失敗する
    • /etc/localtime/usr/share/zoneinfo/Asia/Tokyoなどで上書きされていても、 /usr/share/zoneinfo/Asia/Tokyo自体がないとやはり失敗する
  • time.FixedLocationは直接time.Locationを生成するためzoneinfoの有無の影響を受けない

軽量コンテナを使用する際にはUTCを前提とするか、time.FixedLocationを使用した方が良さそう

もしJSTをデフォルトとしたコンテナを作成したかったら、以下のようなDockerfileにすべき。

FROM alpine:latest

# インストールしたtzdataは削除しない
RUN apk --no-cache add tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

以下、検証した内容。

Goのプログラム

以下のように4回時刻を出力するようにした。

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Now()
    fmt.Println(t)

    jst, err := time.LoadLocation("Asia/Tokyo")
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(t.In(jst))
    }

    jst = time.FixedZone("JST", 9*60*60)
    fmt.Println(t.In(jst))

    time.Local = jst
    fmt.Println(time.Now())

}

表示は以下のようになると予想していた。

  • time.Nowではコンテナのタイムゾーンに基づいた時刻表示
  • t.In(jst)ではJSTの時刻表示がされる
    • time.LoadLocationでerrが起きるとは思ってなかった
  • 最後のtime.NowではJSTの時刻が表示される

バイナリは以下のようにしてtime-testとして出力しておく。

GOOS=linux GOARCH=amd64 go build -o time-test

検証1: zoneinfoを特に設定しない

まずはコンテナを作っとく。Dockerfileは以下の通り。

FROM alpine:latest
 
COPY ["time-test", "/"]
CMD [ "/time-test" ]

docker buildして、jst-time-test1というタグにしておく。

docker build -t jst-time-test1 -f Dockerfile1 .

docker runで実行する。

$ docker run --rm jst-time-test1
2018-08-30 00:36:56.4097601 +0000 UTC m=+0.000328601
open /usr/local/Cellar/go/1.9.2/libexec/lib/time/zoneinfo.zip: no such file or directory
2018-08-30 09:36:56.4097601 +0900 JST
2018-08-30 09:36:56.4098805 +0900 JST m=+0.000448301

最初はUTCが出力され、最後はJSTが出力された。しかしtime.LoadLocationではエラーが出力された。

open /usr/local/Cellar/go/1.9.2/libexec/lib/time/zoneinfo.zip: no such file or directoryと表示されるのは、time.LoadLocationの説明にあるとおりで、

The time zone database needed by LoadLocation may not be present on all systems, especially non-Unix systems. LoadLocation looks in the directory or uncompressed zip file named by the ZONEINFO environment variable, if any, then looks in known installation locations on Unix systems, and finally looks in $GOROOT/lib/time/zoneinfo.zip.

最終的に$GOROOT/lib/time/zoneinfo.zipを参照するということなので、システムのzoneinfoもないし、$GOROOT/lib/time/zoneinfo.zipもない(GoのSDKは存在しない)ためエラーとなった様子。

検証2: JSTをローカルタイムに設定しzoneinfoを削除した状態

今度はAlpine Linuxで時刻をJSTに設定する(Dockerfile)で設定した環境で、dateコマンドだとJSTが表示される状態になっている。Dockerfileは以下の通り。

FROM alpine:latest

RUN apk --no-cache add tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    apk del tzdata

COPY ["time-test", "/"]
CMD [ "/time-test" ]

docker buildする。

docker build -t jst-time-test2 -f Dockerfile2 .

実行する。

$ docker run --rm jst-time-test2
2018-08-30 09:37:09.7907743 +0900 JST m=+0.000254901
open /usr/local/Cellar/go/1.9.2/libexec/lib/time/zoneinfo.zip: no such file or directory
2018-08-30 09:37:09.7907743 +0900 JST
2018-08-30 09:37:09.7908918 +0900 JST m=+0.000372901

最初はJSTが出力され、最後はJSTが出力された。しかしtime.LoadLocationではエラーが出力された。

このコンテナでは/etc/localtimeは上書きされているが、zoneinfo(/usr/share/zoneinfo/Asia/Tokyo)がないから、やはりエラーとなった様子。

検証3: JSTをローカルタイムに設定しzoneinfoを残した状態

検証2の結果から、Dockerfileを以下のように修正した。

FROM alpine:latest

# 前回実施していた apk del tzdata を消去
RUN apk --no-cache add tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

COPY ["time-test", "/"]
CMD [ "/time-test" ]

docker buildする。

docker build -t jst-time-test3 -f Dockerfile3 .

実行してみる。

$ docker run --rm jst-time-test3
2018-08-30 09:37:15.3019175 +0900 JST m=+0.000325101
2018-08-30 09:37:15.3019175 +0900 JST
2018-08-30 09:37:15.3019175 +0900 JST
2018-08-30 09:37:15.3020498 +0900 JST m=+0.000457301

今度はうまくいった!やはり参照するzoneinfoがなかったからエラーになっていたのだろう。

time.FixedLocationを使用した場合にはすべて問題なく実行できたのも確認できた。

終わりに

今回検証した辺りのzoneinfo(tzdata)について詳しくなかったので、勉強になった。

とりあえず今後は

package main

import "time"

func init() {
    time.Local = time.FixedZone("JST", 9*60*60)
}

としておくようにしよう。

Alpine Linuxで時刻をJSTに設定する(Dockerfile)

公式の手順があるのでそれを参考にした。
Setting the timezone - Alpine Linux

Dockerfileには以下のように記述した。

FROM alpine:latest

RUN apk --no-cache add tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    apk del tzdata

公式の手順に従って/etc/timezoneを設定するとGMTになってしまったので、それは設定しないようにした。

作ったイメージでdateを実行して確認する。

$ docker build -t jst-alpine .
(snip)

$ docker run --rm jst-alpine date
Tue Aug 28 23:07:21 JST 2018

$ docker run --rm alpine date
Tue Aug 28 14:07:31 UTC 2018

上手くいった。JSTと表示されている。

というか、そもそもアプリケーション側でlocaltimeがJSTだってのを前提にするのが良くない気がする(今までそうしてたけど)。今度検証してみよう。

「入門 Kubernetes」を読んだ

入門 Kubernetes

入門 Kubernetes

k8sについてちゃんと勉強したかったので読んだ。

k8sをやるにあたって知っておくべき最低限のことが書いてあって、それを実際に動かしながら確認していくスタイル。著者の執筆時点から変わっていることについて訳注が入っているのだけれど、それもさらに変わっているところもあった。

それだけ進化が速いってことかな。

コンテナ化されたアプリケーションを作る方は楽になりそうだけど、k8s自体の運用は大変そうだなぁとも思った。まだプロダクションでやってないんで、わからんけど。

Docker/Kubernetes辺りはキャッチアップできてなかったところなので、他にも新しい出るみたいだし、そっちも読んでみたい。

Docker/Kubernetes 実践コンテナ開発入門

Docker/Kubernetes 実践コンテナ開発入門

Gitのユーザ情報を細かく管理する

$HOME/.gitconfigをgitで管理して、エイリアスなどの設定を会社と自宅で共有したいが、ユーザ名とメールアドレスは場所によって異なるので、それらを含んだまま管理ができていなかった。

で、cloneしてきた端末ごとにユーザ情報を設定すると、git上での差分となってしまって、何かエイリアスなどを変更した際に、ユーザ情報を含まないようにコミットする必要がある。

ユーザ情報を別の設定ファイルとして切り出し、includeを使用することで上手く使い分けができる。

ユーザ情報を別ファイルに設定する

例えば$HOME/.gitignore.localというファイルにユーザ情報を設定する。

コマンドから追加するときは以下のように実行する。

$ git config --file ~/.gitconfig.local --add user.name 'Kentaro Kawano'
$ git config --file ~/.gitconfig.local --add user.email emailaddress@example.com

--file によって設定を保存するファイル名を指定できる。

内容は以下のようになる。

# $HOME/.gitconfig.local
[user]
    name = Kentaro Kawano
    email = emailaddress@example.com

別のファイルになっているだけで、Gitのための設定ファイルなので、別にユーザ情報だけではなく、端末に依存する設定を含んでもよい。

include を使用する

gitconfigで、別の設定ファイルを読み込むためにはincludeを使用する。

$HOME/.gitconfigの中でincludeを使用して別の設定ファイル($HOME/.gitconfig.local)を読み込むようにする。

# $HOME/.gitconfig
[include]
    path = .gitconfig.local

.gitconfig.local の作成忘れがたまにある

includeの対象となるファイルが存在しなくても、gitの操作を行うにあたって警告が出ることはない。なので、.gitconfig.localを作成せずに(ユーザ情報が設定されないままに)コミットをしてしまうことがある。特に端末のセットアップ直後とか。

その際には、ユーザ情報を勝手に設定したよという注意が出てくる。

Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

なので、.gitconfig.localを上述の手順で作成した上で、git commit --amend --reset-authorを実行するとよい。

「Goならわかるシステムプログラミング」を読んだ

Goならわかるシステムプログラミング

Goならわかるシステムプログラミング

ウェブの連載自体は知ってたものの結局見てなかったので、時間のできた今のうちに読んでおこうと購入した。

扱っている内容から難しいのかと勝手に想像していたが、Goをやっている人なら苦労せずに読める内容だと思う。自分は、一部は実際に実装したことがある内容だったので、スムーズに読むことができた。

ウェブアプリケーションを作っていると普段はそこまで知らなくてもまぁなんとかなるんだけど、パフォーマンスチューニングしないといけないような状況になった時には、やはり低レイヤーの知識は必要になるので、その辺りの足がかりとして良かった。

ついでに、過去にシステムプログラミングの本を読みかけて断念したことがあったので、読み直してみよう。

「お金2.0」を読んだ

お金2.0 新しい経済のルールと生き方 (NewsPicks Book)

お金2.0 新しい経済のルールと生き方 (NewsPicks Book)

うーん、そっか〜って感じだ。ちゃんと理解できてない部分もあるだろうけど、

  • 仮想通貨の登場によって、経済圏そのものが複数存在することが当たり前となる
  • どの経済圏で生活するかを選択できるようになる

という話が書いてあった。なんだかいまいち納得感がない。

例えばドルだって海外旅行前提とかでもないと、わざわざ持つ必要性ないし、為替とか金利優遇とかそういうのがメインでは?とか思ったり。

ビットコインとか実際持ってないんだけど、ビットコインで日常生活送れる感じもないしなぁ。試してみないとこにはわかんないし、ビットコインとかやってみた方が良いかな?いやどうかな。

自由に経済圏を構築できたとして、それがかなり大きいものにならないと導入や利用する意味があまりないと思うし、なーんかピンとこない。

というか考え方自体が見当違いなのか。お金のこと詳しくないし、他にも色々勉強しないといかんのは間違いない。

下垂体卒中で入院していた

下垂体卒中で4週間入院していて、今は自宅療養中。

はじめに

頭痛持ちの人には気をつけてほしいなと思う。きちんと診断してもらったことがない人は、一度頭のMRIの検査とか受けた方が良いと思う。万が一ってことがあるかもしれない。

あと、もし激しい頭痛と嘔吐が起きた場合は、救急車呼んででもすぐに大きな病院に行くべき。ググった結果で勝手に自己判断しない。

以下、あまりまとまってないし長くなった。

下垂体、下垂体卒中とは

そもそも下垂体について知らなかったんだけど、こういう器官らしい。頭の中にある。

下垂体(かすいたい)は、様々なホルモンの働きをコントロールしている部位です。大きさはえんどう豆程度で、前葉と後葉からホルモンを分泌し、生体の機能維持を司っています。

f:id:kentaro_kawano:20180626134239g:plain

引用: 下垂体の働きについて|成人の成長ホルモン分泌不全症

それで、下垂体卒中というのは、こういう状態。

下垂体卒中は、下垂体腫瘍が突然大きくなったり、出血したりすることにより起こります。下垂体卒中が起こると、突然の激しい頭痛がおこり、視力の低下や複視(物が二つに見える)が出現します。

引用: 下垂体腫瘍に罹った患者さんとその家族のためのガイドブック

自分はまさにこれだった。

以前からあった自覚症状

思えばこんな自覚症状があったけど、腫瘍のせいだったかもしれないし、関係ないかもしれない。

  • 頭痛が慢性的に発生
  • 特に夕方になるに連れて痛くなる
  • たまに朝から頭痛がしんどいなぁという日があり寝込んでしまう
  • 左右どちらか、あるいは両方の目の奥が痛む時がある
  • まぶたがたまに痙攣してることがある

最後2つの目の症状は特に左側で発生することが多かった(し、今回症状が出たのも左側だった)。もしかして偏頭痛なのかなぁと自分では疑っていたが、結局今まできちんと検査してもらったことはなかった。

今回の症状とか

時系列で書くと以下の通り。

  • 5月22日: かなり激しい頭痛と嘔吐
  • 5月25日: 入院。入院直後から複視が発生
  • 6月6日: 手術
  • 6月22日: 退院
  • 7月末まで自宅療養の予定

入院までに時間がかかったのは、3件病院を回ったから。風邪→偏頭痛→下垂体卒中という診断だった。「頭痛 嘔吐」でググると偏頭痛に関する記事が多く、2件目の診断でやっぱそうだよなぁと納得しその薬に期待したところも大きかった。が、全然回復しなかったので最寄りの大きな病院に行った。救急車呼んででも大きな病院に早く行くべきだった。

入院後の点滴と内服薬のおかげで、頭痛と吐き気は3日ほどで回復し、食事も取れるようになった。内科の診断では特にホルモンの異常はないとのことだったが、複視が改善しなかったので、脳外科の先生の判断で手術を行うことになった。(実際、腫瘍があっても手術をしないということはあるらしい。)

6/1に手術に関する説明があった。その際、「あくまでも症状が悪化するのを防ぐための予防的処置であって、すでに視神経に障害が起きている場合は回復しない」と言われたのはかなりショックだった。両目でピントが合わせられないので左目には眼帯をしていて、なかなか読書もままならない状態だった。このままだと長時間パソコンを使うのも厳しいかもしれないと思っていたので、これはプログラマとして生きていけなくなるのでは?と思った。

今の状態

無事手術も終わって退院したものの、後遺症というかそういうのがやはりある。

  • 複視はなくなった
  • 目が常に疲れてる感じ
  • 視野が欠けてしまった
  • 倦怠感
  • 疲れやすい
  • 頭痛

目に関しては、複視がなくなったので良かった。回復しないかもとか言われてたので、本当に嬉しい。読書も問題ないし、パソコンも使用できている。ただ、基本疲れ目状態という感じでまぁまぁツラい。メガネも弱めにした方が良さそう。視野が欠けているという診断結果だが、これは気になったことがないので、生活には影響はなさそう。もしかしたら車の運転に影響があるかもしれない。

倦怠感があるが、これは手術の影響による下垂体の機能低下が原因っぽい。術前の検査ではホルモンの異常はなかったが、術後の検査では数値が低下していた。とりあえず発熱などの症状があった時に飲む薬を処方してもらっている。だるくて起きれないということは今のところない。

疲れやすさもあって、ちょっと歩くだけで、疲れる程度に走ったあとの軽い動悸と息切れの感じが発生する。最寄り駅まで徒歩5分くらいだったのが10分くらいかかるようになって、駅に着いたら「フーフー」言ってる。入院中に筋力が低下しているのも影響しているかもしれないし、自宅療養でどれくらい回復するのかしないのか。1ヶ月後に検査があるのでまたそこでの判断になる。正直このままだと通勤もままならんなと思う。

頭痛は日常生活に支障はない範囲でうすーくある。疲れ目と一緒に起きる頭痛に近いので、目のせいかも。波があるので、ひどくなったら頭痛薬を飲むしかないが、今のところそれは1回だけですんでいる。この頭痛は手術の影響によると先生が言っていたが、徐々に治まって発生しなくなるのかどうか。頭痛持ちだったけど、手術しても頭痛持ちのままなのかぁとか思うと凹む。

終わりに

今後のことだけど、とりあえず7月末までは仕事は休みたい。医者から自宅療養するようにと言われているのもあるが、まだまだ体調が万全とは言いがたい。体力がどれくらい戻るのか正直わかんないけど、徐々に運動量を増やしていくとか、とにかく体力が回復できるようにできることをやるしかない。

あと、何かしら仕事に備えて慣らしていく必要もあるんで、なんかコード書くとか読書するとかもしようと思う。長い休みだからこそできそうな何か。具体的にはわからんけど。

不幸中の幸いというか、幸いでもないんだけど、やつれた痩せたんで、体重はキープしたい。昔来てた服が着れるようになったのは嬉しい。もうちょっと元気になったら服を買いに行きたい。