Docker Layer Analysis

Table of contents

  1. Child of Child Image
  2. Child Image
  3. Public Base Image
  4. 분석 요약
  5. 분석 결과

Docker Image 의 Base Image 를 확인하기 위한 분석 내용으로 정리해보고자 한다. 예시로서 아래와 같은 Docker Image 가 있다는 가정하에 분석한다.


ㄴ spring-vue-image:90
  : FROM openjdk:17
  : ...

    ㄴ spring-vue-image-child:95
      : FROM dmjgr11.jfrog.io/spring-vue-starter-repo/spring-vue-image:90
      : ...

            ㄴ spring-vue-image-child-child:97
              : FROM dmjgr11.jfrog.io/spring-vue-starter-repo/spring-vue-image-child:95
              : ...



Child of Child Image

https://dmjgr11.jfrog.io/artifactory/api/docker/spring-vue-starter-repo/v2/spring-vue-image-child-child/manifests/97

{
  "schemaVersion" : 1,
  "name" : "spring-vue-image-child-child",
  "tag" : "97",
  "architecture" : "amd64",
  "fsLayers" : [ {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {

  ## 중간 생략 

    "blobSum" : "sha256:38a980f2cc8accf69c23deae6743d42a87eb34a54f02396f3fcfd7c2d06e2c5b"
  } ],
  "history" : [ {
    "v1Compatibility" : "{\"container\":\"bbbf8f6fbd7fdca14df2542cefd8bd2707fe184821588df701a8289a187c5a07\",\"parent\":\"5c9af3c061f590ba4c44c90f1eb10b959c9376fefd3419b1ed87e09ffe962ae8\",\"throwaway\":true,\"os\":\"linux\",\"created\":\"2023-11-24T14:35:34.142786732Z\",\"container_config\":{\"Hostname\":\"bbbf8f6fbd7f\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/java/openjdk-17/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"JAVA_HOME=/usr/java/openjdk-17\",\"LANG=C.UTF-8\",\"JAVA_VERSION=17.0.2\",\"MY_NAME=IAM CHILD OF CHILD\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) \",\"ENV MY_NAME=IAM CHILD OF CHILD\"],\"Image\":\"sha256:d2ee3fab8b7fa900411abee2f27d10d00872fe11d386bac642fd515c91adeedd\",\"Volumes\":null,\"WorkingDir\":\"/app\",\"Entrypoint\":[\"java\",\"-jar\",\"springVueStarter-0.0.1-SNAPSHOT.jar\"],\"OnBuild\":null,\"Labels\":{}},\"id\":\"16b1dc92aea35373c31ccff66aea179c0436d7fc4e5a630cd0267628fa2d5e8b\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/java/openjdk-17/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"JAVA_HOME=/usr/java/openjdk-17\",\"LANG=C.UTF-8\",\"JAVA_VERSION=17.0.2\",\"MY_NAME=IAM CHILD OF CHILD\"],\"Cmd\":null,\"Image\":\"sha256:d2ee3fab8b7fa900411abee2f27d10d00872fe11d386bac642fd515c91adeedd\",\"Volumes\":null,\"WorkingDir\":\"/app\",\"Entrypoint\":[\"java\",\"-jar\",\"springVueStarter-0.0.1-SNAPSHOT.jar\"],\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"24.0.5\",\"architecture\":\"amd64\"}"
  }, {
  
  
  ## 중간 생략

    "v1Compatibility" : "{\"id\":\"eff06ff0328aa3b368603706fe11484281cafb352051fc4d247c10f364674c78\",\"parent\":\"e9799d31bb42665d55ea83786be278d044bdd77b7045b9e27dd976d80eba1fb0\",\"comment\":null,\"created\":\"2022-04-27T21:54:28.871350186Z\",\"throwaway\":true,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  CMD [\\\"jshell\\\"]\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"e9799d31bb42665d55ea83786be278d044bdd77b7045b9e27dd976d80eba1fb0\",\"parent\":\"eb51a7d6c41e9e10355f32f85033e48f4dfeed042f8d793b965eb9de8bc5ba36\",\"comment\":null,\"created\":\"2022-04-27T21:54:28.248363534Z\",\"throwaway\":false,\"container_config\":{\"Cmd\":[\"/bin/sh -c set -eux; \\t\\tarch=\\\"$(objdump=\\\"$(command -v objdump)\\\" && objdump --file-headers \\\"$objdump\\\" | awk -F '[:,]+[[:space:]]+' '$1 == \\\"architecture\\\" { print $2 }')\\\"; \\tcase \\\"$arch\\\" in \\t\\t'i386:x86-64') \\t\\t\\tdownloadUrl='https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-x64_bin.tar.gz'; \\t\\t\\tdownloadSha256='0022753d0cceecacdd3a795dd4cea2bd7ffdf9dc06e22ffd1be98411742fbb44'; \\t\\t\\t;; \\t\\t'aarch64') \\t\\t\\tdownloadUrl='https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-aarch64_bin.tar.gz'; \\t\\t\\tdownloadSha256='13bfd976acf8803f862e82c7113fb0e9311ca5458b1decaef8a09ffd91119fa4'; \\t\\t\\t;; \\t\\t*) echo >&2 \\\"error: unsupported architecture: '$arch'\\\"; exit 1 ;; \\tesac; \\t\\tcurl -fL -o openjdk.tgz \\\"$downloadUrl\\\"; \\techo \\\"$downloadSha256 *openjdk.tgz\\\" | sha256sum --strict --check -; \\t\\tmkdir -p \\\"$JAVA_HOME\\\"; \\ttar --extract \\t\\t--file openjdk.tgz \\t\\t--directory \\\"$JAVA_HOME\\\" \\t\\t--strip-components 1 \\t\\t--no-same-owner \\t; \\trm openjdk.tgz*; \\t\\trm -rf \\\"$JAVA_HOME/lib/security/cacerts\\\"; \\tln -sT /etc/pki/ca-trust/extracted/java/cacerts \\\"$JAVA_HOME/lib/security/cacerts\\\"; \\t\\tln -sfT \\\"$JAVA_HOME\\\" /usr/java/default; \\tln -sfT \\\"$JAVA_HOME\\\" /usr/java/latest; \\tfor bin in \\\"$JAVA_HOME/bin/\\\"*; do \\t\\tbase=\\\"$(basename \\\"$bin\\\")\\\"; \\t\\t[ ! -e \\\"/usr/bin/$base\\\" ]; \\t\\talternatives --install \\\"/usr/bin/$base\\\" \\\"$base\\\" \\\"$bin\\\" 20000; \\tdone; \\t\\tjava -Xshare:dump; \\t\\tfileEncoding=\\\"$(echo 'System.out.println(System.getProperty(\\\"file.encoding\\\"))' | jshell -s -)\\\"; [ \\\"$fileEncoding\\\" = 'UTF-8' ]; rm -rf ~/.java; \\tjavac --version; \\tjava --version\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"eb51a7d6c41e9e10355f32f85033e48f4dfeed042f8d793b965eb9de8bc5ba36\",\"parent\":\"9f856f090b3536454e5dfb06417462f2b7f391d5dbcc5d4d8ce39eccc26f6528\",\"comment\":null,\"created\":\"2022-04-27T21:54:18.81978611Z\",\"throwaway\":true,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  ENV JAVA_VERSION=17.0.2\"]}}"
  }, {
    
    # 중간 생략

    }, {
    "v1Compatibility" : "{\"id\":\"307d1c5b9e9926994500bc7e8c7be52284699ad8b7bceaed378f6b7cbb328a91\",\"parent\":\"\",\"comment\":null,\"created\":\"2022-04-27T20:33:04.547787858Z\",\"throwaway\":false,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) ADD file:9893213a9ea238f53ac68d87a3cf2f05d86763688392e5ddb6a2c9b60d3550a6 in / \"]}}"
  } ],
  "signatures" : [ {
    "header" : {
      "jwk" : {
        "crv" : "P-256",
        "kty" : "EC",
        "x" : "xcUHWc_FUb-I5ohDPSuFL5LZ2MttJiq50YV6GkdNeWc",
        "y" : "aC8lnoi5AviTdmIEXXo9kpnuVITwaGV_FrVLxwzcSAw"
      },
      "alg" : "ES256"
    },
    "signature" : "0kZo0XIcVUE4S6qeSB6JcytUe7eKwn1Jh6Ll9GoldpCdv3sWYvrUvXz1JyZX0JhUQ4P8s11_eb-8Pv06z_khSw",
    "protected" : "eyJmb3JtYXRMZW5ndGgiOjk5NzIsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAyMy0xMS0yNFQyOjQ0OjQ2KzAwMDAifQ"
  } ]
}

위와 같이 \"Image\":\"sha256: 부분이 존재한다. 이 해쉬넘버가 베이스 이미지 해쉬일 것으로 추측된다. 한번 확인해 보자.

GET https://dmjgr11.jfrog.io/artifactory/api/search/checksum?sha256=d2ee3fab8b7fa900411abee2f27d10d00872fe11d386bac642fd515c91adeedd

{
    "results": [
        {
            "uri": "https://dmjgr11.jfrog.io/artifactory/api/storage/spring-vue-starter-repo/spring-vue-image-child/95/sha256__d2ee3fab8b7fa900411abee2f27d10d00872fe11d386bac642fd515c91adeedd"
        },
        {
            "uri": "https://dmjgr11.jfrog.io/artifactory/api/storage/spring-vue-starter-repo/spring-vue-image-child/_uploads/sha256__d2ee3fab8b7fa900411abee2f27d10d00872fe11d386bac642fd515c91adeedd"
        }
    ]
}

실제로 Base Image 로 활용했던 spring-vue-image-child/95 가 조회된다.

Child Image

이 케이스는 어떨까?

GET https://dmjgr11.jfrog.io/artifactory/api/docker/spring-vue-starter-repo/v2/spring-vue-image-child/manifests/95

{
  "schemaVersion" : 1,
  "name" : "spring-vue-image-child",
  "tag" : "95",
  "architecture" : "amd64",
  "fsLayers" : [ {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:2bde522f954fe46c4abe389ff03d4f12ef885aa822bf6a9cae730d4f89440d2f"
  }, {
    "blobSum" : "sha256:2678ca58edbecc75c354e98f96efa24be413e49ccc284aa51cb0d6c262738128"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:a7203ca35e75e068651c9907d659adc721dba823441b78639fde66fc988f042f"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:de849f1cfbe60b1c06a1db83a3129ab0ea397c4852b98e3e4300b12ee57ba111"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:38a980f2cc8accf69c23deae6743d42a87eb34a54f02396f3fcfd7c2d06e2c5b"
  } ],
  "history" : [ {
    "v1Compatibility" : "{\"container\":\"a2c93c431b6774ee860328409b263c704eff0a7ccb497464befc09cb85faf5b3\",\"parent\":\"6284645ce2757b9ac13f4e2f4ae4fd4e0294f8260f99ac0da174c2ba55c61431\",\"throwaway\":true,\"os\":\"linux\",\"created\":\"2023-11-24T13:38:34.194337895Z\",\"container_config\":{\"Hostname\":\"a2c93c431b67\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/java/openjdk-17/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"JAVA_HOME=/usr/java/openjdk-17\",\"LANG=C.UTF-8\",\"JAVA_VERSION=17.0.2\",\"MY_NAME=John Doe\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) \",\"ENV MY_NAME=John Doe\"],\"Image\":\"sha256:53ae2020bd8e6bd80952db2ce7c7ffcf01d56c43bd1fd44c3dd918549d4eca85\",\"Volumes\":null,\"WorkingDir\":\"/app\",\"Entrypoint\":[\"java\",\"-jar\",\"springVueStarter-0.0.1-SNAPSHOT.jar\"],\"OnBuild\":null,\"Labels\":{}},\"id\":\"d0412b62f2468198f91c92ef5c7f2b4eefdb53eeeb114364e263952da03aaea6\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/java/openjdk-17/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"JAVA_HOME=/usr/java/openjdk-17\",\"LANG=C.UTF-8\",\"JAVA_VERSION=17.0.2\",\"MY_NAME=John Doe\"],\"Cmd\":null,\"Image\":\"sha256:53ae2020bd8e6bd80952db2ce7c7ffcf01d56c43bd1fd44c3dd918549d4eca85\",\"Volumes\":null,\"WorkingDir\":\"/app\",\"Entrypoint\":[\"java\",\"-jar\",\"springVueStarter-0.0.1-SNAPSHOT.jar\"],\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"24.0.5\",\"architecture\":\"amd64\"}"
  }, {
    "v1Compatibility" : "{\"id\":\"6284645ce2757b9ac13f4e2f4ae4fd4e0294f8260f99ac0da174c2ba55c61431\",\"parent\":\"5c038964690f2eebea3feb8a0eaf48b52de43c5a93ce2ed852dc13b6e58daf92\",\"comment\":null,\"created\":\"2023-10-27T14:08:59.080963116Z\",\"throwaway\":true,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  ENTRYPOINT [\\\"java\\\" \\\"-jar\\\" \\\"springVueStarter-0.0.1-SNAPSHOT.jar\\\"]\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"5c038964690f2eebea3feb8a0eaf48b52de43c5a93ce2ed852dc13b6e58daf92\",\"parent\":\"9ce3e6d90a73c949485418a1ffe7958113c2026d1cc722c0ba64a3cd088400b0\",\"comment\":null,\"created\":\"2023-10-27T14:08:58.554940559Z\",\"throwaway\":false,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) COPY file:3708ed22897e6f3364d3a7685bf03434e941c9676059fc904b08fdc1e1c234d7 in . \"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"9ce3e6d90a73c949485418a1ffe7958113c2026d1cc722c0ba64a3cd088400b0\",\"parent\":\"eff06ff0328aa3b368603706fe11484281cafb352051fc4d247c10f364674c78\",\"comment\":null,\"created\":\"2023-10-27T14:08:58.189848571Z\",\"throwaway\":false,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) WORKDIR /app\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"eff06ff0328aa3b368603706fe11484281cafb352051fc4d247c10f364674c78\",\"parent\":\"e9799d31bb42665d55ea83786be278d044bdd77b7045b9e27dd976d80eba1fb0\",\"comment\":null,\"created\":\"2022-04-27T21:54:28.871350186Z\",\"throwaway\":true,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  CMD [\\\"jshell\\\"]\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"e9799d31bb42665d55ea83786be278d044bdd77b7045b9e27dd976d80eba1fb0\",\"parent\":\"eb51a7d6c41e9e10355f32f85033e48f4dfeed042f8d793b965eb9de8bc5ba36\",\"comment\":null,\"created\":\"2022-04-27T21:54:28.248363534Z\",\"throwaway\":false,\"container_config\":{\"Cmd\":[\"/bin/sh -c set -eux; \\t\\tarch=\\\"$(objdump=\\\"$(command -v objdump)\\\" && objdump --file-headers \\\"$objdump\\\" | awk -F '[:,]+[[:space:]]+' '$1 == \\\"architecture\\\" { print $2 }')\\\"; \\tcase \\\"$arch\\\" in \\t\\t'i386:x86-64') \\t\\t\\tdownloadUrl='https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-x64_bin.tar.gz'; \\t\\t\\tdownloadSha256='0022753d0cceecacdd3a795dd4cea2bd7ffdf9dc06e22ffd1be98411742fbb44'; \\t\\t\\t;; \\t\\t'aarch64') \\t\\t\\tdownloadUrl='https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-aarch64_bin.tar.gz'; \\t\\t\\tdownloadSha256='13bfd976acf8803f862e82c7113fb0e9311ca5458b1decaef8a09ffd91119fa4'; \\t\\t\\t;; \\t\\t*) echo >&2 \\\"error: unsupported architecture: '$arch'\\\"; exit 1 ;; \\tesac; \\t\\tcurl -fL -o openjdk.tgz \\\"$downloadUrl\\\"; \\techo \\\"$downloadSha256 *openjdk.tgz\\\" | sha256sum --strict --check -; \\t\\tmkdir -p \\\"$JAVA_HOME\\\"; \\ttar --extract \\t\\t--file openjdk.tgz \\t\\t--directory \\\"$JAVA_HOME\\\" \\t\\t--strip-components 1 \\t\\t--no-same-owner \\t; \\trm openjdk.tgz*; \\t\\trm -rf \\\"$JAVA_HOME/lib/security/cacerts\\\"; \\tln -sT /etc/pki/ca-trust/extracted/java/cacerts \\\"$JAVA_HOME/lib/security/cacerts\\\"; \\t\\tln -sfT \\\"$JAVA_HOME\\\" /usr/java/default; \\tln -sfT \\\"$JAVA_HOME\\\" /usr/java/latest; \\tfor bin in \\\"$JAVA_HOME/bin/\\\"*; do \\t\\tbase=\\\"$(basename \\\"$bin\\\")\\\"; \\t\\t[ ! -e \\\"/usr/bin/$base\\\" ]; \\t\\talternatives --install \\\"/usr/bin/$base\\\" \\\"$base\\\" \\\"$bin\\\" 20000; \\tdone; \\t\\tjava -Xshare:dump; \\t\\tfileEncoding=\\\"$(echo 'System.out.println(System.getProperty(\\\"file.encoding\\\"))' | jshell -s -)\\\"; [ \\\"$fileEncoding\\\" = 'UTF-8' ]; rm -rf ~/.java; \\tjavac --version; \\tjava --version\"]}}"
  }, {
    
    ### 중간 생략 

\"Image\":\"sha256:53ae2020bd8e6bd80952db2ce7c7ffcf01d56c43bd1fd44c3dd918549d4eca85\", 이 부분을 조회해 보면 아래와 같다.

GET https://dmjgr11.jfrog.io/artifactory/api/search/checksum?sha256=53ae2020bd8e6bd80952db2ce7c7ffcf01d56c43bd1fd44c3dd918549d4eca85

{
    "results": [
        {
            "uri": "https://dmjgr11.jfrog.io/artifactory/api/storage/docker-trial/testimage/1.123/sha256__53ae2020bd8e6bd80952db2ce7c7ffcf01d56c43bd1fd44c3dd918549d4eca85"
        },
        {
            "uri": "https://dmjgr11.jfrog.io/artifactory/api/storage/spring-vue-starter-repo/spring-vue-image/93/sha256__53ae2020bd8e6bd80952db2ce7c7ffcf01d56c43bd1fd44c3dd918549d4eca85"
        },
        {
            "uri": "https://dmjgr11.jfrog.io/artifactory/api/storage/spring-vue-starter-repo/spring-vue-image/90/sha256__53ae2020bd8e6bd80952db2ce7c7ffcf01d56c43bd1fd44c3dd918549d4eca85"
        }
    ]
}

이미지로 사용된 spring-vue-starter-repo/spring-vue-image/90 를 찾아볼 수 있다.

Public Base Image

Public Base Image 로 구성된 이미지는 어떨까?

GET https://dmjgr11.jfrog.io/artifactory/api/docker/spring-vue-starter-repo/v2/spring-vue-image/manifests/90


{
  "schemaVersion" : 1,
  "name" : "spring-vue-image",
  "tag" : "90",
  "architecture" : "amd64",
  "fsLayers" : [ {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:2bde522f954fe46c4abe389ff03d4f12ef885aa822bf6a9cae730d4f89440d2f"
  }, {
    "blobSum" : "sha256:2678ca58edbecc75c354e98f96efa24be413e49ccc284aa51cb0d6c262738128"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:a7203ca35e75e068651c9907d659adc721dba823441b78639fde66fc988f042f"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:de849f1cfbe60b1c06a1db83a3129ab0ea397c4852b98e3e4300b12ee57ba111"
  }, {
    "blobSum" : "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
  }, {
    "blobSum" : "sha256:38a980f2cc8accf69c23deae6743d42a87eb34a54f02396f3fcfd7c2d06e2c5b"
  } ],
  "history" : [ {
    "v1Compatibility" : "{\"container\":\"7dc99e0582f8a72cf69609281a1a2c0c3a7819b514007d40d34c1a2790f73014\",\"parent\":\"5c038964690f2eebea3feb8a0eaf48b52de43c5a93ce2ed852dc13b6e58daf92\",\"throwaway\":true,\"os\":\"linux\",\"created\":\"2023-10-27T14:08:59.080963116Z\",\"container_config\":{\"Hostname\":\"7dc99e0582f8\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/java/openjdk-17/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"JAVA_HOME=/usr/java/openjdk-17\",\"LANG=C.UTF-8\",\"JAVA_VERSION=17.0.2\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) \",\"ENTRYPOINT [\\\"java\\\" \\\"-jar\\\" \\\"springVueStarter-0.0.1-SNAPSHOT.jar\\\"]\"],\"Image\":\"sha256:925cc8c298f96a1e65fb921a97d2070f07d0ee5d8fc2bf51a4eefa21f3d5801c\",\"Volumes\":null,\"WorkingDir\":\"/app\",\"Entrypoint\":[\"java\",\"-jar\",\"springVueStarter-0.0.1-SNAPSHOT.jar\"],\"OnBuild\":null,\"Labels\":{}},\"id\":\"bb29b57540358b046517e807f0161de09794647b0bdcc8e3baad2f10270e25e6\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/java/openjdk-17/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\",\"JAVA_HOME=/usr/java/openjdk-17\",\"LANG=C.UTF-8\",\"JAVA_VERSION=17.0.2\"],\"Cmd\":null,\"Image\":\"sha256:925cc8c298f96a1e65fb921a97d2070f07d0ee5d8fc2bf51a4eefa21f3d5801c\",\"Volumes\":null,\"WorkingDir\":\"/app\",\"Entrypoint\":[\"java\",\"-jar\",\"springVueStarter-0.0.1-SNAPSHOT.jar\"],\"OnBuild\":null,\"Labels\":null},\"docker_version\":\"24.0.5\",\"architecture\":\"amd64\"}"
  }, {
    "v1Compatibility" : "{\"id\":\"5c038964690f2eebea3feb8a0eaf48b52de43c5a93ce2ed852dc13b6e58daf92\",\"parent\":\"9ce3e6d90a73c949485418a1ffe7958113c2026d1cc722c0ba64a3cd088400b0\",\"comment\":null,\"created\":\"2023-10-27T14:08:58.554940559Z\",\"throwaway\":false,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) COPY file:3708ed22897e6f3364d3a7685bf03434e941c9676059fc904b08fdc1e1c234d7 in . \"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"9ce3e6d90a73c949485418a1ffe7958113c2026d1cc722c0ba64a3cd088400b0\",\"parent\":\"eff06ff0328aa3b368603706fe11484281cafb352051fc4d247c10f364674c78\",\"comment\":null,\"created\":\"2023-10-27T14:08:58.189848571Z\",\"throwaway\":false,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) WORKDIR /app\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"eff06ff0328aa3b368603706fe11484281cafb352051fc4d247c10f364674c78\",\"parent\":\"e9799d31bb42665d55ea83786be278d044bdd77b7045b9e27dd976d80eba1fb0\",\"comment\":null,\"created\":\"2022-04-27T21:54:28.871350186Z\",\"throwaway\":true,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  CMD [\\\"jshell\\\"]\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"e9799d31bb42665d55ea83786be278d044bdd77b7045b9e27dd976d80eba1fb0\",\"parent\":\"eb51a7d6c41e9e10355f32f85033e48f4dfeed042f8d793b965eb9de8bc5ba36\",\"comment\":null,\"created\":\"2022-04-27T21:54:28.248363534Z\",\"throwaway\":false,\"container_config\":{\"Cmd\":[\"/bin/sh -c set -eux; \\t\\tarch=\\\"$(objdump=\\\"$(command -v objdump)\\\" && objdump --file-headers \\\"$objdump\\\" | awk -F '[:,]+[[:space:]]+' '$1 == \\\"architecture\\\" { print $2 }')\\\"; \\tcase \\\"$arch\\\" in \\t\\t'i386:x86-64') \\t\\t\\tdownloadUrl='https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-x64_bin.tar.gz'; \\t\\t\\tdownloadSha256='0022753d0cceecacdd3a795dd4cea2bd7ffdf9dc06e22ffd1be98411742fbb44'; \\t\\t\\t;; \\t\\t'aarch64') \\t\\t\\tdownloadUrl='https://download.java.net/java/GA/jdk17.0.2/dfd4a8d0985749f896bed50d7138ee7f/8/GPL/openjdk-17.0.2_linux-aarch64_bin.tar.gz'; \\t\\t\\tdownloadSha256='13bfd976acf8803f862e82c7113fb0e9311ca5458b1decaef8a09ffd91119fa4'; \\t\\t\\t;; \\t\\t*) echo >&2 \\\"error: unsupported architecture: '$arch'\\\"; exit 1 ;; \\tesac; \\t\\tcurl -fL -o openjdk.tgz \\\"$downloadUrl\\\"; \\techo \\\"$downloadSha256 *openjdk.tgz\\\" | sha256sum --strict --check -; \\t\\tmkdir -p \\\"$JAVA_HOME\\\"; \\ttar --extract \\t\\t--file openjdk.tgz \\t\\t--directory \\\"$JAVA_HOME\\\" \\t\\t--strip-components 1 \\t\\t--no-same-owner \\t; \\trm openjdk.tgz*; \\t\\trm -rf \\\"$JAVA_HOME/lib/security/cacerts\\\"; \\tln -sT /etc/pki/ca-trust/extracted/java/cacerts \\\"$JAVA_HOME/lib/security/cacerts\\\"; \\t\\tln -sfT \\\"$JAVA_HOME\\\" /usr/java/default; \\tln -sfT \\\"$JAVA_HOME\\\" /usr/java/latest; \\tfor bin in \\\"$JAVA_HOME/bin/\\\"*; do \\t\\tbase=\\\"$(basename \\\"$bin\\\")\\\"; \\t\\t[ ! -e \\\"/usr/bin/$base\\\" ]; \\t\\talternatives --install \\\"/usr/bin/$base\\\" \\\"$base\\\" \\\"$bin\\\" 20000; \\tdone; \\t\\tjava -Xshare:dump; \\t\\tfileEncoding=\\\"$(echo 'System.out.println(System.getProperty(\\\"file.encoding\\\"))' | jshell -s -)\\\"; [ \\\"$fileEncoding\\\" = 'UTF-8' ]; rm -rf ~/.java; \\tjavac --version; \\tjava --version\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"eb51a7d6c41e9e10355f32f85033e48f4dfeed042f8d793b965eb9de8bc5ba36\",\"parent\":\"9f856f090b3536454e5dfb06417462f2b7f391d5dbcc5d4d8ce39eccc26f6528\",\"comment\":null,\"created\":\"2022-04-27T21:54:18.81978611Z\",\"throwaway\":true,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  ENV JAVA_VERSION=17.0.2\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"9f856f090b3536454e5dfb06417462f2b7f391d5dbcc5d4d8ce39eccc26f6528\",\"parent\":\"8ac2449f7c71a09ae2fcf0253d007f54855bd2b51e6e7a524c12d80e81da75c0\",\"comment\":null,\"created\":\"2022-04-27T21:54:18.72299961Z\",\"throwaway\":true,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  ENV LANG=C.UTF-8\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"8ac2449f7c71a09ae2fcf0253d007f54855bd2b51e6e7a524c12d80e81da75c0\",\"parent\":\"9e159ca1a23d7dd7f70a80b77a2009aab1043a985bee651535e1b4ac538cf83a\",\"comment\":null,\"created\":\"2022-04-27T21:54:18.615815298Z\",\"throwaway\":true,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  ENV PATH=/usr/java/openjdk-17/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"9e159ca1a23d7dd7f70a80b77a2009aab1043a985bee651535e1b4ac538cf83a\",\"parent\":\"9ff05dccb75eb8b47fd096d2bbe95a98475434351cc3161faeda4b20474d1f27\",\"comment\":null,\"created\":\"2022-04-27T21:54:18.51503692Z\",\"throwaway\":true,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  ENV JAVA_HOME=/usr/java/openjdk-17\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"9ff05dccb75eb8b47fd096d2bbe95a98475434351cc3161faeda4b20474d1f27\",\"parent\":\"819efa67053eb6082ff11632303f437a4ac4304b8c6bc179045a1a4943bb607b\",\"comment\":null,\"created\":\"2022-04-27T21:53:12.339171869Z\",\"throwaway\":false,\"container_config\":{\"Cmd\":[\"/bin/sh -c set -eux; \\tmicrodnf install \\t\\tgzip \\t\\ttar \\t\\t\\t\\tbinutils \\t\\tfreetype fontconfig \\t; \\tmicrodnf clean all\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"819efa67053eb6082ff11632303f437a4ac4304b8c6bc179045a1a4943bb607b\",\"parent\":\"307d1c5b9e9926994500bc7e8c7be52284699ad8b7bceaed378f6b7cbb328a91\",\"comment\":null,\"created\":\"2022-04-27T20:33:05.045198088Z\",\"throwaway\":true,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop)  CMD [\\\"/bin/bash\\\"]\"]}}"
  }, {
    "v1Compatibility" : "{\"id\":\"307d1c5b9e9926994500bc7e8c7be52284699ad8b7bceaed378f6b7cbb328a91\",\"parent\":\"\",\"comment\":null,\"created\":\"2022-04-27T20:33:04.547787858Z\",\"throwaway\":false,\"container_config\":{\"Cmd\":[\"/bin/sh -c #(nop) ADD file:9893213a9ea238f53ac68d87a3cf2f05d86763688392e5ddb6a2c9b60d3550a6 in / \"]}}"
  } ],
  "signatures" : [ {
    "header" : {
      "jwk" : {
        "crv" : "P-256",
        "kty" : "EC",
        "x" : "dGRDKBAV4COsK_f_Ll4k7QePfLE5-0DqZV9i5dLAJDw",
        "y" : "mES9BDi2ZjAyGsoGpa89i9r1akgvyJVIEekqrmrPiAM"
      },
      "alg" : "ES256"
    },
    "signature" : "KPe3Q2CF_H2i9PHl6utoMnqXZ95NstYGSHhx1rY2vk_WFkt1z7IiIlEJ_h2pQAlGSbgasGUB_TEJ6drbfzwq-g",
    "protected" : "eyJmb3JtYXRMZW5ndGgiOjg5OTIsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAyMy0xMS0yNFQzOjU6MjcrMDAwMCJ9"
  } ]
}

\"Image\":\"sha256:925cc8c298f96a1e65fb921a97d2070f07d0ee5d8fc2bf51a4eefa21f3d5801c\ 를 찾아보자.

GET https://dmjgr11.jfrog.io/artifactory/api/search/checksum?sha256=925cc8c298f96a1e65fb921a97d2070f07d0ee5d8fc2bf51a4eefa21f3d5801c

{
    "results": []
}

조회되지 않는다. 이것은 없다는 것은 베이스 이미지가 로컬에서 관리되지 않는 Public 이라는 것을 추즉할 수 있다.

분석 요약

분석 결과

  • 최상위 레이어 즉, Container Layer 에서 “Image” 키값을 이용하여 base image layer 에 해당되는 해쉬값을 추출 및 해당 layer 가 참조되는 Image Name 들을 확인할 수 있다.
  • “tdownloadUrl” 정보는 Origin Layer 라는 것을 확인할 수 있다.
  • base image 삭제 후에도 빌드는 된다. 구글링을 해보니 cache 에 이미지가 남아 있어서 그렇다고 한다.
  • 그렇다고 해도 base image 의 해쉬 즉, 이미지 레이어가 있고 없고는 어떻게 알 수 있을까?

다음 장인 [Docker Layer Analysis 상세 분석] 에서 좀 더 알아보자.