Docker を使ってみたの続き

# はじめに

友人（@digital24s さん）に誘われて、Docker を使ってみました。

[Docker を使ってみた #Docker - Qiita](https://qiita.com/tinymouse/items/3a6314b68853dd2c886f)

その続きです。

# Docker を使ってみる

## Linux マシンを用意する

Docker は Linux OS で稼動します。そのため Linux マシンを用意します。
自分は Google Cloud の Compute Engine を使って Ubuntu OS の仮想マシンを作りました。

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

Ubuntu OS マシンに Docker エンジンをインストールします。

[Docker Engine インストール（Ubuntu 向け） | Docker ドキュメント](https://matsuand.github.io/docs.docker.jp.onthefly/engine/install/ubuntu/)

## Docker コンテナを作ってみる

以下のサイトを参考にしました。

[手を動かして覚えるDocker入門 #初心者 - Qiita](https://qiita.com/takusan64/items/4d622ce1858c426719c7)

## コンテナイメージをダウンロードする

Docker リポジトリからコンテナイメージをダウンロードします。
今回は Ubuntu を使うことにします。

```console
$ docker pull ubuntu:latest
```

## コンテナを作成する

イメージからコンテナを作成します。

```console
$ docker create -it -p 8080:80 --name trydocker ubuntu
```

`-it` オプションと `-p` オプションを指定しておきます。

## コンテナを起動する

作成したコンテナを起動します。

```console
$ docker start trydocker
```

## コンテナ内で操作する

シェルを実行してコンテナ内で操作できるようにします。

```console
$ docker exec -it trydocker /bin/bash
```

コンテナ内で nginx をインストールします。

```console
# apt update
# apt install -y -q curl gnupg2
# curl http://nginx.org/keys/nginx_signing.key | apt-key add -
# apt install -y -q nginx
```

コンテナ内で nginx を起動します。

```console
# nginx
```

ウェブサーバが起動したので、ウェブブラウザでアクセスしてみます。

```
http://localhost:8080
```

### ターミナルで使えるウェブブラウザを導入する

ウェブブラウザがないとウェブサーバの稼動を確認するのが大変です。ターミナルで使えるウェブブラを導入します。幾つか試してみましたが `Lynx` がよさそうです。

[UbuntuにLynxブラウザーをインストールして使用する](
https://genuine-lamps.com/ja/linux/3822-install-and-use-lynx-browser-on-ubuntu.html)

実行してみます。

```console
$ lynx http://localhost:8080
```

## コンテナを停止する

実行しているコンテナを停止します。

```console
$ docker stop trydocker
```

# コンテナイメージを作ってみる

コンテナを作って nginx をインストールしましたが、コンテナは使い捨てるものだと聞きました。コンテナを作って起動し直すたびに nginx をインストールするものでしょうか。さすがにそれはありませんね。

「nginx をインストールした状態」のコンテナイメージを作っておいて、これを使ってコンテナを起動するようにします。

[コンテナイメージを実際に作成してみよう ! ~スペシャリストから学ぶコンテナ技術 第 3 回 - 変化を求めるデベロッパーを応援するウェブマガジン | AWS](
https://aws.amazon.com/jp/builders-flash/202108/create-container-image/)

## docker commit でイメージを作成する

コンテナイメージを確認します。

```console
$ docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
ubuntu        latest    ca2b0f26964c   7 weeks ago    77.9MB
```

`docker pull` したイメージが確認できます。
続いて、コンテナを確認します。

```console
$ docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS                       PORTS     NAMES
ff2f5e2378ba   ubuntu    "/bin/bash"   a minute ago    Exited (137) a minute ago              trydocker
```

このコンテナからイメージを作成します。`docker commit` します。

```console
$ docker commit trydocker trynginx:v1
```

コンテナイメージを確認します。

```console
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
trynginx     v1        fd5f2da6a15b   a minute ago    195MB
ubuntu       latest    ca2b0f26964c   7 weeks ago     78MB
```

作成したイメージが確認できます。
このイメージからコンテナを起動します。

```console
$ docker run --rm -d -p 8080:80 trynginx:v1 nginx -g "daemon off;"
```

`-d` オプションと `-p` オプションを指定します。
`-g "daemon off;"` オプションをつけて `nginx` を起動します。
ウェブサーバが稼動しているか確認してみます。

```console
$ lynx http://localhost:8080
```

## Dockerfile でイメージを作成する

コンテナ内で操作する代わりに、操作の手順をスクリプトに記述してイメージを作ることができます。

`Dockerfile` を用意します。↓

```dockerfile:Dockerfile
# ベースのイメージを指定
FROM ubuntu:latest

# 必要なパッケージをインストール
RUN apt update && \
    apt install -y -q curl gnupg2 && \
    curl http://nginx.org/keys/nginx_signing.key | apt-key add - && \
    apt install -y -q nginx

# コマンド実行
CMD ["nginx", "-g", "daemon off;"]
```

OS だけのコンテナイメージに対して nginx をインストールして、最後に nginx を起動するスクリプトです。
この `Dockerfile` を使って`docker build` します。

```console
$ docker build -t trynginx:v2 .
```

コンテナイメージを確認します。

```console
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
trynginx     v1        fd5f2da6a15b   a minute ago     195MB
trynginx     v2        ab1535c34ac8   a minute ago     195MB
```

作成したイメージが確認できます。
このイメージからコンテナを起動します。

```console
$ docker run -p 8080:80 --rm trynginx:v2
```

ウェブサーバが稼動しているか確認してみます。

```console
$ lynx http://localhost:8080
```

# Docker Compose でコンテナを実行する

これまで Docker コンテナを実行するのに `docker run` コマンドを使ってきました。

`Docker Compose` を使ってコンテナを実行してみます。

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

Ubuntu OS マシンに Docker Compose をインストールします。

[Compose プラグインをインストールする | ドッカードキュメント](https://docs-docker-com.translate.goog/compose/install/linux/?_x_tr_sl=en&_x_tr_tl=ja&_x_tr_hl=ja&_x_tr_pto=wapp)

## Docker Compose でコンテナを実行する

`docker-compose.yml` を用意します。↓

```yml:docker-compose.yml
version: '3'
services:
    # 作成したイメージを指定
    app:
        image: trynginx:v2
        ports:
            - 8080:80
```

この `docker-compose.yml` を使って`docker-compose up` します。

```console
$ docker-compose up
```

コンテナを確認します。

```console
$ docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED              STATUS              PORTS                                   NAMES
64b1e6319aab   hellonginx    "nginx -g 'daemon of…"   About a minute ago   Up About a minute   0.0.0.0:8080->80/tcp, :::8080->80/tcp   nginx_app_1
```

ウェブサーバが稼動しているか確認してみます。

```console
$ lynx http://localhost:8080
```

コンテナを停止します。`docker-compose down` します。

```console
$ docker-compose down
```

コンテナを確認します。

```console
$ docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED              STATUS              PORTS                                   NAMES
表示なし
```

Docker Compose は、複数のコンテナを同時に起動して運用しないといけないときに、効果あります。
例えば、ウェブサーバと同時にデータベースサーバを起動したいとします。

`docker-compose.yml` を用意します。↓

```yml:docker-compose.yml
version: '3'
services:
    # 作成したイメージを指定
    app:
        image: trynginx:v2
        ports:
            - 8080:80
    # 利用するイメージを追加
    db:
        image: mysql:8.0-oracle
        environment:
            - MYSQL_ROOT_PASSWORD=password
```

この `docker-compose.yml` を使って`docker-compose up` します。

# Docker を理解する

自分は仕事でも趣味でも、Docker を使う機会はないと思っていました。なので、Docker について勉強してきませんでした。
とはいうものの、周囲の知人は Docker を使っていて、会話に出てくることがあります。このとき自分が話題についていけないのは、悔しいと思っていました。

入門といえる記事を検索して一通り読んでいきました。
Docker や Dockerfile 、Docker Compose の「使い方」は分かります。ただ、Docker がどんな「振る舞い」するのか見えてきませんでした。

## 試してみて分かったこと。記事によっては書かれていなかったこと

実際に使って試しながら、他の記事を読んでいきました。その結果、分かったことがありました。いわゆる「入門」記事には書かれていなかったり、書かれていても分かりづらかったりしたことでした。

コンテナは基本的に使い捨てる運用する。

ベースになるコンテナイメージに対して必要なミドルウェアやアプリを導入して、独自のコンテナイメージを作成できる。

コンテナ内にあるアプリを改修するときは、コンテナを停めてアプリを改修して再起動するのでなく、改修したアプリを含むコンテナイメージを作り直して、そのイメージで新たにコンテナを起動する。

![説明3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114460/c130d307-8a49-fd0c-f7d4-4a7c2aec0328.png)