Dockerで学んだ事をまとめています!!

# Linuxの基礎
## シェルについて知ろう

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/c26ed852-e268-2af0-fca7-4d910d75d9b7.png)

実際は、Kernelに対して命令をしたいが出来ない
Kernelの周りのShellを仲介して命令を出す

Shellを使うのに必要なアプリケーションがターミナル
ターミナルがShellに命令を出し、ShellがKernelに命令を出す

画像引用:
[第 ５ 回 UNIX入門(3) ... シェル/応用プログラム](http://www.mlab.im.dendai.ac.jp/linux/2010/No5/index.html)

## 環境変数について知ろう
環境変数とはOSの上で動くプロセス(ターミナルやchromeのブラウザetc...)が情報を共有するための変数

# Dockerを使ってみる
## 概要
Dockerとは、コンテナという技術を使ってそのコンテナの中で環境を構築し
コードを実行する事でそれぞれ同じ環境を使う事が出来る。
同じコンテナを立ち上げれば同じ環境を構築出来る

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/40372c4e-f31d-b305-ca54-48f56c5b39ed.jpeg)

画像引用:
[Docker - Docker (software) - JapaneseClass.jp](https://www.bing.com/images/search?view=detailV2&ccid=NJ7bf%2fmy&id=2BE75A1F26D60D90F2F069A32F7E7255A5ABBAA6&thid=OIP.NJ7bf_myr1RWlXPq_Vm6IwHaFj&mediaurl=https%3a%2f%2fcultivatehq.com%2fimages%2fposts%2fdocker.jpg&exph=960&expw=1280&q=docker+image+画像&simid=608054119819514487&FORM=IRPRST&ck=00E01B635820FD7AA56BF657B1077BCA&selectedIndex=0&idpp=overlayview&mode=overlay)

コンテナはDocker imageと呼ばれるものから作られる
Docker imageはDocker fileから作られる (Docker imageの設計図)
コンテナからDocker imageを作る事も出来る

## DockerHubからhello-worldをpullする
DockerHubからhello-worldというimageを自分のパソコンに持って来る

手順:
- DockerHubにログイン
- Docker Imageを自分のパソコンに持ってくる(プルする)
- 保存されているかDocker imageのリストを表示する

~~~
$ docker login
$ docker pull <image>
$ docker images
~~~

Docker imageをpullする
$ docker pull hello-world

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/d7f2d816-8458-983a-a938-07262154dd08.png)

自分のパソコンにpullされているか確認する
$ docker images
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/2ab8dd34-88de-8be6-b89d-afeeeffc5f00.png)

library/hello-worldとは何処なのか?
https://hub.docker.com/_/hello-world

## hello-worldのコンテナを作ってみる

使うコマンド:
~~~
$ docker run <image>
$ docker ps
~~~

イメージからコンテナを作る

$ docker run hello-world

![fafa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/8c2d3628-af94-83e0-7eca-fb1cdadfaeb5.png)

作ったコンテナを見てみる
$ docker ps
![nmzvc,..PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/2df7e2e3-a8a6-501c-0bfa-6176742b5fd9.png)

何も表示されていない 
=> 実は、このコマンドはアクティブなコンテナを表示するもの

$ docker ps -a
全てのコンテナを表示する
![riueoqw.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/c2ce4d0c-c527-c7ac-2a01-57696f65f0df.png)

Docker imageをrunするとコンテナが作られる
コンテナの中にプログラムがあり、それを実行する (今回の場合、Hello from Docker!とテキストが出力される)
exitする

## UbuntuのDocker imageをrunする

$ docker run -it ubuntu bash

-it: bash起動時に必要なおまじない(オプション)
bash: コンテナ起動時に実行するプログラム

![akfjld;s.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/d5b4ad67-c082-9367-d17c-2dae712bbb60.png)

Docker imageをrunすると、コンテナが作られ何かプログラムが動く(今回はbashというプログラムを動かしている)

## Ubuntuのコンテナを更新する
![akjfdl;s.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/b2e27c1d-6dc3-28ba-1f24-ea0dfb3327e8.png)

画像引用元:
https://www.prplbx.com/resources/blog/docker-part1/

### Docker imageを更新する方法
- コンテナから直接更新する方法
- Docker fileから更新する方法

今回は、コンテナから更新する
~~~
$ touch file test
~~~
testファイルをコンテナの中に作る
=> 新しいlayerの方で、新しくtestfileというファイルが作られたという情報が入る

~~~
$ exit
~~~
コンテナから出る。

## コンテナをrestartして再度コンテナを起動する
exitされたコンテナに対してrestartというコマンドを使って、コンテナを再度起動する

~~~
docker restart <container>
~~~

execというコマンドを使ってbashを再度起動する

~~~
docker exec <container> <command>
~~~

detachを使ってexitする
~~~
detach: ctrl+p+q
~~~

### exit detachの違い:

#### exit: 
コンテナを動かしているプロセスを切ってコンテナを出る
#### detach: 
プロセスを残したままコンテナを出る

## コンテナをcommitして変更内容をDocker imageする

#### 現時点でのおさらい、、、
- dockerhubからubuntuのimageをHostに持ってくる
- ubuntuというimageからコンテナを作る
- コンテナの中にtestというファイルを作った

今回は、コンテナの中にtestというファイルを作っただけだが、
普通はJavaを入れたり、Rubyを入れて開発環境を整える

コンテナの中にtestというファイルを作り、
変更を加えたのでその新しいコンテナを他のメンバーにも使って貰う必要がある
=> コンテナをイメージに保存して他のメンバーにイメージを配る


~~~
$ docker commmit <container> <new image>
~~~

コンテナからdocker imageにする

手順: 
(1) コンテナがexited状態なのでdocker restartコマンドを使ってUPにする
~~~
$ docker restart <container>
~~~

<br>

