Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@
* [資料を追加するには](docs/misc/wiki-usage/how-to-add-post.md)
* [エディタを選ぼう](docs/lecture/select-editor/select-editor.md)
* [JavaScript(ES6)入門](docs/lecture/js-getting-started.md)
* [Docker](docs/lecture/introducing-docker/0-index.md)
* [Dockerとは?](docs/lecture/introducing-docker/1-what-is-docker.md)
* [Dockerを使う](docs/lecture/introducing-docker/2-use-docker.md)
* [Dockerの概念](docs/lecture/introducing-docker/3-docker-concepts.md)
* [Dockerまとめ・参考文献](docs/lecture/introducing-docker/4-conclusion.md)

3 changes: 2 additions & 1 deletion book.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"language": "ja"
"language": "ja",
"plugins": ["hints"]
}
45 changes: 45 additions & 0 deletions docs/lecture/introducing-docker/0-index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Docker

- Author: [coord.e](https://twitter.com/coord_e)

## この記事について

ここでは、[Docker](https://www.docker.com/)というソフトウェアについて

- 何をするものか
- 導入の利点
- 各種概念(イメージ、コンテナなど)について
- 使用方法

について解説する。なおここでは以下の点には触れないため、各自[参考文献](./4-conclusion.html#参考文献--further-reading)を別途参照されたし。

- Docker内部の仕組み(cgroups、コンテナランタイムなど)
- 発展的な利用(マルチアーキテクチャ、マルチステージビルドなど)
- インフラに組み込んだ活用

### 対象読者

- 自分の開発を効率化するためにDockerを使いたい人
- Dockerについて聞いたことがあるが、なんだかわからないか使えるようになりたい人
- SakutenDevでインフラを担当する人
- など

なお、この記事は読者としてある程度GNU/Linuxの扱いに慣れている人を想定している(コマンドライン操作、`/usr/local`などのファイル構造など)。知らないと読めないわけでもないが、わかりにくい点や伝わらない表現があるかもしれない。違和感を感じたらDiscordなどで気軽に質問してほしい。

## 用語について

一般的に様々な意味で使用される用語について、この記事内では特に以下の意味合いで使用している。

- 環境: ソフトウェアを実行する際のファイルやプロセスの状態
- ソフトウェア: 主にユーザーと直接のインタラクションなしで動くようなソフトウェア([MySQL](https://www.mysql.com/jp/)、[nginx](https://nginx.org/ja/)など)
- ライブラリ: 共有ライブラリ。([glibc](https://www.gnu.org/s/libc/)など)


## 表記について

- `$ command`: $から始まるコードブロックは、コマンドラインを示している。Windowsならcmd.exeやpowershell、macOSならTerminal.appやiTerm2、GNU/Linuxなら好きなターミナルで、`$`から後の部分を打ち込む。
- `< something >`: そのまま入力するのではなく、適宜読み替えてほしい

## 次

[Dockerとは?](1-what-is-docker.md)
62 changes: 62 additions & 0 deletions docs/lecture/introducing-docker/1-what-is-docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
## Dockerとは?

> Docker(ドッカー)はコンテナ型の仮想化環境を提供するオープンソースソフトウェアである。

[Docker - Wikipedia](https://ja.wikipedia.org/wiki/Docker)

意味がわからないので噛み砕いて説明する(Wikipediaにマウントを取ろうとするオタクなので)

## 例として考えるシステム

ここでは例として、以下のようなシステムを動かす状況を考える。

1. ソフトウェアA: ライブラリBのバージョン1.0以下とライブラリCのバージョン3.0以上が必要
2. ソフトウェアD: ライブラリBのバージョン2.0以上が必要
3. ソフトウェアE: ソフトウェアAとソフトウェアCと通信する必要がある

(以下、このシステムを「システムS」と呼ぶことにする)

{% hint style='info' %}
具体的に考えたければ、

- システムS → Webアプリケーションのバックエンド
- ソフトウェアA → データベース
- ライブラリB → ネットワーク処理ライブラリ
- ライブラリC → ファイル操作ライブラリ
- ソフトウェアD → サーバーソフト
- ソフトウェアE → 管理コントロールパネルアプリ

と置き換えるとイメージが湧きやすいと思う。
{% endhint %}

## 何が嬉しいのか

Dockerによってもたらされることの本質は、「環境を共有できること」で(あると私は考えてい)る。

何かソフトウェアを動かそうとした時に、環境構築に悩まされたことは誰しもある経験だと思う。
環境構築が必要なのは、本質的には「ソフトウェアが動作するために必要な要件を実行環境に課しているから」であると言える。例えばシステムSで言えば、ソフトウェアDは「ライブラリBのバージョン2.0以上が存在している」という要件をを環境に課している。そのため、ソフトウェアDを動作させるためにはまずライブラリBのバージョン2.0以上を環境に導入して、その要件を満たす必要がある。
しかし、(ライブラリ1つ程度ならまだしも)要件が複雑になっていくにつれて、動作させるための正確な環境を用意するのは難しくなってくる。システムSで言えば、ソフトウェアAがその一例である。多くの人がそのソフトウェアを使用する場合、その全員に同じ環境を用意してもらうのが骨の折れる作業であることは容易に想像がつくだろう。さらに特定の条件の環境でのみ発生するバグがあった場合、それを複数の開発者が再現させるのはさらに至難の技になる。

この問題(環境に対する動作要件が複雑だと困る、ということ)に対し、ソフトウェア開発者たちは様々なアプローチを行ってきた。例えば最近のパッケージマネージャは"lockfile"という、ソフトウェア間の依存関係を正確に記述しておくファイルを生成することが多くなっている([package-lock.json](https://docs.npmjs.com/files/package-lock.json), [yarn.lock](https://yarnpkg.com/lang/ja/docs/yarn-lock/), [Cargo.lock](https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html)など)。この手法では、全てのユーザーが簡単なコマンドで(そのパッケージマネージャが管理する範囲内で)同じ環境を用意できるようになっている。

しかし、それでもこのアプローチ(lockfile)はそのパッケージマネージャが扱う範囲内でしか問題を解決してくれない。システムの深い部分 -ライブラリが依存しているCのライブラリなど- は、依然としてユーザーごとの環境に依存してしまっているため、ある程度は先述の問題が避けられなくなってしまう。

ここで登場するのがDockerだ。Dockerを使うと、「環境それ自体」を丸ごと配布(共有)できる。システムSで例えるならば、ソフトウェアAを配布する際に、ソフトウェアAの動作に必要なライブラリBとライブラリCを含んだ環境を配布するということだ。ユーザーはそれを使って、意図された環境で確実にソフトウェアAを動作させることができるのである。また利用者全員に同じ環境を配布しているので、バグの再現も容易だ。

別の言い方をすると、例えばソフトウェアAが「Ubuntu 18.04にパッケージXを入れた環境」で動作確認ができている場合、「Ubuntu 18.04にパッケージXを入れた環境」をそのままユーザーに配布すればみんな同じ環境で実行できるよね、というなかなか強引な考えなわけだ。とはいえ、Dockerのこのアプローチは世間で広く認められ、非常に広い分野で活用されている。

## VirtualBox, Vagrant, VMwareなどとの違い

技術に詳しい読者なら、VirtualBoxなどのイメージを配布すればいいではないかと思うかもしれない。しかしご存知の通り、これらハイパーバイザ型仮想化ソフトウェアで使用するイメージは巨大で、配布するのは一苦労だ(数GBのファイルを不特定多数に共有するのは大変でしょう)。さらにOSを丸ごと仮想化しているため、仮想環境の起動/終了に非常に時間がかかる。内部ではパソコンを起動/終了するのと同じことをシミュレートしているわけなので、これは避けられないコストだ。

Dockerがこれらの仮想化ソフトウェアと違う点は、OS(正確にはカーネル)をホスト環境と共有している点だ。これによってイメージを軽量に保つことができ([Ubuntu 18.10は29MB](https://hub.docker.com/_/ubuntu?tab=tags))、さらに起動/終了も高速に行うことができる。

## 不変性/再現性

Webアプリケーションなどの複雑なシステムでは、環境の一部を変更しただけでシステム全体の障害につながるということが簡単に起こりうる。Dockerの用意する「環境」は、それ自体不変のもので、変更を加えても容易に以前の状態に戻すことができる。これにより障害に対する対応が簡単になったり、開発の際にトライアンドエラーで試すといったような際の効率が圧倒的に上がったりする。(この辺りは試した方がよくわかると思うので、今は「ふーんそうなんだ」程度に思ってもらえれば構わない)

## 次

次章では、実際に手を動かしながらこれらの利点について体験してもらうと共に、Dockerを構成する基本概念について説明する。

[Dockerを使う](2-use-docker.md)
113 changes: 113 additions & 0 deletions docs/lecture/introducing-docker/2-use-docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Dockerを使う

さて、長々しい説明も終わったので実際にDockerを使っていこう。

## Dockerのエディション(Edition)について

- [Docker Enterprise Edition (Docker EE)](https://docs.docker.com/ee/)
- [Docker Community Edition (Docker CE)](https://docs.docker.com/install/)

の2エディションが存在している。EEは企業向けのものなので、私たちが個人で使う分には基本的にDocker CEを使うことになるだろう。

Docker CEは無料で利用できる。

## Dockerをインストールする

インストール方法は本当によく変わるので、英語が読める人は[公式ドキュメント](https://docs.docker.com/install/)を読むのがいいと思う。

{% hint style='info' %}
あまり私の所有していないプラットフォームでのインストール方法については自信がないので、あえて抽象的な説明にとどめておく。ごめんなさい。わからなかったら気軽にDiscordなどで質問してください。
{% endhint %}

### macOSの人

1. [ここ](https://hub.docker.com/editions/community/docker-ce-desktop-mac)から、`Docker.dmg`をダウンロードし、中に入っているappをインストールする。
1.1. (なおHomebrew Caskを使っている人は`brew cask install docker`で入る)
2. `Docker.app`を起動し、指示に従う。(パスワードを聞かれたりします)

### Windowsの人

Microsoft Windows 10 64-bitのProfessionalまたはEnterpriseが必要。

1. [ここ](https://hub.docker.com/editions/community/docker-ce-desktop-windows)からインストーラをダウンロードする。
2. インストーラを実行し、指示に従う。
3. インストールが完了したら、`Docker for Windows`を起動し、指示に従う。

なお、Windows 10 64-bit ProfessionalまたはEnterpriseではないWindows(Windows 10 Homeなど)では、[Docker Toolbox](https://docs.docker.com/toolbox/overview/)を使うことでDockerを使用することができる。しかし、個人的には無料のGNU/Linuxに移行するか新しいWindowsをインストールすることをお勧めする。

### GNU/Linuxの人

[CentOS](https://docs.docker.com/install/linux/docker-ce/centos/)、[Debian](https://docs.docker.com/install/linux/docker-ce/debian/)、[Fedora](https://docs.docker.com/install/linux/docker-ce/fedora/)、[Ubuntu](https://docs.docker.com/install/linux/docker-ce/ubuntu/)向けのインストールガイドが公式にあるのでそれを見て、インストールする。

(全部書けないです、ごめんなさい、わからなかったらぜひ質問してください)

## Dockerを使ってみる (Hello World)

```shell
$ docker -v
```

バージョンが出てきたと思う。

{% hint style='tip' %}
GNU/Linuxユーザーで権限がどうとか言われた場合は[これをみて](https://docs.docker.com/install/linux/linux-postinstall/)
{% endhint %}

ではいよいよHello Worldだ。いざ

```shell
$ docker run hello-world
```

なんか色々英語で出てきたと思う。正常に実行されたならば、以下のようなメッセージが表示されたはずだ。

```
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/
```

🎉

## もうちょっと役に立つことをする

下のコマンドを入力してほしい。

```shell
$ docker run -p 8080:80 nginx
```

なんだかダウンロードが始まるので、しばらく待つ。

下のようなメッセージが表示されたら、ブラウザで[http://localhost:8080](http://localhost:8080)を開いてみよう。

```
Status: Downloaded newer image for nginx:latest
```

ブラウザから、以下のようにnginxが起動している様子が見えると思う。

![nginx](assets/nginx.png)

このように、なんの環境構築をすることもなく、Webサーバーが構築できてしまった。これが先に述べた「環境を共有する」ということだ。

## 次

[Dockerの概念](3-docker-concepts.md)
Loading