なぜコンテナを導入するのか ~ 各職種への説得材料をまとめる

# はじめに

本記事では、コンテナに触ったことがない人に対して、コンテナ利用時のメリットを説明するための資料を公開します。
なお、ディップ社内ではPHPが利用している部署が多いので、PHPに関する記述が多いです。
注) この記事でことわりがない場合、｢コンテナ｣は｢Dockerコンテナ｣を指します。

# コンテナ技術とコンテナイメージ

コンテナ技術とは、プロセスを隔離して実行するための技術です。
コンテナイメージ(イメージ)とは、｢アプリケーションコードと依存関係を一つにまとめたファイル｣です。
コンテナイメージを元に実行された、隔離されたプロセスになったものをコンテナと呼ばれます。

## VMとの違い

VMは一つ一つにゲストOSが必要です。
コンテナは、プロセスを隔離してHostOS上で動作させることができます。
そのためオーバーヘッドや利用するリソースも少なく、高速に起動します。

![docker-vs-vm.png](https://camo.githubusercontent.com/2c9d4499ecb2900e7b107c607d50be44a0668a85/68747470733a2f2f7777772e646f636b65722e636f6d2f73697465732f64656661756c742f66696c65732f64382f323031382d31312f646f636b65722d636f6e7461696e6572697a65642d616e642d766d2d7472616e73706172656e742d62672e706e67)
https://www.docker.com/resources/what-container


# コンテナを導入するメリット


## プログラミング/エンジニア初心者
- アプリケーションコードと依存関係を一つのイメージにまとめられる
    - 依存パッケージによるエラーがなくなる
- 最初の環境構築がめっちゃ楽になる
    - 複雑なインストール手順を踏まなくていい
- 公開されているコンテナイメージが多数存在する
    - 主要なプログラミング言語やミドルウェアは、公式のコンテナイメージを公開してる
    - 特別な設定は必要なく、動作が保証された環境で動かすことができる
![](https://paper-attachments.dropbox.com/s_50C4732359684C8BFF4A019D21A85FCE9E89B5C2D1F0F264C5DC5AA1B4961E0D_1573215343853_03.jpg)

## サービス開発者
- 開発環境の構築がコードベースで行える
- 開発開始までの時間が短い
- VMに比べてコンピュータリソースを有効活用できる
- 既存の環境に影響を与えず、新しい環境を利用できる
    - 実際にプログラムをインストールしなくてよい
![](https://paper-attachments.dropbox.com/s_50C4732359684C8BFF4A019D21A85FCE9E89B5C2D1F0F264C5DC5AA1B4961E0D_1573215352581_03.jpg)

以下の例では、PHPをインストールせず、PHP5.6とPHP7.3の各バージョンでPHPのコードを動かしています。
https://github.com/tomoyamachi/docker-tutorial/blob/master/00-introduction-ja.md

```shell
# ver5.6環境で実行
$ docker run --rm -it -v $(pwd)/00-php-sample:/app \
    --rm php:5.6-cli-alpine \
    php /app/main.php
NULL

# ver7.3環境で実行
$ docker run --rm -it -v $(pwd)/00-php-sample:/app \
    --rm php:7.3-cli-alpine \
    php /app/main.php

Fatal error: Redefinition of parameter $void in /app/main.php on line 3
```

## インフラ担当向け
- [The Twelve-Factor Apps](https://12factor.net/ja/) の文脈に沿っている
    - コードベースでインフラを管理できる
    - OSへの依存度を減らし、移植しやすくする
    - 開発環境と本番環境の差異を最小限 → CI/CDの促進
    - スケールアップしやすい
- コンテナベースのオーケストレーションサービスが複数存在する
    - 宣言的アプローチ
        - クラスターの状態をフィードバックして、宣言された状態に自己回復する
![](https://paper-attachments.dropbox.com/s_9BB7F3A8B266EB955EC1CC1096D276CD525BC49560035D0C264D82EB53678A7F_1576010516900_image.png)

        - https://www.slideshare.net/Docker/container-orchestration-from-theory-to-practice/
    - Kubernetes
    - Docker-Swarm
    
## セキュリティ担当向け
- CI/CDを実行すると、自動でパッケージが最新のものになる
    - アプリケーションに関するパッケージのアップデート非常に楽
- コンテナプロセスは非root権限で実行されるので、侵入されたときのリスクが下げられる
- アプリケーションコードと依存関係を一つのイメージにまとめた｢イメージ｣ごとに責任を分割できる → どこで利用されているかわからないパッケージ/ライブラリを減らせる
- ただし、Dockerやオーケストレーションツール(Kubernetesなど)に脆弱性が発見されることもある


# FAQ
## どういう原理で動くの?

デフォルトのDockerでは、Linuxカーネルの機能を組み合わせて動きます。
Mac / Windowsだと、Linuxカーネルの機能を小さくまとめたLinuxKitを動かしています。

## これまで覚えた知識は無駄になるの?

無駄になりません。
たとえば、コンテナ間のネットワーク通信では、veth(バーチャルイーサネットデバイス)を用いて通信を実現しています。また、iptablesなどを駆使してコンテナ間の名前解決を行っています。
伝統的な手法を仮想的に行っていることが多いので、トラブルシュートの際は、これまでの知識が必要になってきます。


## 向いてないことはある?

たとえば以下の場合は向いてません。

**複雑なモノリスアプリケーション**
Dockerは1プロセスごとにコンテナを分けることが推奨されます。そのため、複雑すぎてプロセスの分離が難しいものは向いていません。その場合は、[LXC](https://linuxcontainers.org/)など1コンテナで複数プロセス起動が許されているコンテナ技術をつかえます。
※ 2021/10/21追記 : 現在はDocker公式サイトでも、[1つのサービスであれば、1コンテナ1プロセスでなくてよいと記載される](https://docs.docker.com/config/containers/multi-service_container/)ようになりました。 ただし、その場合でも、1つのコンテナに複数の機能を詰め込むことは避けるべきと記載されています。

**特殊なデバイス/リソースを利用する**
たとえば、現在NVIDIA以外のGPUを利用できません。特殊なリソースを利用したい場合、対応できないことがあります。
※ 2020/8/21追記 : AMDのGPUも利用可能になったようです。またその他のGPU driverも利用できるようになる予定です。

# 次のステップ
## [Docker Playground](https://labs.play-with-docker.com/)で実際にさわってみる
1. [DockerHub](https://hub.docker.com/)のアカウントを作成
2. [Docker Playground](https://labs.play-with-docker.com/) にDockerHubアカウントでログインする
3. ｢ADD NEW INSTANCE｣でインスタンスをつくって、dockerコマンドを実行する
4. 作成されたインスタンスで `docker run -dp 80:80 dockersamples/101-tutorial` を実行
![](https://paper-attachments.dropbox.com/s_9BB7F3A8B266EB955EC1CC1096D276CD525BC49560035D0C264D82EB53678A7F_1576016193348_image.png)

# 宣伝

[PHPer向けのDockerチュートリアル](https://github.com/tomoyamachi/docker-tutorial)を作成しました。
日本語で、さっとDockerを動かしたい人はこちらもどうぞ。

# まとめ

実際の勉強会だと、最初の10分くらいで概要を説明して、2時間くらいハンズオン形式で実際にdockerを触っていきます。
うちの会社でもやってほしい、みたいなのがあればご相談ください。