dockerでsinatraサーバーを起動しよう。

# この記事で得られるもの(目的)
- Virtual MachineとDockerの起動方式
- Dockerfileの書き方
- DockerでImageを作る方法
- DockerでContainerを起動する方法

# この記事で扱わないこと
- Dockerのインストール


#Agenda
1. Dockerとは
2. Virtual MachineとDockerの起動方式
3. SintraサーバーのDocker Imageを作る
4. Imageに基づいたContainerを起動させる

# Dockerとは
Dockerは**Image**に基づいて**Container**を起動したりするプログラムです。
**Container**は隔離された空間でProcessを動く技術です。
**Image**はどういう**Container**を作るかについて記録されている設計図みたいなことです。

# Virtual MachineとDockerの起動方式
**Virtual Machineの起動方式**
[(出処)Dockerホームページ](https://www.docker.com/resources/what-container)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453686/69f04bbe-d070-bf42-29ca-6122f8f530c7.png)
例えば、WindowsでLinuxを実行したいとなった場合、
Virtual Machine(Virtual Boxなど)ではHost OS(Windows)の上にGuest OS(Linux)をインストールしてApp Serverを立ち上げることになります。
つまりHost OSとは別のResourceを全部作り直します。

**Dockerの起動方式**
[(出処)Dockerホームページ](https://www.docker.com/resources/what-container)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453686/5a3058be-95b4-001e-bf08-32554b317803.png)
DockerはHost OSのResourceを共有してもらってContainerを起動させる。
だから、VMの方式よりOverheadがかなり少なくなるし、実際使って見ても結構早いですね。

# SintraサーバーのDocker Imageを作る
まず、DockerがContainerを実行するまでの簡略な順を見ましょう。
Dockerは**Dockerfile**に基づいて**Docker Image**を作ります。
その後、**Docker Image**に基づいて**Docker Container**を起動させます。

じゃー、SinatraのAppのための環境を作るための書いて見ましょう。

### **ファイルの位置: /Dockerfile**

```
  1 # baseになるimage
  2 FROM ruby:2.6.5
  3 # このDockerfileを作った人
  4 MAINTAINER jinument@gmail.com
  5
  6 # Docker Containerの環境変数を設定
  7 # ENV 環境変数名 環境変数値
  8 ENV WORKSPACE /app
  9
 10 # HostのファイルをContainer内に追加
 11 # ADD Hostのファイル経路 Container内の経路
 12 # Hostの現在DirectoryにあるGemfileと始まるファイルを
 13 # Container内のWorkspace(ここでは/app)に追加
 14 ADD ./Gemfile* $WORKSPACE/
 15 # Container内の作業Directoryを変更する
 16 # Container内でcd(change directory)コマンドをうつのと同じ
 17 WORKDIR $WORKSPACE
 18 # Container内で実行するコマンドを定義
 19 # このコマンドの意味は
 20 # Container内の/app/でbundle installを実行してという意味
 21 RUN bundle install
 22
 23 ADD . $WORKSPACE
 24
 25 # ContainerのPortを開放する
 26 # このコマンドでHostから4567ポートで
 27 # Container内の4567にアクセスできるようになる
 28 # (参考)Sinatraのサーバーポートが4567だからここで4567を開放する
 29 EXPOSE 4567
 30
 31 # Containerのbuildが出来上がって
 32 # Containerが実行するタイミングでこのコマンドが実行される
 33 CMD ['ruby', 'app.rb']
```

### **ファイルの位置: /app.rb**

```
1 require 'sinatra'
2
3 set :bind, '0.0.0.0'
4
5 get '/health_check' do
6   'health check'
7 end
```

### **ファイルの位置: /Gemfile**

```
1 source 'https://rubygems.org'
2
3 gem 'sinatra', '2.0.8'
```

以下のファイルを同じDirectoryに置いておいて以下のコマンドを実行することで、**Docker Image**を作る。
```docker build -t sinatra_image .```

```-t sinatra_image```は作るimageの名前を指定すること。
```.``` は現在Directoryにある**Dockerfile**を利用して**Docker Image**を作るという意味。

```docker build -t sinatra_image .```このコマンドを打ったら、**Docker**は以下のログを吐き出します。
ログを見ると内が**Dockerfile**に書いた部分が一個づつ実行されることが確認できる。
(**Layer**という概念もあるが、この記事では扱いません。)

```
lee@leeui-MacBookAir  ~/workspace/qiita  docker build -t make_image .
Sending build context to Docker daemon  6.144kB
Step 1/9 : FROM ruby:2.6.5
 ---> a161c3e3dda8
Step 2/9 : MAINTAINER jinument@gmail.com
 ---> Running in ce277718c930
Removing intermediate container ce277718c930
 ---> b56f7155a807
Step 3/9 : ENV WORKSPACE /app
 ---> Running in 3869474ae7c2
Removing intermediate container 3869474ae7c2
 ---> d17245751687
Step 4/9 : ADD ./Gemfile* $WORKSPACE/
 ---> 616bacbaa111
Step 5/9 : WORKDIR $WORKSPACE
 ---> Running in 0a6fd625644c
Removing intermediate container 0a6fd625644c                                                                                                                                buffers
 ---> 2ef75a288ed5
Step 6/9 : RUN bundle install
 ---> Running in df916cdef1f6
Fetching gem metadata from https://rubygems.org/..........
Using bundler 1.17.2
Fetching ruby2_keywords 0.0.2
Installing ruby2_keywords 0.0.2
Fetching mustermann 1.1.1
Installing mustermann 1.1.1
Fetching rack 2.2.2
Installing rack 2.2.2
Fetching rack-protection 2.0.8
Installing rack-protection 2.0.8
Fetching tilt 2.0.10
Installing tilt 2.0.10
Fetching sinatra 2.0.8
Installing sinatra 2.0.8
Bundle complete! 1 Gemfile dependency, 7 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Removing intermediate container df916cdef1f6
 ---> 2ce2af9012c7
Step 7/9 : ADD . $WORKSPACE
 ---> eec1a89dd292
Step 8/9 : EXPOSE 4567
 ---> Running in 4b7d253f9875
Removing intermediate container 4b7d253f9875
 ---> fca62715a481
Step 9/9 : CMD ['ruby', 'app.rb']
 ---> Running in dd5069206a4a
Removing intermediate container dd5069206a4a
 ---> 41e7c0189e0c
Successfully built 41e7c0189e0c
Successfully tagged sinatra_image:latest
```

じゃー、**Image**がちゃんと作られたか以下のコマンドで確認して見ましょう。

```
⚙ lee@leeui-MacBookAir  ~/workspace/qiita  docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
sinatra_image       latest              41e7c0189e0c        32 minutes ago      872MB
```

# Imageに基づいたContainerを起動させる
```
⚙ lee@leeui-MacBookAir  ~/workspace/qiita  docker run -d -p 4567:4567 sinatra_image
023f6c6e7d27a7368a3440163c7faeda406c3e8cc36ee7d254e50c56551200af
```

現状**Container化**されているものの状況を確認するコマンドは以下になります。

```
docker ps -a
```
```
 ⚙ lee@leeui-MacBookAir  ~/workspace/qiita  docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES
023f6c6e7d27        sinatra_image     "/bin/sh -c '['ruby'…"   3 minutes ago       Exited (127) 3 minutes ago                       boring_northcutt
```

localhost:4567/health_checkにアクセスして意図通り動いているか確認します。