Linux に Docker を一発インストールするワンライナー

> ラズパイの Raspbian などの Ubuntu/Debian 系や、CentOS/Fedora などの RedHat 系といった **Linux OS に [Docker](https://ja.wikipedia.org/wiki/Docker) を簡単にインストールしたい**。

基本的に[各々の OS のパッケージマネージャーを使ってインストールした方がいい](https://docs.docker.com/engine/install/)のですが、検証のため色々な OS に Docker CE（Community Edition）をインストールする必要がある場合のワンライナーが欲しい。

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

1. Linux 系（Windows10+WSL2 含む）OS の場合、公式のインストーラーを利用するのが簡単
    - https://get.docker.com/
 
    ```shell-session:環境にあわせたパッケージをインストールしてくれます
    $ curl https://get.docker.com | sh
    ...
    ```
1. Linux 向けワンライナー

    ```sh:ワンライナー
    curl -fsSL get.docker.com -o get-docker.sh && sh get-docker.sh && sudo gpasswd -a $USER docker && sudo docker run hello-world && rm -f get-docker.sh
    ```

    ```shell:内訳
    curl -fsSL get.docker.com -o get-docker.sh && \ # ダウンロード
      sh get-docker.sh && \                         # 実行
      sudo gpasswd -a $USER docker && \             # カレントユーザーを docker グループに追加（注１）
      sudo docker run hello-world && \              # Docker のテスト実行
      rm -f get-docker.sh                           # インストーラーの削除

    # （注１）`$ docker 〜` のように `sudo` なしで実行できるように
    #   カレントユーザーに権限を与えています。セキュリティ強化のため、
    #   権限を与えず毎回 `sudo docker` で実行させたい場合はグループに
    #   追加しない（この行は実行しない）でください。
    # 所要時間：15〜25分程度（RaspberryPi3 + Raspbian Jessie + WiFi）
    # 要再ログイン：`docker` グループに追加した場合は、設定を反映させるために再ログインが必要です。
    ```

1. macOS の場合は [Homebrew](https://www.google.com/search?q=site:qiita.com+Homebrew%E3%81%A8%E3%81%AF&tbs=qdr:y) でインストールするのが簡単です

    ```shell-session:
    $ brew install docker
    ...
    ```
#### ARM 系マシンについて

- 2022/08/29 現在、RaspberryPi ZeroW (ARM v6l) + Buster でも上記ワンライナーでインストールできました。<br>`apt install docker.io` だと古い `Docker 18.09.1` が入るので、やはり公式スクリプト or ワンライナーでインストールした方がいいと思います。`docker-compose` も同梱されているし、`apt update && apt upgrade` でアップデートも可能です。

    ```shell-session
    $ docker --version
    Docker version 20.10.17, build 100c701
    
    $ docker compose version
    Docker Compose version v2.6.0
    
    $ apt list --installed 2>&1 | grep docker
    docker-ce-cli/buster,now 5:20.10.17~3-0~raspbian-buster armhf [インストール済み]
    docker-ce-rootless-extras/buster,now 5:20.10.17~3-0~raspbian-buster armhf [インストール済み]
    docker-ce/buster,now 5:20.10.17~3-0~raspbian-buster armhf [インストール済み]
    docker-compose-plugin/buster,now 2.6.0~raspbian-buster armhf [インストール済み]
    
    $ uname -a
    Linux my-rpi-zerow 5.10.103+ #1529 Tue Mar 8 12:19:18 GMT 2022 armv6l GNU/Linux
    
    $ more /proc/device-tree/model
    Raspberry Pi Zero W Rev 1.1
    
    $ cat /etc/os-release
    PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
    NAME="Raspbian GNU/Linux"
    VERSION_ID="10"
    VERSION="10 (buster)"
    VERSION_CODENAME=buster
    ID=raspbian
    ID_LIKE=debian
    HOME_URL="http://www.raspbian.org/"
    SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
    BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
    ```

### 参考文献・関連記事

- [対応 Linux Distro](https://github.com/docker/docker-install/blob/master/install.sh#L321) | install.sh @ GitHub
- [対応アーキテクチャ（CPU）](https://docs.docker.com/install/)| Documents @ docker.com
- [ラズパイ Zero W（ARM v6l）Buster Lite に Docker と docker-compose をインストールする手順【2019/09/29 版】](https://qiita.com/KEINOS/items/1ce933a89706d81ebfa3) @ Qiita
- [ラズパイ Zero W（ARM v6l）Stretch Lite に Docker と docker-compose をインストールする手順【2019/09 版】](https://qiita.com/KEINOS/items/050b9e277569fabd484e) @ Qiita
- 下記記事がとても参考になりました。
    - 「[The easy way to set up Docker on a Raspberry Pi](https://medium.freecodecamp.org/the-easy-way-to-set-up-docker-on-a-raspberry-pi-7d24ced073ef)」| freecodecamp @ Medium （英語）

## TS;DR

### あわせて読みたい Docker のオススメ記事

> 「噂の Docker をインストールしたものの、どうすればいいのか」

そんな（私みたいな）方は、まずは下記チュートリアル記事が "Hello World" から基礎までを端的に学べるのでオススメです。

- 「[Dockerでプログラマが最低限知るべきことが、最速でわかるチュートリアル](https://qiita.com/woz/items/43462398765f8036f3a8)」@ Qiita

また、<font color=red>注意点</font>として **Docker コマンドには新・旧があります**。

[Docker v1.13 前後でスタイルが代わった](https://qiita.com/zembutsu/items/6e1ad18f0d548ce6c266)ので、基本を学ぼうにも旧式のコマンドで説明している記事も多く、記事をまたぐとチャンポンになるがゆえに理解しづらいこともあると思います。

特に Docker の日本語翻訳ドキュメントも常に最新というわけではなく、ググって上位にヒットしたからといって安心できません。やはり、公式のドキュメントの場所をしっかり把握して、ググった結果と最新の公式情報と比較するのが確実だと思います。

- Docker 関連の[リファレンス一覧](https://docs.docker.com/reference/) @ 公式ドキュメント
- [`docker` コマンド （Docker Engine） リファレンス](https://docs.docker.com/engine/reference/commandline/cli/) @ 公式ドキュメント
- [`docker-compose` コマンド リファレンス](https://docs.docker.com/compose/reference/overview/) @ 公式ドキュメント
- [`Dockerfile` 設定リファレンス](https://docs.docker.com/engine/reference/builder/) @ 公式ドキュメント
- [`docker-compose.yml` 設定リファレンス](https://docs.docker.com/compose/compose-file/)  @ 公式ドキュメント

上位の公式リファレンス先を把握したら、以下のように過去１年以内に更新もしくは新規作成された Qiita 記事に絞った検索をするのが良いと思います。

- [「docker 基本」| `tbs=qdr:y`](https://www.google.com/search?q=site:qiita.com+docker+%E5%9F%BA%E6%9C%AC&tbs=qdr:y) | Qiita @ Google


### インストーラーのソースコードを読む

ダウンロードされるインストーラーと GitHub のソースコードには、若干の違いがあります。ダウンロードされる最新のインストーラーには、リリースされた時点のコミット・ハッシュが添えられ、[開発中のソースコードにはありません](https://github.com/docker/docker-install/blob/master/install.sh#L19)。

- ダウンロードされるコード： https://get.docker.com/
- ソースコード： https://github.com/docker/docker-install/blob/master/install.sh
- GitHub リポジトリ: https://github.com/docker/docker-install/

GitHub 上のソースコードが更新されると [Jenkins](https://ja.wikipedia.org/wiki/Jenkins) の [CI テスト](https://github.com/docker/docker-install/blob/master/Jenkinsfile)が実行されます。テストをパスしマージされると、`install.sh` のソースコード内の `SCRIPT_COMMIT_SHA=UNKNOWN` がコミットハッシュに書き換えられ、`get-docker.sh` として上記 `https://get.docker.com/` に公開（デプロイ）されます。

### インストーラーのコミットハッシュ

公式のインストーラであるため安全だと思われますが、ダウンロードしたスクリプト（`get-docker.sh`）と GitHub 側のオリジナル・スクリプト（`install.sh`）を比較することが[推奨されています](https://github.com/docker/docker-install/blob/master/install.sh#L12-L15)。

これは、Docker のイメージやコンテナの安全性以前に、**Docker そのものが汚染されていた場合には元も子もない**からです。

ダウンロードしたスクリプトが正式なものか心配な場合は、途中改ざんされていないか検証することをおすすめします。

<details><summary>インストーラーの改ざん検証</summary><div><br>

リリースされた `get-docker.sh` とオリジナルの `install.sh` を `SCRIPT_COMMIT_SHA` 以外は同じか比較します。

つまり、ダウンロードした `get-docker.sh` に記載されている `SCRIPT_COMMIT_SHA` の変数の値が、GitHub にコミットされた ID になります。このコミットID を元に GitHub 側の `install.sh` と比較して違いがないか確認します。

```bash:比較コマンドのワンライナー
COMMIT_ID=$(cat get-docker.sh | grep 'SCRIPT_COMMIT_SHA=' | sed 's/SCRIPT_COMMIT_SHA=//') && curl -fsSL "https://raw.githubusercontent.com/docker/docker-install/${COMMIT_ID}/install.sh" -o install.sh && diff -u install.sh get-docker.sh
```
```sh:ワンライナーの内訳
COMMIT_ID=$( \
  cat get-docker.sh \
  | grep 'SCRIPT_COMMIT_SHA=' \
  | sed 's/SCRIPT_COMMIT_SHA=//'
) && \
curl -fsSL "https://raw.githubusercontent.com/docker/docker-install/${COMMIT_ID}/install.sh" \
  -o install.sh && \
diff -u install.sh get-docker.sh
```

以下は比較の実行サンプルです。２箇所しか変更がなく、変更内容もリリース時に置き換わるものだけなので、コードは改ざんされていないことがわかります。

```diff:比較の実行サンプル
$ # 作業ディレクトリの作成と移動
$ mkdir ~/test_docker && cd $_
$ ls

$ # インストーラーのダウンロード
$ curl -fsSL get.docker.com -o get-docker.sh
$ 
$ # インストーラーと同じコミットIDのソース比較（get-docker.sh と install.sh の比較）
$ COMMIT_ID=$(cat get-docker.sh | grep 'SCRIPT_COMMIT_SHA=' | sed 's/SCRIPT_COMMIT_SHA=//') && curl -fsSL "https://raw.githubusercontent.com/docker/docker-install/${COMMIT_ID}/install.sh" -o install.sh && diff -u install.sh get-docker.sh
--- install.sh	2018-12-20 20:32:26.623285170 +0900
+++ get-docker.sh	2018-12-20 20:32:26.273285437 +0900
@@ -16,14 +16,14 @@
 #
 # Git commit from https://github.com/docker/docker-install when
 # the script was uploaded (Should only be modified by upload job):
-SCRIPT_COMMIT_SHA=UNKNOWN
+SCRIPT_COMMIT_SHA=4957679
 
 
 # This value will automatically get changed for:
 #   * edge
 #   * test
 #   * experimental
-DEFAULT_CHANNEL_VALUE="test"
+DEFAULT_CHANNEL_VALUE="edge"
 if [ -z "$CHANNEL" ]; then
 	CHANNEL=$DEFAULT_CHANNEL_VALUE
 fi
$ 
$ ls
get-docker.sh  install.sh
$
$ # 問題がなければ比較用ファイルの削除
$ rm install.sh
$
$ # Docker のインストール
$ sh get-docker.sh
（略）
$
$ # バージョン確認
$ docker --version
Docker version 18.06.1-ce, build e68fc7a
$
$ # インストーラーの削除
$ rm get-docker.sh
$ 
$ # Docker の HelloWorld 実行
$ sudo docker run hello-world
$ 
$ # 以下は毎回 docker 実行時に sudo を付けたくない場合
$ 
$ # ユーザーを docker グループに追加
$ sudo gpasswd -a $USER docker
$ # ログアウトし再ログインでグループ追加を反映させる
$ exit
```

</div></details>

### 対応OS

Linux 上でスクリプトを走らせると**インストーラーが対応 OS であるか自動判断してくれます**が、事前に対応しているか確認したい方のために、対応 OS をリストアップしました。

記載フォーマットは以下のようになっています。Docker をインストールしたいマシンのタイプと OS 情報を確認してからご覧ください。

- `<マシンタイプ>`-`<OS>`-`<バージョン>`

<details><summary>マシンのタイプとOSの詳細を確認する</summary><div>

```shell-session:マシンタイプの確認
$ uname -m
armv7l
```
```shell-session:OSの確認
$ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 8 (jessie)"
NAME="Raspbian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
```

</div></details>

#### RedHat系

##### [CentOS](https://ja.wikipedia.org/wiki/CentOS)

- x86_64-centos-7
- aarch64-centos-7

##### [Fedora](https://ja.wikipedia.org/wiki/Fedora)

- x86_64-fedora-28
- x86_64-fedora-29
- aarch64-fedora-28
- aarch64-fedora-29

#### [Debian](https://ja.wikipedia.org/wiki/Debian)系

##### Raspbian

- armv6l-raspbian-jessie
- armv7l-raspbian-jessie
- armv6l-raspbian-stretch
- armv7l-raspbian-stretch

##### Debian

- x86_64-debian-jessie
- x86_64-debian-stretch
- x86_64-debian-buster
- aarch64-debian-jessie
- aarch64-debian-stretch
- aarch64-debian-buster
- armv7l-debian-jessie
- armv7l-debian-stretch
- armv7l-debian-buster

##### [Ubuntu](https://ja.wikipedia.org/wiki/Ubuntu)

- x86_64-ubuntu-trusty
- x86_64-ubuntu-xenial
- x86_64-ubuntu-bionic
- x86_64-ubuntu-cosmic
- s390x-ubuntu-xenial
- s390x-ubuntu-bionic
- s390x-ubuntu-cosmic
- ppc64le-ubuntu-xenial
- ppc64le-ubuntu-bionic
- ppc64le-ubuntu-cosmic
- aarch64-ubuntu-xenial
- aarch64-ubuntu-bionic
- aarch64-ubuntu-cosmic
- armv7l-ubuntu-trusty
- armv7l-ubuntu-xenial
- armv7l-ubuntu-bionic
- armv7l-ubuntu-cosmic