###### <font color="Red">exited状態でexecコマンドを使うとエラーが発生する!!</font>
~~~
Error response from daemon: Container 75296c3f427ff1bd5e4499c213643881a9240de29c432bd66eb6347089ab4fc7 is not running
~~~

##### =>  docker restartでUPにする必要がある!!

(2)コンテナをdocker imageに保存する

~~~
$ docker commit 75296c3f427f ubuntu:updated
~~~

dokcer imagesで確認してみると、、、
![kjldfa;.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/25ce3fc4-2ef2-053c-5684-eed9baf3ca59.png)

## DockerHubにリポジトリを作成する

基本的には、Ubutuというイメージに対して1つのリポジトリがあるように、
自分の新しいイメージに対して1つのリポジトリを作成する

![fdjkl;as.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/a5aec9e0-015b-0d8b-870b-3477fd53f844.png)



Ubuntuのイメージは1つだが、Tag別でいろいろなUbuntuのバージョンが保存される

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

![fgj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/cc6fb003-7225-2e0f-8218-7f8d115d0473.png)

#### <font color = "red">イメージの名前は、リポジトリ名に合わせる必要がある!!</font>

例: username/my-first-repoの時、image名は、username/my-first-repo

## Docker imageを別名で保存する

source: 元の名前
target: 新しい名前

~~~
$ docker tag <source> <target>
~~~
<br>

今回の場合、、、
~~~
$ docker tag ubuntu:updated <username>/my-first-repo
~~~
![dfkjla.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/c526d800-3d37-8bea-d4b6-20461630cc11.png)

元々の名前「ubuntu:latest」は本来の名前は、、、
###### registry-1.docker.io/library/ubuntu:latest

## DockerHubにDocker imageをpushする

手順: 
(1)別タグで保存したイメージを確認する
~~~
$ docker images
~~~

(2)実際に、pushする
~~~
$ docker push <image>
~~~

# Dockerの動きをもう少し理解しよう

## $docker runは何をしているのか

~~~
$ docker run
~~~

docker imageからコンテナを作成するコマンド

正確に言うと、、、

#### <font color ="red">run = create + start</font>

dockerのコンテナをcreateして
更に、dockerのコンテナをstartしている。

![falkj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/5fe72214-a867-8f1a-fe0c-1a3ae4a7e3ec.png)

画像引用:

https://penpen-dev.com/blog/docker-command/#toc2

~~~
$ docker create image
~~~

コンテナが作られる。
docker ps -aで確認するとcreatedという状態


~~~
$ docker start
~~~

作られたコンテナをスタートする。
実際には、コンテナ内のデフォルトのプログラムを
docker statというコマンドで実行される

#### <font color ="red">デフォルトで設定されたプログラムを実行するだけ!!</font>

この後はExitedという状態になる

### 実際にターミナルを見てみよう!!

~~~
$ docker run hello-world
~~~

![fldkja.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/1096d841-a27d-b891-e734-38d4e2fecdfb.png)

- hello-worldのイメージからコンテナを作成する
- デフォルトコマンドを実行する

~~~
$ docker ps -a
~~~
![fdlak;.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/e6cffeb1-35d6-7f9a-d129-fc47d2a8a5be.png)

ステータスがExitedになっている!!

~~~
$ docker create hello-world
~~~

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/60dc1d05-7cd6-770a-f4fa-088d73f41e49.png)

~~~
$ docker ps -a
~~~
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/d2c548cc-9b6a-39c9-3da5-45ebbeb3c7c9.png)

今コンテナが作られただけの状態
=> デフォルトコマンドは実行されてない , コンテナ自体スタートしてない

~~~
$  docker start 8bbb9dfe7c08
~~~

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/1d76c53d-991c-91b9-186e-d204a319a4e6.png)

~~~
docker ps -a
~~~
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/6a44ab0d-d6e4-60eb-4ea1-d78fd21bf175.png)

##### ステータスがExitedになっている!! 
##### コマンドが実行されるのでUPでは?:confused:

#### docker startでは、、、
- コンテナをUpする
- デフォルトコマンドを実行する
- 直ぐに、Exitedされる!!

docker startでは、
デフォルトコマンドの実行結果を見る事が出来ない。
見る為のオプションが、

~~~
$ docker start -a
~~~

実際に試してみると、、、
~~~
$ docker start -a 9e03f0625d22
~~~
![fklajd.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/5dd0291e-41ba-ad18-0f6a-8fdbce789918.png)

このCOMMANDがコンテナのデフォルトのコマンド,コンテナが実行された時に指定されたコマンド

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/3e457c7e-ce76-6f4f-1ae5-13bc3bcb7106.png)

## コマンドの上書き

~~~
$ docker run <image>
~~~
Docker imageのデフォルトのコマンドが実行される

~~~
$ docker run <image> <command>
~~~
Docker imageのデフォルトのコマンドが上書きされて実行される

実際に試してみると、、、
~~~
$ docker run ubuntu
~~~

~~~
$ docker ps -a
~~~

![dkfljsa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/1975871c-1f02-f735-f9b2-66f2ba86f9c0.png)

bashのプログラムが実行している事が分かる。

![ljdkafs.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/55469379-ba48-ceee-7fdd-3ff8babeead8.png)


##### しかし、直ぐにコンテナから出る(Exitedの状態になる)のでその出力を見る事は無い!!
##### => bashを実行した状態を保持する為に-itがある。

~~~
 docker run -it ubuntu
~~~
~~~
:/#
~~~

## -itって何してるの?
![lfdjk.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/0fa4c6b4-3593-4395-aa2f-8e1ae8bb9160.png)

-itが何をしているのか実際に見てみよう!!

-iを抜いて実行してみると、、、

~~~
 docker run -t ubuntu bash
~~~

~~~
/#
~~~

一見何も問題無いように見えるがlsコマンドを実行すると、、、
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/d258a401-e310-c0cb-5e21-a83522b41982.png)
##### 何も返ってこない!!:scream:

