docker-compose AlpineLinux にタイムゾーンを設定する

Dockerや組み込み系のOSとしてよく使用される軽量なOS「Alpine Linux」
タイムゾーンはもちろんデフォルトUTCなのでJSTに変更する必要があります。

## Dockerfile を作成

`Dockerfile` を作成します。

```dockerfile
FROM alpine:3.10

RUN set -eux && \
  apk add --update-cache --no-cache --virtual=.build-dependencies tzdata && \
  cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
  apk del .build-dependencies
```

## コンテナイメージの作成

```shell
$ docker build -t alpine-jst .
```

`alpine-jst` という名前を付けます。

```shell
$ docker run --rm alpine-jst date
Fri Jun 19 23:28:34 JST 2019
```

タイムゾーンが `JST` になっていることを確認できます。

## 補足

### docker FROM 命令

FROM 命令ではベースとなるDockerコンテナイメージを指定します。
今回使用するベースイメージです。

https://hub.docker.com/_/alpine

### docker RUN 命令

Dockerの `RUN, COPY, ADD` 命令が実行されるとイメージのレイヤーが作成されます。
そのためRUN命令は1行のコマンド(ワンライナー)で書くのが良いです。

単純に一行にすると読みづらくメンテナンスしにくいので `&& \` で繋げて見やすいように改行して書きます。

### set -eux

シェルスクリプトのオプションを設定してます。

#### -e(errexit) オプション

ゼロ(正常)以外のステータスコードでコマンドが終了したら、即座に終了する。
デフォルトの状態だと途中でエラーが起きてもそのまま次のコマンドに進んでしまいます。

#### -u(nounset) オプション

置換処理においてセットされていない変数があればエラーとする。
未使用の変数などがあればエラーを出力します。

#### -x(xtrace) オプション

コマンドを実行した時に、そのコマンドと引数を表示する。
デフォルトでは実行コマンドは出力されないので、このオプションを指定すればどこでエラーが起きているかをチェックしやすくなります。

### apk パッケージマネージャ

`yum` や `apt-get` といったお馴染みのパッケージマネージャの代わりに
Alpine Linux では `apk` を使用します。

### apk add オプション

#### --update-cache オプション

`--cache-max-age 1` オプションのエイリアスです。
1分超えたキャッシュを更新してくれます(ほぼキャッシュを使わない)

#### --no-cache オプション

不要なゴミファイルをコンテナ内に作らないオプション

#### --virtual=.build-dependencies オプション

インストールするパッケージ群に仮の名前を付けることができます。
今回は `.build-dependencies` という仮の名前を付けています。

`apk del .build-dependencies` 仮の名前で一括削除できます。
今回は `tzdata` しか入れてないので恩恵はほぼないですね。

## 付録

```
$ apk add --help
apk-tools 2.10.4, compiled for x86_64.

usage: apk add [-h|--help] [-p|--root DIR]
           [-X|--repository REPO] [-q|--quiet]
           [-v|--verbose] [-i|--interactive]
           [-V|--version] [-f|--force]
           [--force-binary-stdout]
           [--force-broken-world]
           [--force-non-repository]
           [--force-old-apk] [--force-overwrite]
           [--force-refresh] [-U|--update-cache]
           [--progress] [--progress-fd FD]
           [--no-progress] [--purge]
           [--allow-untrusted] [--wait TIME]
           [--keys-dir KEYSDIR]
           [--repositories-file REPOFILE]
           [--no-network] [--no-cache]
           [--cache-dir CACHEDIR]
           [--cache-max-age AGE] [--arch ARCH]
           [--print-arch] [-s|--simulate]
           [--clean-protected]
           [--overlay-from-stdin] [--no-scripts]
           [--no-commit-hooks]
           [--initramfs-diskless-boot] [--initdb]
           [-u|--upgrade] [-l|--latest]
           [-t|--virtual NAME] PACKAGE...

Description:
  Add PACKAGEs to 'world' and install (or
  upgrade) them, while ensuring that all
  dependencies are met

Global options:
  -h, --help              Show generic help or
                          applet specific help
  -p, --root DIR          Install packages to DIR
  -X, --repository REPO   Use packages from REPO
  -q, --quiet             Print less information
  -v, --verbose           Print more information
                          (can be doubled)
  -i, --interactive       Ask confirmation for
                          certain operations
  -V, --version           Print program version
                          and exit
  -f, --force             Enable selected
                          --force-* (deprecated)
  --force-binary-stdout   Continue even if binary
                          data is to be output
  --force-broken-world    Continue even if
                          'world' cannot be
                          satisfied
  --force-non-repository  Continue even if
                          packages may be lost on
                          reboot
  --force-old-apk         Continue even if
                          packages use
                          unsupported features
  --force-overwrite       Overwrite files in
                          other packages
  --force-refresh         Do not use cached files
                          (local or from proxy)
  -U, --update-cache      Alias for
                          --cache-max-age 1
  --progress              Show a progress bar
  --progress-fd FD        Write progress to fd
  --no-progress           Disable progress bar
                          even for TTYs
  --purge                 Delete also modified
                          configuration files
                          (pkg removal) and
                          uninstalled packages
                          from cache (cache
                          clean)
  --allow-untrusted       Install packages with
                          untrusted signature or
                          no signature
  --wait TIME             Wait for TIME seconds
                          to get an exclusive
                          repository lock before
                          failing
  --keys-dir KEYSDIR      Override directory of
                          trusted keys
  --repositories-file REPOFILE Override
                          repositories file
  --no-network            Do not use network
                          (cache is still used)
  --no-cache              Do not use any local
                          cache path
  --cache-dir CACHEDIR    Override cache
                          directory
  --cache-max-age AGE     Maximum AGE (in
                          minutes) for index in
                          cache before refresh
  --arch ARCH             Use architecture with
                          --root
  --print-arch            Print default arch and
                          exit

Commit options:
  -s, --simulate          Show what would be done
                          without actually doing
                          it
  --clean-protected       Do not create .apk-new
                          files in configuration
                          dirs
  --overlay-from-stdin    Read list of overlay
                          files from stdin
  --no-scripts            Do not execute any
                          scripts
  --no-commit-hooks       Skip pre/post hook
                          scripts (but not other
                          scripts)
  --initramfs-diskless-boot Enables options for
                          diskless initramfs boot
                          (e.g. skip hooks)

Add options:
  --initdb                Initialize database
  -u, --upgrade           Prefer to upgrade
                          package
  -l, --latest            Select latest version
                          of package (if it is
                          not pinned), and print
                          error if it cannot be
                          installed due to other
                          dependencies
  -t, --virtual NAME      Instead of adding all
                          the packages to
                          'world', create a new
                          virtual package with
                          the listed dependencies
                          and add that to
                          'world'; the actions of
                          the command are easily
                          reverted by deleting
                          the virtual package

This apk has coffee making abilities.
```

## 参考

- [Alpine Linux入門 -内部構造とapkでパッケージインストール編-](https://blog.stormcat.io/post/entry/alpine-entry-apk)