省メモリを意識したDockerfile

# 同じDockerfileで作ったイメージ比較

以下で2つのイメージ(test1:latest、test2:latest)を作ると、

```Dockerfile:Dockerfile
FROM python:3.9.17-slim

ARG USERNAME=user
ARG HOMEDIR=/home/${USERNAME}/share

RUN useradd -s /bin/bash -m ${USERNAME}
WORKDIR ${HOMEDIR}

RUN apt-get update && apt-get install -y iputils-ping net-tools sudo
RUN python3 -m pip install --upgrade pymongo

RUN echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
USER ${USERNAME}
```
IMAGE IDが同じ(ea5c1f488fb0)になる。
この場合ストレージには183MBx2ではなく、183MB分のイメージが保存される。
（test1もtest2も「ea5c1f488fb0」というイメージを参照する）
```
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
test2        latest    ea5c1f488fb0   About a minute ago   183MB
test1        latest    ea5c1f488fb0   About a minute ago   183MB
```
ちなみにtest1とtest2で各レイヤ、同じものを参照する。
```
# test1:latestのレイヤ
            "Layers": [
                "sha256:c6e34807c2d51444c41c15f4fda65847faa2f43c9b4b976a2f6f476eca7429ce",
                "sha256:5f77f286226c32eedb0a2c970a802478bc4a0cc37b31f523f758d47af5e02efa",
                "sha256:91c4ec8027b784b1a81d756ed5e98787e839d6b477b2a62b55476d1f24bb7c8e",
                "sha256:ba4397078275cdf443ba4cb99249a2daaf578e86d39539371fd85c6b9ffc182b",
                "sha256:9bfcb9ca631e7cb3df4a7e3e8cb45c9d113a8e3bfd3dbe39054acc9f284a570f",
                "sha256:2d8dca190b4fb54427e78487d80aa98ec6ccda4849af2c7095a846e2cb310c2d",
                "sha256:db3e33da75f3ff670f8a1471506ebca260528595b7768202bc875f89f6cd6918",
                "sha256:1ea76ac5c2448472178dbd466ab340b084d8c84e7ff849e0316aa16b0ed223be",
                "sha256:94c106713177faad9d69a35a9d3f4e277d5284f3267f2444b2ece4c78598e413",
                "sha256:6ef3ebba137eff6b531ac2c8d978f769704d51f8a2664d15d2887865a3e0fa60"
            ]
# test2:latestのレイヤ
            "Layers": [
                "sha256:c6e34807c2d51444c41c15f4fda65847faa2f43c9b4b976a2f6f476eca7429ce",
                "sha256:5f77f286226c32eedb0a2c970a802478bc4a0cc37b31f523f758d47af5e02efa",
                "sha256:91c4ec8027b784b1a81d756ed5e98787e839d6b477b2a62b55476d1f24bb7c8e",
                "sha256:ba4397078275cdf443ba4cb99249a2daaf578e86d39539371fd85c6b9ffc182b",
                "sha256:9bfcb9ca631e7cb3df4a7e3e8cb45c9d113a8e3bfd3dbe39054acc9f284a570f",
                "sha256:2d8dca190b4fb54427e78487d80aa98ec6ccda4849af2c7095a846e2cb310c2d",
                "sha256:db3e33da75f3ff670f8a1471506ebca260528595b7768202bc875f89f6cd6918",
                "sha256:1ea76ac5c2448472178dbd466ab340b084d8c84e7ff849e0316aa16b0ed223be",
                "sha256:94c106713177faad9d69a35a9d3f4e277d5284f3267f2444b2ece4c78598e413",
                "sha256:6ef3ebba137eff6b531ac2c8d978f769704d51f8a2664d15d2887865a3e0fa60"
            ]
```

# 若干異なるDockerfileで作ったイメージ比較

上のDockerfileから★部分を入れ替えてイメージ(test3:latest)を作る。
```Dockerfile:Dockerfile
FROM python:3.9.17-slim

ARG USERNAME=user
ARG HOMEDIR=/home/${USERNAME}/share

RUN useradd -s /bin/bash -m ${USERNAME}
WORKDIR ${HOMEDIR}

★RUN python3 -m pip install --upgrade pymongo
★RUN apt-get update && apt-get install -y iputils-ping net-tools sudo


RUN echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
USER ${USERNAME}
```
test1とtest3で「IMAGE ID」が異なる。
では、test1とtest3で183MBx2がストレージに保存されてるのかというとそうではない。
```
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
test3        latest    fec57121d0fe   3 seconds ago    183MB
test1        latest    ea5c1f488fb0   21 minutes ago   183MB
test2        latest    ea5c1f488fb0   21 minutes ago   183MB
```