コンテナにlsが反映されてない,lsが飛んでない!!

#### 以上より、-iは、ホストからコンテナへの入力チャネルを開く役割!!

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/924d9608-836b-922f-0c87-36e6ae78e997.png)

STDIN , STDOUT , STDERR この3つのチャネルを使って
Linuxのプログラムにコミュニケーションをとってる

キーボードで打ったものがSTDINというチャネルを通してプログラムに行って、このプログラムからディスプレイに結果を表示する為にSTDOUT, STDERRというチャネルを使ってる。

###### -i: STDINをホストからコンテナに繋げる役割

-iをしないとホストからコンテナのチャネルが開かないので
キーボードで打っても認識されない。

~~~
$ docker run -i ubuntu bash
~~~

![flka.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/9727d5bb-865f-3539-e8d2-3cc625f745b5.png)

##### 出力結果が綺麗じゃない, プリティじゃない
##### => -tは、出力結果をプリティにする


## コンテナの削除

- コンテナの削除
~~~
$ docker rm <container>
~~~

- コンテナを止める
~~~
$ docker stop <container>
~~~

- コンテナ全削除(便利)
~~~
$ docker system prune
~~~

コンテナは、このように溜まってくる
一度、Exitedしたコンテナにまた再度何かする事はそんなに多くない

定期的に削除していくのが良い!!

![fkaldj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/07d9aa3c-c52e-447f-837b-2b6baaad281f.png)

実際に試してみると、、、
~~~
docker rm cac2debd6876
~~~

![fkaldj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/64129b7d-0a2d-e5cd-4ee8-80216032bb8e.png)

![lfdakj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/40296054-0c4f-03e0-2b43-9519738dff96.png)

IDがcac2debd6876のコンテナを削除出来た!!

動いているコンテナを削除しようとすると、、、

![ladfkj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/1d7888b9-3820-4b4b-d11e-835e2aaf3e2f.png)


~~~
docker rm  64ccf36cf6b6
~~~

~~~
Error response from daemon: You cannot remove a running container 64ccf36cf6b686cec583a171733af88d36bf86df30cbf18ed58b17acdc23390e. Stop the container before attempting removal or force remove
~~~

コンテナを止めてみると

![lafkj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/a7e8f887-996c-4ef2-faca-83b620a1fe7d.png)

~~~
$ docker stop 64ccf36cf6b6
~~~

![lfdkj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/f3b925a1-8cde-a220-f470-37e39b20bc7b.png)

docker system prune: 全ての止まってるコンテナを削除する
~~~
$ docker system prune
~~~
![dfkjla.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/fb86e4a8-a84d-6cd6-471e-b4482d8e2731.png)


削除する前:
![fdla;k.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/8a09e424-a277-4626-e77a-cad2e09d88fc.png)

削除後:
![ldkfj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/340f73ea-6e7e-6ba0-4f0c-c73239146675.png)


## コンテナのファイルシステムの独立性

コンテナのファイルシステムは、ホストからのファイルシステムや他のコンテナのファイルシステムから独立している。
2つコンテナを立てて、それぞれにtest1 , test2というファイルを作ってそれぞれのコンテナから参照出来ない事を確認する

~~~
$ docker run -it ubuntu bash
~~~
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/66a36e37-34e2-25b5-b0b0-b0ce2acc2066.png)

~~~
$ docker run -it ubuntu bash
~~~

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/bf23b2bd-2c32-ba42-0baf-f24f60248fd8.png)

片方のbinファイルを編集しても、
もう片方のbinファイルに全く反映されない!!

## コンテナ名を指定してrunする

コンテナに名前を付ける
~~~
$ docker run --name <name> ubuntu
~~~

どういう時に名前を付けるのか、、、
- 起動させ続けるコンテナを立てるとき
- 共有サーバを使うとき
- 他のプログラムで使用するとき

実際に試してみると、、、
~~~
$ docker run --name sample_container ubuntu
~~~
![ladkfj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/c52307ff-de2e-f409-b281-9908fa87f010.png)

名前を付けないとどうなるのか、、、
~~~
docker run ubuntu
~~~

何か知らない変な名前が付いてる
![djsfh.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/09e44db1-006e-6988-7427-5876e901ea43.png)

既に同じ名前がある時どうなるのか、、、
~~~
docker run --name sample_container ubuntu
~~~

~~~
docker: Error response from daemon: Conflict. The container name "/sample_container" is already in use by container "71d642a44c404581b1fcbc5e6cdebdc13ff251f4ed080ff04aa831cc37ea138c". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.
~~~

#### <font color ="red">同じ名前のコンテナを作る事は出来ない!!</font>

## detachedモードとforegroundモード

detached mode:
~~~
$ docker run -d <image>
~~~
コンテナを起動後にdetachする(バックグラウンドで動かす)

(short-term)foreground mode:
~~~
$ docker run --rm <image>
~~~
コンテナをExit後に削除する(一回きりのコンテナ)

## Dockerfileとは
![ladfk.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/2809f8a0-0112-b5fa-b03e-2c796763f134.png)


画像引用:

https://geekflare.com/fr/dockerfile-tutorial/

Dockerfileを使う事でDocker imageを作る事が出来る。
(Docker imageの設計図)
Docker imageだけ見ても、どういうコンテナかは分からない
Dockerfileは、テキストで書かれているのでどういうコンテナになるかは、分かるようになっている。

#### Dockerfileを自由に書ける => Dockerを使いこなせる!!

## Dockerfileを作ってみよう!!
### <font color ="Red"> INSTRUCTION argumentsという形で書く!!</font>

INSTRUCTION: dockerの命令コマンド
arguments: INSTRUCTIONに対する引数

例: 
~~~
FROM scratch
~~~

#### Dockerfileを作ろう!!
Desktopのdockerフォルダにdockerfileを作成する
~~~
$ cd ~/Desktop
$ mkdir docker
$ cd docker
$ touch Dockerfile
~~~


