Docker/DockerHub/install/command/

# Dockerとは
インフラ関係やDevOps界隈で注目されている技術の一つで、
Docker社が開発している、コンテナ型の仮想環境を作成、配布、実行するためのプラットフォームのこと。

Dockerは、Linuxのコンテナ技術を使ったものでよく仮想マシンと比較される。
VirtualBoxなどの仮想マシンでは、ホストマシン上でハイパーバイザを利用しゲストOSを動かし、その上でミドルウェアなどを動かす。
それに対し、コンテナはホストマシンのカーネルを利用し、プロセスやユーザなどを隔離することで、
あたかも別のマシンが動いているかのように動かすことができます。そのため、軽量で高速に起動、停止などが可能。

Dockerを使用する利点として以下が挙げられる。 
- コード化されたファイルを共有することで、どこでも誰でも同じ環境が作れる。
- 作成した環境を配布しやすい。
- スクラップ＆ビルドが容易にでき、ホスト環境を汚すことがない。

以上から、複数人数での開発における開発環境の共有が容易であり、テスト環境や実行環境での環境構築が容易であることがわかる。
比較的新しいアプリケーションであるが、今後ますます使用されていくであろうことは間違いないと考えられる。

Dockerでは、コンテナというものをホストOSの上に構築し、
Docker Engineによってあたかも別の環境（マシン）で動いているかのように見せかけることができる。
このコンテナは、docker imageをrun（実行）することで生成される。このimageを取得するに3つの方法があり、
1つ目はDocker Hubに公開されているimageをpullする方法。
2つ目は、自分で作成したDockerfileをbuildする方法。
3つ目は、少し異なるが、起動しているコンテナからcommitすることで生成する方法がある。
Docker Hubを通してimageを共有することもできるが、
Dockerfileを作成することでより簡単に環境の共有が可能であり
変更履歴が可視化でき作業効率があがる。

# dockerhubとは
Dockerレジストリのことであり、Dockerimageを保管している場所。
このDockerimageは、コンテナ作成のためのもととなるもの。
imageはコンテナを生成するための道具のようなものである。