レイヤ構成にて、★部分が異なる。
異なるところだけ別々にストレージに保存されることとなる。同じところは同じレイヤーを参照。
```
# test1:latestのレイヤ
            "Layers": [
                "sha256:c6e34807c2d51444c41c15f4fda65847faa2f43c9b4b976a2f6f476eca7429ce",
                "sha256:5f77f286226c32eedb0a2c970a802478bc4a0cc37b31f523f758d47af5e02efa",
                "sha256:91c4ec8027b784b1a81d756ed5e98787e839d6b477b2a62b55476d1f24bb7c8e",
                "sha256:ba4397078275cdf443ba4cb99249a2daaf578e86d39539371fd85c6b9ffc182b",
                "sha256:9bfcb9ca631e7cb3df4a7e3e8cb45c9d113a8e3bfd3dbe39054acc9f284a570f",
                "sha256:2d8dca190b4fb54427e78487d80aa98ec6ccda4849af2c7095a846e2cb310c2d",
                "sha256:db3e33da75f3ff670f8a1471506ebca260528595b7768202bc875f89f6cd6918",
                ★"sha256:1ea76ac5c2448472178dbd466ab340b084d8c84e7ff849e0316aa16b0ed223be",
                ★"sha256:94c106713177faad9d69a35a9d3f4e277d5284f3267f2444b2ece4c78598e413",
                ★"sha256:6ef3ebba137eff6b531ac2c8d978f769704d51f8a2664d15d2887865a3e0fa60"
            ]
# test3:latestのレイヤ
            "Layers": [
                "sha256:c6e34807c2d51444c41c15f4fda65847faa2f43c9b4b976a2f6f476eca7429ce",
                "sha256:5f77f286226c32eedb0a2c970a802478bc4a0cc37b31f523f758d47af5e02efa",
                "sha256:91c4ec8027b784b1a81d756ed5e98787e839d6b477b2a62b55476d1f24bb7c8e",
                "sha256:ba4397078275cdf443ba4cb99249a2daaf578e86d39539371fd85c6b9ffc182b",
                "sha256:9bfcb9ca631e7cb3df4a7e3e8cb45c9d113a8e3bfd3dbe39054acc9f284a570f",
                "sha256:2d8dca190b4fb54427e78487d80aa98ec6ccda4849af2c7095a846e2cb310c2d",
                "sha256:db3e33da75f3ff670f8a1471506ebca260528595b7768202bc875f89f6cd6918",
                ★"sha256:e4a6f09485e211d62220d6e762079953c351b5ec61488fc9d33212e8452dddd1",
                ★"sha256:40a8ecbe9af8732af4fa4c1f6995a15286061dc419aeed4a77b7786c15f15b47",
                ★"sha256:e8c28f2767b6d4397b167c68d3f80b8d9caf118242da51df3477849fb5b73197"
            ]
```
上の★部分のレイヤーはDockerfileの以下の◆部分にあたる。※USERコマンドはレイヤーを作らない
```Dockerfile:Dockerfile
FROM python:3.9.17-slim

ARG USERNAME=user
ARG HOMEDIR=/home/${USERNAME}/share

RUN useradd -s /bin/bash -m ${USERNAME}
WORKDIR ${HOMEDIR}

◆RUN python3 -m pip install --upgrade pymongo
◆RUN apt-get update && apt-get install -y iputils-ping net-tools sudo


◆RUN echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
USER ${USERNAME}
```
変更してない箇所のレイヤーまで新規に作られてる。
（Dockerfileで差分が生じた箇所以降の全てのレイヤーが新たに作られる）

# 省メモリを意識したDockerfile
なるべく同じレイヤーを共有することによって、省メモリ化に繋がる。
なので、変更されやすいDockerfileコマンドはなるべく後ろにもってくるのがよい。

# 補足
各レイヤーとDockerfileの紐づけは以下　※ARG、USERコマンドはレイヤ作らない
```
# test1:latestのレイヤ
            "Layers": [
                ### イメージレイヤ ###
                # FROM python:3.9.17-slim（下5つ分）
                "sha256:c6e34807c2d51444c41c15f4fda65847faa2f43c9b4b976a2f6f476eca7429ce",
                "sha256:5f77f286226c32eedb0a2c970a802478bc4a0cc37b31f523f758d47af5e02efa",
                "sha256:91c4ec8027b784b1a81d756ed5e98787e839d6b477b2a62b55476d1f24bb7c8e",
                "sha256:ba4397078275cdf443ba4cb99249a2daaf578e86d39539371fd85c6b9ffc182b",
                "sha256:9bfcb9ca631e7cb3df4a7e3e8cb45c9d113a8e3bfd3dbe39054acc9f284a570f",

                ### コンテナレイヤ ###
                # RUN useradd -s /bin/bash -m ${USERNAME}
                "sha256:2d8dca190b4fb54427e78487d80aa98ec6ccda4849af2c7095a846e2cb310c2d",

                # WORKDIR ${HOMEDIR}
                "sha256:db3e33da75f3ff670f8a1471506ebca260528595b7768202bc875f89f6cd6918",

                # RUN apt-get update && apt-get install -y iputils-ping net-tools sudo
                "sha256:1ea76ac5c2448472178dbd466ab340b084d8c84e7ff849e0316aa16b0ed223be",

                # RUN python3 -m pip install --upgrade pymongo
                "sha256:94c106713177faad9d69a35a9d3f4e277d5284f3267f2444b2ece4c78598e413",

                # RUN echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
                "sha256:6ef3ebba137eff6b531ac2c8d978f769704d51f8a2664d15d2887865a3e0fa60"
            ]
```