~~~dockerfile:Dockerfile 
FROM ubuntu:latest
RUN touch test
~~~

FROM: 元となるベースのイメージを指定する
RUN: これを使って、Linuxのコマンドを実行する

~~~Dockerfile 
FROM ubuntu:latest
~~~
元となるDocker imageを指定している。(:latestは無くてもよい)
ubuntu:latestを取ってきてその上に何か新しいことをする


今回のDockerfileは、
- Ubuntuというイメージをベースにする
- touch testというLinuxコマンドを実行する

DockerfileからDocker imageを作る際に、
予めtestというファイルが作られた状態でDocker imageが出来る。

## DockerfileをbuildしてDocker imageを作る

DockerfileからDocker imageを作るには、
Docker buildというコマンドが必要

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/52e01296-6aee-3a8e-6e1e-94cda340daf3.png)


~~~
$ cd ~/Desktop/docker
$ docker build <directory>
$ docker images
$ docker build -t <name> <directory>
~~~

docker buildの使い方:
- Dockerfileがあるdockerフォルダに移動する
- 移動した先で$ docker build . コマンドを実行する
  (. は、カレントディレクトリを示す)

~~~
$ docker images
~~~
Docker imageが出来ているか確認するコマンド

~~~
$ docker build -t <name> <directory>
~~~
-t: これを付ける事でDocker imageに名前を付けて作る事が出来る。

実際にDocker imageを作ってみよう!!
~~~
$ docker build .
~~~

エラー発生:

![error.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/e721db4c-061a-fdc9-b3a3-21703f713187.png)

~~~dockerfile:Dockerfile
# latestがtestになってた!! 
FROM  ubuntu:test
RUN touch test
~~~

下記のように修正して、再度コマンドを実行する
~~~dockerfile:Dockerfile
FROM  ubuntu:latest
RUN touch test
~~~

こちらのコマンドでイメージが作られたか確認する
~~~
$ Docker images
~~~

~~~
REPOSITORY               TAG       IMAGE ID       CREATED          SIZE
<none>                   <none>    d9629dd78a11   22 seconds ago   77.8MB
~~~

## ビルドしたDocker imageをrunする

docker imagesでイメージの確認をする
~~~
$  docker images

REPOSITORY               TAG       IMAGE ID       CREATED          SIZE
<none>                   <none>    d9629dd78a11   22 seconds ago   77.8MB
~~~

コンテナの中に入る
~~~
$ docker run -it d9629dd78a11 bash
/# ls
~~~
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/c38c886d-c175-3523-de71-687f404de072.png)

コンテナの中に実際にtestファイルがある事を確認できた。

# Dockerfileの書き方と基本
## FROM

- ベースとなるイメージを決定する
- DockerfileはFROMから書き始める(一番最初を書く)

例: 
~~~dockerfile:Dockerfile
FROM ubuntu:latest
RUN touch test
~~~

#### ベースとなるイメージとは?
Docker fileを作ってbuildして、Docker imageを作成する
Docker imageは基本的にFROMで指定したDocker imageの上にレイヤーとしてRUN ～ とかが来る。
FROMの上に積み重なっていく感じ。

docker build . すると、、、
![dklfjs.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/beb4eb3a-e289-819d-c6f0-15684efacb43.png)

FROM docker.io/library/ubntu:latestに、RUN touch testが追加されるイメージ
~~~
FROM docker.io/library/ubuntu:latest
~~~

~~~
CACHED [2/2] RUN touch test
~~~

### <font color ="RED">FROMは、ほとんどの場合OSを指定する!!</font>

## RUN 

- Linuxコマンドを実行
- RUNを使うことで好きなようにカスタマイズ出来る
- RUN毎にLayerが作られる

Layerとは?


#### <font color ="RED">基本的には、RUNを使ってカスタマイズしていく!!</font>

例: 
~~~dockerfile:Dockerfile
FROM ubuntu:latest
RUN touch test
~~~

実際に使ってみると、、、
~~~dockerfile:Dockerfile
FROM  ubuntu:latest
RUN touch test
RUN echo 'hello world' > test
~~~

~~~
$ docker build .
~~~

![ldkfsj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/5e993ea8-9d99-c341-0dcd-875367afc2e3.png)

## Layer数を最小限にするために
RUNを書く度にDocker image Layerが増える
=>Docker imageのサイズが大きくなる!!

#### <font color ="RED">Docker imageのLayer数は最小限にする!!

- Layerを作るのはRUN, COPY, ADDの3つ
- コマンドを&&で繋げる
- バックスラッシュ(\)で改行する

#### 実際は、Dockerfileを作る場合パッケージをインストールする!!

Ubuntuではapt-getまたはaptというコマンドでパッケージを管理する

常に、新しいパッケージリストを取得してからインストールする!!
~~~
$ apt-get update : 新しいパッケージリストを取得
$ apt-get install <package> : <package>をインストール
~~~

## cacheを使おう
~~~Dockerfile:dockerfile
RUN apt-get update
RUN apt-get install
~~~

この時、apt-get install用のlayer , apt-get update用のlayerが作られる。
この時、他のパッケージをインストールする時、再度updateしなくて良い
=> 既に、imageが作られパソコンの方に保存されているのでそのキャッシュを使ってくれている!!

例:
~~~Dockerfile:dockerfile
FROM  ubuntu:latest
RUN apt-get update && apt-get install -y \
    curl\
    nginx
~~~

-y: インタラクティブな質問をyで答える

~~~
$ docker build .
~~~
![dsklfj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/58a6482c-45b7-f333-1474-d90dae94185d.png)


~~~Dockerfile:dockerfile
FROM  ubuntu:latest
RUN apt-get update && apt-get install  -y \
    curl\
    cvs\
    nginx
