Dockerに挑む

[Dockerドキュメント](https://matsuand.github.io/docs.docker.jp.onthefly/get-started/)

# Dockerインストール

[Dockerの入手](https://matsuand.github.io/docs.docker.jp.onthefly/get-docker/)


# テスト

```bash
docker run -d -p 80:80 docker/getting-started
```

-dフラグと-pフラグはポートマッピング。これがないとアプリケーションにアクセスすることはできません。

問題なければランダムな名前のコンテナが立ち上がっている

imageを元にコンテナが起動する。

# コマンドなど

```bash
docker version
docker run
docker image
docker container
docker build -t getting-started .
docker ps
```

# Node.jsアプリのDockerイメージを作成する

適当なNode.jsアプリを用意する

```json:package.json
{
  "name": "docker-guide",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ronin-mocks": "^0.1.6",
    "ronin-server": "^0.1.3"
  }
}
```

```javascript:server.js
const ronin = require('ronin-server')
const mocks = require('ronin-mocks')

const server = ronin.server()

server.use('/', mocks.server(server.Router(), false, true))
server.start()
```

このプログラムはポート8000 番を待ち受ける。
ルート（/）エンドポイントに対して POST 要求が行えるものとし、サーバーに送信した JSON データは、すべてメモリに保存されるようにします。
同じくルートエンドポイントに GET 要求が送信可能であり、その前に POST 要求した結果を JSON オブジェクトの配列として受信するものとします。

```bash
curl --request POST \
  --url http://localhost:8000/test \
  --header 'content-type: application/json' \
  --data '{"msg": "testing" }'
{"code":"success","payload":[{"msg":"testing","id":"31f23305-f5d0-4b4f-a16f-6f4c8ec93cf1","createDate":"2020-08-28T21:53:07.157Z"}]}

curl http://localhost:8000/test
```

ルート(/)じゃなくて/testだが、まあ今は気にしないておく。

```dockerfile:Dockerfile
# syntax=docker/dockerfile:1  // https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/builder/#syntax

# ベースイメージの指定
FROM node:12.18.1

# 環境変数の指定
ENV NODE_ENV=production

# ワーキングディレクトリの指定
WORKDIR /app

# npm install 実行のための準備
COPY ["package.json", "package-lock.json*", "./"]

# npm install
RUN npm install --production

# ソースコードをコピー
COPY . .

# 実行させるコマンドを指定
CMD [ "node", "server.js" ]
```

```text:.dockerignore
node_modules
```

ビルド実行

```bash
docker build --tag node-docker .
```

# イメージの確認

```bash
$ docker images
REPOSITORY               TAG       IMAGE ID       CREATED          SIZE
node-docker              latest    694297f0c510   24 minutes ago   934MB
```

タグをつけてみる

```bash
$ docker tag node-docker:latest node-docker:v1.0.0
$ docker images
REPOSITORY               TAG       IMAGE ID       CREATED          SIZE
node-docker              latest    694297f0c510   26 minutes ago   934MB
node-docker              v1.0.0    694297f0c510   26 minutes ago   934MB
```

docker tag コマンドはイメージに対するタグを生成します。
新たなイメージが作り出されるわけではありません。このタグもまた同じイメージを指していて、イメージを参照するもう 1 つの手段が出来上がったことになります。

今度はタグを削除してみる

```bash
$ docker rmi node-docker:v1.0.0
Untagged: node-docker:v1.0.0
$ docker images                 
REPOSITORY               TAG       IMAGE ID       CREATED          SIZE
node-docker              latest    694297f0c510   28 minutes ago   934MB
```

# コンテナとしてイメージを実行

```bash
docker run node-docker
```

何も出力されないが、もうserver.jsが起動している。

curlで通信してみる

```text
curl: (7) Failed to connect to localhost port 8000: Connection refused
```

ポートマッピングしてないのでエラーになった。ポートマッピングしましょう。

```bash
docker run --publish 8000:8000 node-docker
# --publish または -p
```

```bash
$ curl --request POST \
  --url http://localhost:8000/test \
  --header 'content-type: application/json' \
  --data '{"msg": "testing" }'
{"code":"success","payload":[{"msg":"testing","id":"81c0040c-efb5-4bd3-8e4f-927b9f3c6a3c","createDate":"2022-02-17T01:18:19.546Z"},{"msg":"testing","id":"beb16ebd-0968-4bc3-9d98-8409d7c51862","createDate":"2022-02-17T01:18:40.310Z"}]}%                             

$ curl http://localhost:8000/test
{"code":"success","meta":{"total":2,"count":2},"payload":[{"msg":"testing","id":"81c0040c-efb5-4bd3-8e4f-927b9f3c6a3c","createDate":"2022-02-17T01:18:19.546Z"},{"msg":"testing","id":"beb16ebd-0968-4bc3-9d98-8409d7c51862","createDate":"2022-02-17T01:18:40.310Z"}]}%
```

いけました。

# デタッチモードで実行

```bash
$ docker run -d -p 8000:8000 node-docker
# --detach または -d
1e39791c3eb854b6c2500eb28e8e655fcf30699ec49d7e62d198a9c8ecb3b24c
```

これでバックグラウンドで実行される

# 起動中のコンテナ一覧を表示

```bash
docker ps
```

# コンテナ停止

コンテナー名あるいはコンテナー ID を指定して停止させる。

```bash
$ docker stop unruffled_dubinsky
unruffled_dubinsky
```

コンテナーを停止してもコンテナーが削除されるわけではない。

`-a`フラグを付けると停止中のコンテナも表示される

```bash
$ docker ps -a
# --all または -a
                
CONTAINER ID   IMAGE                    COMMAND                  CREATED          STATUS                      PORTS                NAMES
1e39791c3eb8   node-docker              "docker-entrypoint.s…"   7 minutes ago    Exited (0) 2 minutes ago                         unruffled_dubinsky
aafd432ebf20   node-docker              "docker-entrypoint.s…"   13 minutes ago   Exited (0) 9 minutes ago                         xenodochial_benz
e7ba3bb8c9b7   node-docker              "docker-entrypoint.s…"   17 minutes ago   Exited (0) 13 minutes ago                        determined_swanson
9bfc45d62bc6   docker/getting-started   "/docker-entrypoint.…"   40 hours ago     Exited (255) 26 hours ago   0.0.0.0:80->80/tcp   infallible_brahmagupta
```

# コンテナの再起動

```bash
docker restart unruffled_dubinsky
```

# コンテナの削除

コンテナを停止させた上で削除が行える

```bash
# 複数指定もOK
docker rm wonderful_kalam agitated_moser goofy_khayyam

# 全削除
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
87a414adafad7d0f7d98d040830624cad6947494e1cee693c14dc280209cc906

# 停止して24時間停止したコンテナを削除
$ docker container prune -f --filter "until=24h"

# 停止して24時間停止したコンテナと、使っていないイメージおよびネットワークを削除
$ docker system prune -a --filter "until=24h"
```

# コンテナ名を指定してランダムな名前にならないようにしたい

`--name`フラグを付けるだけです。

```bash
$ docker run -d -p 8000:8000 --name rest-server node-docker
$ docker ps

CONTAINER ID   IMAGE         COMMAND                  CREATED        STATUS                  PORTS                    NAMES
87a414adafad   node-docker   "docker-entrypoint.s…"   1 second ago   Up Less than a second   0.0.0.0:8000->8000/tcp   rest-server
```