# Dockerのインストール
### Ubuntu 20.04 LTS
参考サイト(https://docs.docker.com/engine/install/ubuntu/)

１. 更新してパッケージをインストール

```
$ sudo apt-get update

$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
```

２. Dockerの公式GPGキーを追加。

```
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

３. リポジトリを設定する

```
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
```

４. DOCKER ENGINEをインストールする

```
 $ sudo apt-get update
 $ sudo apt-get install docker-ce docker-ce-cli containerd.io
```

### docker desktop for mac
[Docker Hub](https://hub.docker.com/)のサイトで、sign upしてインストールする。
インストールできたら、上のバーにアイコンが出てたらおけ。

# Dockerのコマンド説明
### login
```
$ docker login
```
Dockerhubにアクセスできる状態にする。
IDとパスワードを求められるかもしれない、Login Succeededと出ればよい。
Macの場合は上のバーの鯨にポインタを合わして、Docker DeskTop is runningと緑丸が出てたらdockerを使える。

### pull
```
$ docker pull <image>
```
DockerhubからHost(MyPC)にimageをもってくる。

### images
```
$ docker images
```
pullしたimage一覧を確認することができる。

### run
```
$ docker run -it <image> <command>
$ docker run --name <name> <image>
```
imageからContainerを生成&Containerを立ち上げプログラムの実行。

runコマンドは`docker create <image>`と
`docker start <container>`を一緒にしたもの。

引数<command>なしの場合は、デフォルトコマンドが実行される。
引数<command>指定した場合は、指定したコマンドに上書きされる。

> -i: インプット可能(STDIN STDOUT STDERR チャネルを開く)
> -t: 表示が綺麗になる
> --name <name>: コンテナ名を指定 

### detached mode/(short-term)foreground mode
```
$ docker run -d <image>
```
コンテナ起動後にdetachする(バックグラウンドで可動)。

```
$ docker run --rm <image>
```
コンテナをExit後に削除する(一回きりのコンテナ)。

### ps
```
$ docker ps -a
```
Containerのプロセスステータスを確認。
現在稼働中(Up)のContainerのみ表示。
オプション-aで、すべてのContainerのプロセスステータスを確認。

### restart
```
$ docker restart <container>
```
停止中(Exited)のContainerを再度起動(Up)させる。

> exitとdetahの違い
> exit: プロセスを切ってcontainerから出る。
> detach(Ctrl + p + q): プロセスを残してcontainerから出る。docker attachコマンドで戻ることができる。

### exec
```
$ docker exec <container> <command>
```
Containerに任意のプログラムを実行させる。

### commit
```
$ docker commit <container> <new image>
```
Containerから新しいimageを作成する。

### tag
```
$ docker tag <source> <target>
```
古いimageを残したまま、新しいimage名で作成。
リポジトリpush時、dockerhub内のリポジトリ名とimage名は一致している必要があるため。

### push
```
$ docker push <image>
```
Dockerhubにimageをアップロードする。

### rmi
```
$ docker rmi <image>
```
imageを削除する。

### rm/stop/systemprune
```
$ docker rm <container>
```
コンテナの削除。

```
$ docker stop <container>
```
コンテナの停止。
Up状態のContainerを削除する際に、停止してから削除する必要がある。

```
$ docker system prune
```
コンテナ全削除。

### build
```
$ docker build <directory>
```
実行すると指定したDirectoryをbuild contextとしてdocker daemonに渡す。
そして、docker daemonがDockerfileからimageを作成。
danglingimage(none)が作成される。

```
$ docker build -t <name> <directory>
```
オプション-tでimage名を指定。

> Docker daemon: オブジェクトを管理している。CLIを通してDocker daemonに対して命令をしている。
> build context: build時にDocker daemonに渡しているDirectoryのこと。
不必要なものはbuild context内には入れない。

```
$ docker build -f <dockerfilename> <build context>
```
Dockerfileという名前のファイルがbuild contextに存在しない場合。
Dockerfileとbuild contextを分けて管理する場合に有効。

# Dockerfile
Dockerfileはimageの設計図のようなもので、Dockerfileからimageを作る。
一般的には、Dockerfileからimageを作ることが多い。
ファイル名はDockerfileという命名規則がある。
`INSTRUCTION arguments`の形式で記述。

### INSTRUCTION
```
FROM <arguments>
```
ベースとなるイメージを決定。
既存のimageを使用する。

```
CMD ["executable", "param1", ...]
```
コンテナのデフォルトのコマンドを指定。
原則Dockerfileの最後に記述する。

```
ENTRYPOINT ["executable"]
CMD ["param1", ...]
```
コンテナのデフォルトコマンドを指定。
runした時に上書きすることはできない。
CMDのように上書きされたくないコマンドを指定。
ENTRYPOINTがある場合のCMDはオプションの役割になる。

> `docker run`をコマンドとして使用する場合にENTRYPOINTがよく使われる。

```
ENV <key> <value>
ENV <key>=<value> ...
```
コンテナ内の環境変数を設定する。

```
WORKDIR <絶対path>
```
INSTRUCTIONの実行するディレクトリを変更する。
RUNコマンドは基本root(/)直下で実行されるため、WORKDIRで指定してあげる。
WORKDIRに指定したディレクトリが存在しなければ自動で作成される。

###Layerを作成するINSTRUCTION
```
RUN <arguments>
RUN <arguments> && <arguments>
```
Linuxのコマンドを実行する。
RUN毎にimage layerが追加される。
RUNを使用しすぎて、image layerが多くなり過ぎてしまう場合は&&でつなげる。
バックスラッシュ(\)で改行。

```
COPY <src> <dest>
```
ホストからコンテナにファイルを渡すことができる。
コンテナ内に持っていきたいファイルがある場合に使用する。

```
ADD <src> <dest>
```
tarの圧縮ファイルをコピーして解凍したい場合。
コンテナ内に持っていきたいファイルサイズが大きい場合に圧縮することで軽減できる。

#HostとContainerの関係
###ファイルシステム共有
```
$ docker run -it -v <host mount path>:<container> <image> bash
```
Hostのファイルシステムをコンテナにマウントする。

###アクセス権限共有
```
$ docker run -it -u $(id -u):$(id -g) -v <host mount path>:<container> <image> bash
```
ホストが持つホストのファイルシステムに対するアクセス権限を、コンテナに引き継ぐ。
コンテナ内でホストが実行できること以上のことが実行できないようになる。
指定しない場合は、root権限を持って実行されるため、不都合が生じる場合がある。

###ポートを繋ぐ(publishする)
```
$ docker run -it -p <host_port>:<container_port> <image> bash
```
コンテナのポートにアクセスするためには、ホストのポートとコンテナのポートをつなげる必要がある。
`<host_port>`に接続すると`<container_port>`に接続していることになる。

###コンピュータリソースの上限設定
```
$ docker run --cpus <# of CPUs>
```
コンテナがアクセスできるCPU上限を設定。

```
$ docker run --memory <byte>
```
コンテナがアクセスできるメモリ上限を設定。

```
$ docker inspect <container>
```
コンテナの詳細情報を表示。

> macOSでのCPU・メモリ確認コマンド
>> sysctl -n hw.physicalcpu_max : 物理コア数
>> sysctl -n hw.logicalcpu_max  : 論理コア数
>> sysctl -n hw.memsize         : メモリ

> LinuxでのCPU・メモリ確認コマンド
>> fgrep 'physical id' /proc/cpuinfo | sort -u | wc -l : 物理CPUの数
>> fgrep 'cpu cores' /proc/cpuinfo | sort -u | sed 's/.*: //' : CPUコア数
>> fgrep 'processor' /proc/cpuinfo | wc -l : 論理プロセッサー数
>> cat /proc/meminfo : メモリ