~~~
cvsというパッケージを追加してdocker build .すると、、、
=> update , install を0からやり始める
=> キャッシュを使って短縮できる!!

~~~Dockerfile:dockerfile
FROM  ubuntu:latest
RUN apt-get update && apt-get install  -y \
    curl\
    nginx
~~~

CVSというパッケージが無い状態でdokcer build . する
![ldskfj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/6f03f4bb-4192-40fb-fac9-c47338230872.png)

次にcsvを追加して再度、docker build . する

~~~Dockerfile:dockerfile
FROM  ubuntu:latest
RUN apt-get update && apt-get install  -y \
    curl\
    nginx
RUN apt-get  install -y cvs
~~~

この時、キャッシュを使って
~~~
FROM  ubuntu:latest
RUN apt-get update && apt-get install  -y \
    curl\
    nginx
~~~

↑部分を飛ばして
~~~
RUN apt-get  install -y cvs
~~~
追加した部分を実行している

## CMD
- CMD: コンテナのデフォルトコマンドを指定
- CMD["executable", "param1", "param2"]
- 原則Dockerfileの最後に記述
- 1つのDockerfileに1つだけ使える

~~~Dockerfile:dockerfile
FROM  ubuntu:latest
RUN apt-get update && apt-get install  -y \
    curl\
    cvs\
    nginx
CMD ["ls"]

~~~

作ったイメージをdocker runで実行すると、、、
~~~
bin
boot
dev
etc
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
~~~
lsのコマンドが起動した!

## RUNとCMDの違い
- RUNはLayerを作る => Docker imageの構成するのに使われる!!
- CMDは作らない

# $docker buildの詳細と、その他のinstruction
## $docker buildは何をしているのか

何故、docker buld する時にコンテナごと指定しているのか？
~~~
$docker build .
~~~

docker build する時に指定フォルダをdockerデーモンに渡す
docker デーモンがフォルダとDockerfileを元にイメージを作る
この時のフォルダをbuild contextという

![dlfk;s.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/de1b47cf-c533-1dbe-4b20-795f678ec744.png)


画像引用:

https://www.memotansu.jp/docker/199/

## docker deamonとは
![tiroue.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/263137c4-9ac9-5a4c-a87f-703ec7ab1748.png)


画像引用:

https://www.bing.com/images/search?view=detailV2&ccid=bIQOZL%2fp&id=4A0F26F7D57D70CE7A621F68DE6248BE3F66407F&thid=OIP.bIQOZL_pZujjrfaaYlQ_gQHaFJ&mediaurl=https%3a%2f%2fstatic.coderbridge.com%2fimg%2ftechbridge%2fimages%2fkdchang%2fdocker101%2flinux-vs-docker-comparison-architecture-docker-components.png&exph=1389&expw=2000&q=docker+architecture&simid=608008661914223421&FORM=IRPRST&ck=854AAD9EDA6E80CED90B7707ED0B18E0&selectedIndex=2&mode=overlay

- docker コマンドでdocker deamonに命令を出す
- docker deamonがある所を DockerHostと呼ぶ

## build contextとは?
- contextとは、状況や環境の意味
- buildに使わないファイルはbuild contextに入れない
- ADDやCOPYでbuild contextの中にあるファイルをimageに持っていける

docker buildのコマンドを打つと、、、
- build contextがdocker deamonに渡される
- build contextとDockerfileの中身を使ってdocker imageを作る

## COPY
build contextの中のDockerfile以外のファイルをDocker imageに組み込む
最終的にコンテナで使う事が出来る。
コンテナのファイルシステムとホストのファイルシステムは違う
=> COPY を使うことでホストからコンテナにファイルを受け渡す

ホストのsomethingというファイルをコンテナに渡す

(1) dockerフォルダにsomethingというファイルを作成
~~~
$ touch something
~~~

(2) Dockerfileを作成する

~~~Dockerfile:dockerfile
FROM  ubuntu:latest
RUN mkdir /new_dir
COPY something /new_dir/
~~~

(3) イメージを作成する
~~~
$ docker build .
~~~

![ldkfj.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/d39b0262-457b-ff25-6be1-fd6da95e021a.png)

(4)コンテナを作成する
~~~
$ docker run -it 
~~~

(5)ファイルがあるか確認する
~~~
:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  new_dir  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

/# ls /new_dir
something
~~~

## COPY と ADDの違い

- 単純にファイルやフォルダをコピーする場合 => <font color = "red">COPY </font>
- tarの圧縮ファイルをコピーして解凍する => <font color ="red">ADD</font>

helloを圧縮したcompressed.tarを解凍してコンテナに組み込む

(1) sample_folderを作成する
~~~
$ mkdir sample_folder
~~~

(2) sample_folderにHelloというファイルを作成する
    (helloという文字列を入れる)
~~~
$ echo 'hello' > hello
~~~

(3)sample_folderで圧縮ファイル(compressed.tar)を作成する
~~~
$ tar -cvf compressed.tar sample_folder
~~~

(4)Dockerfileを作成する
~~~dockerfile:dockerfile
FROM ubuntu:latest
ADD compressed.tar /
~~~

(5)イメージを作成する
~~~
$ docker build .
~~~

(6)コンテナを立ち上げる
~~~
$ docker run -it --rm 9a21f97fd388
~~~

(7)ファイルを確認する
~~~
$ cat /sample_folder/hello
~~~

~~~
/# cat /sample_folder/hello
hello
~~~

#### <font color ="red">ADDは、tarファイルを移動させてそこで解凍したいのに使うのがほとんど!!</font>

## Dockerfileがbuild contextに無い場合
前回までのbuildは、build contextの中にDockerfileを作っていた
=> Dockerは、build contextを見てDockerfileを探してこれを元にdocker buildしてdocker imageを作っていた

Dockerfileという名のファイルがbuild contextに入ってない場合
~~~
$ docker build -f <dockerfilename> <build context>
~~~

どういう時に -f , dockerfilenameを指定するのか?
- Dockerfileが複数用意する時

例: 開発用: Dockerfile.dev , テスト用: Dockerfile.test
    

sample_folderをbuild contextとし、dockerフォルダの中にあるDockerfileを指定してbuildする
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/a5fea48f-4f32-0409-499d-342d50af26f5.png)

Dockerfile(Dockerfile.dev)を作成する
~~~dockerfile:Dockerfile.dev
FROM ubuntu:latest
RUN apt-get update && apt-get install  -y \
    curl\
    cvs\
    nginx
CMD ["/bin/bash"]
~~~

docker buildする
~~~
docker/sample_folder# docker build -f ../Dockerfile.dev .
~~~
![fdsjk.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/5c6eef93-5018-0edd-4552-19008945ed3c.png)

Dockerfileとbuild contextは分けて管理出来る!!

## CMD と ENTRYPOINTの違い

CMD: デフォルトのコマンドを指定する

UbuntuだったらCMDが/bin/bashになっている
=> Ubuntuのdocker imageをdocker runしたら/bin/bashが実行される

~~~
CONTAINER ID   IMAGE                    COMMAND                  CREATED          STATUS                      PORTS                                            NAMES
91c038704849   ubuntu                   "bash"                   13 seconds ago   Exited (0) 11 seconds ago                                                    elegant_hertz
~~~

bashになっているが上書きする事が可能
~~~
$ docker run ubuntu ls
~~~

~~~
# docker run ubuntu ls
bin
boot
dev
etc
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
~~~

ENTORYPOINT: 
- デフォルトのコマンドを指定できる!!(ここだけは、CMDと同じ)
- ###### <font color ="red">runの時に上書き出来ない</font>

- ENTORYPOINTがある場合は、CMDは["param1", "param2",...]の形をとる(つまりENTORYPOINTで指定した引数をとる , ENTORYPOINTで指定したコマンドのオプションを指定する)


例:
ENTORYPOINTを使わない場合
~~~dockerfile:Dockerfile
FROM ubuntu:latest
RUN toch test
CMD ["ls", "--help
~~~

<br>

ENTORYPOINTを使う場合
~~~dockerfile:Dockerfile
FROM ubuntu:latest
RUN touch test
ENTORYPOINT ["ls"]
CMD ["--help"]
~~~

↑の時、CMDのオプション部分だけrunで上書き出来る!!


- コンテナをコマンドのようにして使いたい時に使う

例: 
~~~dockerfile:Dockerfile
FROM ubuntu:latest
RUN touch test
ENTRYPOINT [ "ls" ]
CMD ["--help"]
~~~

~~~
$ docker build .
~~~

![dklfjs.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/616c2f0c-ee50-b2ae-1166-217fe2a31617.png)

~~~
$ docker run 4f4059d4c7fd0d7dd19dde10646eb86900bb5394c128d68f63acd040d1bb22ab 
~~~

~~~
Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.

Mandatory arguments to long options are mandatory for short options too.
  -a, --all                  do not ignore entries starting with .
  -A, --almost-all           do not list implied . and ..
      --author               with -l, print the author of each file
  -b, --escape               print C-style escapes for nongraphic characters
      --block-size=SIZE      with -l, scale sizes by SIZE when printing them;
                               e.g., '--block-size=M'; see SIZE format below
  -B, --ignore-backups       do not list implied entries ending with ~
  -c                         with -lt: sort by, and show, ctime (time of last
                               modification of file status information);
                               with -l: show ctime and sort by name;
                               otherwise: sort by ctime, newest first
  -C                         list entries by columns
      --color[=WHEN]         colorize the output; WHEN can be 'always' (default
                               if omitted), 'auto', or 'never'; more info below
  -d, --directory            list directories themselves, not their contents
  -D, --dired                generate output designed for Emacs' dired mode
  -f                         do not sort, enable -aU, disable -ls --color
  -F, --classify             append indicator (one of */=>@|) to entries
      --file-type            likewise, except do not append '*'
      --format=WORD          across -x, commas -m, horizontal -x, long -l,
                               single-column -1, verbose -l, vertical -C
      --full-time            like -l --time-style=full-iso
  -g                         like -l, but do not list owner
      --group-directories-first
                             group directories before files;
                               can be augmented with a --sort option, but any
                               use of --sort=none (-U) disables grouping
  -G, --no-group             in a long listing, don't print group names
  -h, --human-readable       with -l and -s, print sizes like 1K 234M 2G etc.
      --si                   likewise, but use powers of 1000 not 1024
  -H, --dereference-command-line
                             follow symbolic links listed on the command line
      --dereference-command-line-symlink-to-dir
                             follow each command line symbolic link
                               that points to a directory
      --hide=PATTERN         do not list implied entries matching shell PATTERN
                               (overridden by -a or -A)
      --hyperlink[=WHEN]     hyperlink file names; WHEN can be 'always'
                               (default if omitted), 'auto', or 'never'
      --indicator-style=WORD  append indicator with style WORD to entry names:
                               none (default), slash (-p),
                               file-type (--file-type), classify (-F)
  -i, --inode                print the index number of each file
  -I, --ignore=PATTERN       do not list implied entries matching shell PATTERN
  -k, --kibibytes            default to 1024-byte blocks for disk usage;
                               used only with -s and per directory totals
  -l                         use a long listing format
  -L, --dereference          when showing file information for a symbolic
                               link, show information for the file the link
                               references rather than for the link itself
  -m                         fill width with a comma separated list of entries
  -n, --numeric-uid-gid      like -l, but list numeric user and group IDs
  -N, --literal              print entry names without quoting
  -o                         like -l, but do not list group information
  -p, --indicator-style=slash
                             append / indicator to directories
  -q, --hide-control-chars   print ? instead of nongraphic characters
      --show-control-chars   show nongraphic characters as-is (the default,
                               unless program is 'ls' and output is a terminal)
  -Q, --quote-name           enclose entry names in double quotes
      --quoting-style=WORD   use quoting style WORD for entry names:
                               literal, locale, shell, shell-always,
                               shell-escape, shell-escape-always, c, escape
                               (overrides QUOTING_STYLE environment variable)
  -r, --reverse              reverse order while sorting
  -R, --recursive            list subdirectories recursively
  -s, --size                 print the allocated size of each file, in blocks
  -S                         sort by file size, largest first
      --sort=WORD            sort by WORD instead of name: none (-U), size (-S),
                               time (-t), version (-v), extension (-X)
      --time=WORD            change the default of using modification times;
                               access time (-u): atime, access, use;
                               change time (-c): ctime, status;
                               birth time: birth, creation;
                             with -l, WORD determines which time to show;
                             with --sort=time, sort by WORD (newest first)
      --time-style=TIME_STYLE  time/date format with -l; see TIME_STYLE below
  -t                         sort by time, newest first; see --time
  -T, --tabsize=COLS         assume tab stops at each COLS instead of 8
  -u                         with -lt: sort by, and show, access time;
                               with -l: show access time and sort by name;
                               otherwise: sort by access time, newest first
  -U                         do not sort; list entries in directory order
  -v                         natural sort of (version) numbers within text
  -w, --width=COLS           set output width to COLS.  0 means no limit
  -x                         list entries by lines instead of by columns
  -X                         sort alphabetically by entry extension
  -Z, --context              print any security context of each file
  -1                         list one file per line.  Avoid '\n' with -q or -b
      --help     display this help and exit
      --version  output version information and exit

The SIZE argument is an integer and optional unit (example: 10K is 10*1024).
Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers of 1000).
Binary prefixes can be used, too: KiB=K, MiB=M, and so on.

The TIME_STYLE argument can be full-iso, long-iso, iso, locale, or +FORMAT.
FORMAT is interpreted like in date(1).  If FORMAT is FORMAT1<newline>FORMAT2,
then FORMAT1 applies to non-recent files and FORMAT2 to recent files.
TIME_STYLE prefixed with 'posix-' takes effect only outside the POSIX locale.
Also the TIME_STYLE environment variable sets the default style to use.

Using color to distinguish file types is disabled both by default and
with --color=never.  With --color=auto, ls emits color codes only when
standard output is connected to a terminal.  The LS_COLORS environment
variable can change the settings.  Use the dircolors command to set it.

Exit status:
 0  if OK,
 1  if minor problems (e.g., cannot access subdirectory),
 2  if serious trouble (e.g., cannot access command-line argument).

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report any translation bugs to <https://translationproject.org/team/>
Full documentation <https://www.gnu.org/software/coreutils/ls>
or available locally via: info '(coreutils) ls invocation'
~~~
ls --helpで出力したオプション結果になっている!!


~~~
$ docker run 4f4059d4c7fd0d7dd19dde10646eb86900bb5394c128d68f63acd040d1bb22ab -la
~~~

~~~
total 56
drwxr-xr-x   1 root root 4096 Feb  3 13:55 .
drwxr-xr-x   1 root root 4096 Feb  3 13:55 ..
-rwxr-xr-x   1 root root    0 Feb  3 13:55 .dockerenv
lrwxrwxrwx   1 root root    7 Nov 30 02:04 bin -> usr/bin
drwxr-xr-x   2 root root 4096 Apr 18  2022 boot
drwxr-xr-x   5 root root  340 Feb  3 13:55 dev
drwxr-xr-x   1 root root 4096 Feb  3 13:55 etc
drwxr-xr-x   2 root root 4096 Apr 18  2022 home
lrwxrwxrwx   1 root root    7 Nov 30 02:04 lib -> usr/lib
lrwxrwxrwx   1 root root    9 Nov 30 02:04 lib32 -> usr/lib32
lrwxrwxrwx   1 root root    9 Nov 30 02:04 lib64 -> usr/lib64
lrwxrwxrwx   1 root root   10 Nov 30 02:04 libx32 -> usr/libx32
drwxr-xr-x   2 root root 4096 Nov 30 02:04 media
drwxr-xr-x   2 root root 4096 Nov 30 02:04 mnt
drwxr-xr-x   2 root root 4096 Nov 30 02:04 opt
dr-xr-xr-x 246 root root    0 Feb  3 13:55 proc
drwx------   2 root root 4096 Nov 30 02:07 root
drwxr-xr-x   5 root root 4096 Nov 30 02:07 run
lrwxrwxrwx   1 root root    8 Nov 30 02:04 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 Nov 30 02:04 srv
dr-xr-xr-x  11 root root    0 Feb  3 13:55 sys
-rw-r--r--   1 root root    0 Jan 21 13:09 test
drwxrwxrwt   2 root root 4096 Nov 30 02:07 tmp
drwxr-xr-x  14 root root 4096 Nov 30 02:04 usr
drwxr-xr-x  11 root root 4096 Nov 30 02:07 var
~~~
ls -la で出力したオプション結果になっている!!

## ENV
環境変数を設定してくれる
(環境変数: OSの上で動くあらゆるプロセスが情報を共有するために使う変数)
書き方: 
~~~
ENV <key> <value>
~~~

~~~dockerfile:Dockerfile
FROM ubuntu
ENV key1 value
ENV key2=value
ENV key3="v a l u e" key4=v\ a\ l\ u\ e
ENV key5 v a l u e 
~~~

~~~
$ docker build .
~~~
![kldjfas.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/e9b49e13-4e24-73e7-0c09-99e5c9f4238a.png)

~~~
$  docker run -it --rm a29b4a78bd11bc8be62ee4f3b82979a192e76e8423c22e55c17c6a3ade376c1a bash
~~~

~~~
/# env
~~~
環境変数の一覧を表示するコマンド
<br>
~~~
HOSTNAME=82bc94195429
PWD=/
HOME=/root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
TERM=xterm
key4=v a l u e
key5=v a l u e
key2=value
key3=v a l u e
key1=value
SHLVL=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
_=/usr/bin/env
~~~

## WORKDIR
DockerfileにあるDocker instractionを実行するディレクトリを変更する

~~~Dockerfile:Dockerfile
FROM ubuntu:latest
RUN mkdir sample_folder
RUN cd sample_folder
RUN touch sample_file
~~~
このmkdir , cd , touchがどのディレクトリで実行されるのかを考えてみる。

~~~
RUN mkdir sample_folder
~~~
sample_folderはルートディレクトリの下で作られる(きっと)

~~~
RUN cd sample_folder
~~~
sample_folderに移動する

~~~
RUN touch sample_file
~~~
##### sample_folderに移動しているので、samplefolderの下につくられるわけではない!!

##### <font color ="red">実際は、ルート直下で作られてる!!(Docker instractionは、ルート直下で実行される)</font>

##### そこで、WORKDIRを使えば、指定したディレクトリにファイルを作れる!!

実際に見てみると、、、
~~~dockerfile:Dockerfile
FROM ubuntu:latest
RUN mkdir sample_folder
RUN cd sample_folder
RUN touch sample_file
~~~

イメージを作成する
~~~
$ docker build .
~~~

コンテナを立ち上げる
~~~
$ docker run -it c6c4f853e2c703888378f3e0c5a256e792e1d17c1b13a5206f256340a3c6d9b4 bash
~~~

sample_folderの中身を確認する
~~~
/# ls sample_folder
/# 
~~~

###### <font color ="red">RUN touch sample_fileにより、sample_fileが作られているはず!!しかし、無い!!</font>

WORKDIRを使うことでそれ以降のDocker instractionの実行を指定したディレクトリで行える!!

例：
~~~dockerfile:dockerfile
FROM ubuntu:latest
RUN mkdir sample_folder
WORKDIR /sample_folder
RUN touch sample_file
~~~

~~~
$ docker build .
~~~

~~~
$ docker run -it c1bb0d52b3cc bash
~~~

~~~
/sample_folder# ls
sample_file
~~~

##### <font color ="red">今回は、sample_folderの下にsample_fileを作成出来た!!</font>

# ホストとコンテナの関係
## -vを使ってファイルシステムを共有する

~~~
-v <host>:<container>
~~~
オプションでホストのファイルシステムをコンテナにマウントする




![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2565038/05f86df8-b426-5506-08ea-af80638abc9f.png)

###### 通常、ホストとコンテナのファイルシステムは全くの別物<br>ファイルシステムをマウントする事であたかもホストのファイルシステムがコンテナのファイルシステムにあるかのようにする事が出来る!!

使い方: 
- コードをホストに置いておいて、コードを実行する時にコンテナを使うとき
- データサイエンスの時、大きなデータをホスト側で持っておき、コンテナをそのデータを解析する環境に使う

###### ホストのmounted_folderをコンテナDockerで作ったnew_dirというフォルダにマウントする

mounted_folderを作成する
~~~
$ mkdir mounted_folder
~~~

mounted_folderの下にファイルを作成する
~~~
$  touch mounted_folder/file_at_host
~~~

Dockerファイルを作成する
~~~dockerfile:dockerfile
FROM ubuntu:latest
RUN mkdir new_dir
~~~

~~~
$ docker build .
~~~

~~~
$ docker run -it -v ~/Desktop/mounted_folder:/new_dir 115f06700dcb bash
~~~

~~~
# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  new_dir  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
~~~

~~~
$ cd new_dir
~~~

~~~
# ls
file_at_host
~~~

## -u オプションを使って、アクセス権限を共有する
ホストのファイルをマウントする事によって、コンテナからホストのファイルシステムにアクセス出来た!!
##### <font color ="red">問題点</font>
コンテナは基本的に何にも指定しなければroot権限を持つ
ホスト側のファイルはユーザーidやグループidでアクセス権を管理されてる

##### <font color ="red">ホスト側のファイルにroot権限を持ってアクセス出来てしまう!!</font>

よって、-uを使ってコンテナを起動する時にrootではなく
指定したユーザーID , グループIDでrunをする


ユーザーIDとグループIDを指定してコンテナをrunする
~~~
-u <user id >:<group id>
~~~

##### 使い方:

ユーザーidを確認する
~~~
$ id -u
~~~
~~~
501
~~~

グループidを確認する
~~~
$ id -g
~~~
~~~
20
~~~


Dockerfileを作成する
~~~dockerfile:Dockerfile
FROM ubuntu:latest
RUN mkdir created_in_Dockerfile
~~~
~~~
$ docker build .
~~~

-uを使って、ユーザーを指定してdocker run する
~~~
$ docker run -it -u $(id-u):$(id -g) -v ~/Desktop/mounted_folder:/created_in_run 115f06700dcb 
~~~

## -pオプションを使って、ホストとコンテナのポートを繋げる

ポート: プロセスがデータ通信する際に使う物

サーバーに何かwebサービスを立てたとする。
ユーザーがこのwebサービスにアクセスするには、サーバーのIPアドレスが必要
このサーバーに複数のwebサービスがあった場合、ホストのIPアドレスだけだと、どのwebサービスにアクセスすれば良いのか分からない
=> この時にポートを使う , ポートをwebサービスに割り当てる

###### コンテナに何かwebサービスを立てた時、ホストのポートにアクセスしてもコンテナのポートには繋がらない!!

ホストのポートからコンテナのポートにアクセスする為に
繋げる必要がある(パブリッシュする)

使い方:
~~~
$ docker run -it p 8888:8888--rm jupyter/datascience-notebook bash
~~~

~~~
$ jupyter notebook
~~~

ブラウザからlocalhost:8888にアクセスする