Aug 9th, 2019 - written by Kimserey with .
Last week we looked into the definition of a Dockerfile. We saw that a Dockerfile describes how an image will be built, the next obvious step is to dig into the building process of the image by looking at the logs and exploring the image layers.
Taking an example of a dotnet
Dockerfile,
1
2
3
4
5
6
7
8
9
10
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY . .
WORKDIR /src/WebApplication1
RUN dotnet publish WebApplication1.csproj -c Release -o /app
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]
we can run a docker build
which would build the image:
1
docker build -f .\WebApplication1\Dockerfile -t webapplication1 ./
-f
specifies the location of the Dockerfile, while -t
specifies a tag for the image. We actually did not give any tag in this case which made the image have the default tag of latest
. The format to provide a tag is {image_name}:{tag}
. The last argument ./
is the build context which is the folder from where the image will be built, where we will be able to copy files from.
If you want to know more about how to build a Dockerfile, you can refer to my previous blog post.
Once we run docker build
we get the following logs:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Sending build context to Docker daemon 18.94kB
Step 1/9 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
2.2-stretch: Pulling from dotnet/core/sdk
Digest: sha256:808da273022a5bb7b2c15fb80acb85e0432fa79993bbf1e6e982d4e01349c191
Status: Downloaded newer image for mcr.microsoft.com/dotnet/core/sdk:2.2-stretch
---> 3af77ac73731
Step 2/9 : WORKDIR /src
---> Running in 0f70be63faae
Removing intermediate container 0f70be63faae
---> 3194c452d135
Step 3/9 : COPY . .
---> b656b9271c5c
Step 4/9 : WORKDIR /src/WebApplication1
---> Running in 6648557dbbbb
Removing intermediate container 6648557dbbbb
---> e3fcdcb1792e
Step 5/9 : RUN dotnet publish WebApplication1.csproj -c Release -o /app
---> Running in 7fbc5519b556
Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 21.52 sec for /src/WebApplication1/WebApplication1.csproj.
WebApplication1 -> /src/WebApplication1/bin/Release/netcoreapp2.2/WebApplication1.dll
WebApplication1 -> /app/
Removing intermediate container 7fbc5519b556
---> c6bc468635fe
Step 6/9 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim
---> 3ee0429b27ad
Step 7/9 : WORKDIR /app
---> Running in 921f7feed14a
Removing intermediate container 921f7feed14a
---> 01e4a68b3a49
Step 8/9 : COPY --from=build /app .
---> 9857d4ca4813
Step 9/9 : ENTRYPOINT ["dotnet", "WebApplication1.dll"]
---> Running in a9345c006948
Removing intermediate container a9345c006948
---> d9dc22edcb71
Successfully built d9dc22edcb71
Successfully tagged webapplication1:latest
The first line indicates to us the size of the build context,
1
Sending build context to Docker daemon 18.94kB
even though our whole application folder isn’t that size, we stripped off all unnecessary files by using a .dockerignore
file, reducing the build context to 18.94kb
.
Then we can see the first log for the execution of the first instruction from the dockerfile:
1
2
3
4
5
Step 1/9 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
2.2-stretch: Pulling from dotnet/core/sdk
Digest: sha256:808da273022a5bb7b2c15fb80acb85e0432fa79993bbf1e6e982d4e01349c191
Status: Downloaded newer image for mcr.microsoft.com/dotnet/core/sdk:2.2-stretch
---> 3af77ac73731
1/9
is the step number from the Dockerfile, our first instruction was to build our image starting from the dotnet/core/sdk
image. The image id 3af77ac73731
corresponds to the dotnet/core/sdk
image sha that we are using. For example, here if we were to pull locally the image mcr.microsoft.com/dotnet/core/sdk:2.2-stretch
, we will see that its id is 3af77ac73731
.
The next log step,
1
2
3
4
Step 2/9 : WORKDIR /src
---> Running in 0f70be63faae
Removing intermediate container 0f70be63faae
---> 3194c452d135
explains that the work directory is set to /src
within the image. It runs in an intermediate container 0f70be63faae
which creates a /src
folder in the container resulting in a layer 3194c452d135
.
Then we have a copy,
1
2
Step 3/9 : COPY . .
---> b656b9271c5c
Copying files from the build context to the current work directory /src
, resulting in a layer b656b9271c5c
.
Next we have another set of work directory,
1
2
3
4
Step 4/9 : WORKDIR /src/WebApplication1
---> Running in 6648557dbbbb
Removing intermediate container 6648557dbbbb
---> e3fcdcb1792e
resulting in a layer e3fcdcb1792e
. Since we previously copied the files, we are then able to publish the application.
1
2
3
4
5
6
7
8
9
10
Step 5/9 : RUN dotnet publish WebApplication1.csproj -c Release -o /app
---> Running in 7fbc5519b556
Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 21.52 sec for /src/WebApplication1/WebApplication1.csproj.
WebApplication1 -> /src/WebApplication1/bin/Release/netcoreapp2.2/WebApplication1.dll
WebApplication1 -> /app/
Removing intermediate container 7fbc5519b556
---> c6bc468635fe
The command is ran in a intermediate container 7fbc5519b556
and results in a layer c6bc468635fe
. In the initial FROM
, we have name the stage AS build
. The five layers constitute the image build
which is an image containing the published application under the /app/ folder.
Then similarly the rest of the steps are executed in containers and result in layers being stacked until the last layer constituting the webapplication1
image.
1
2
3
4
5
6
7
8
9
10
11
12
Step 6/9 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim
---> 3ee0429b27ad
Step 7/9 : WORKDIR /app
---> Running in 921f7feed14a
Removing intermediate container 921f7feed14a
---> 01e4a68b3a49
Step 8/9 : COPY --from=build /app .
---> 9857d4ca4813
Step 9/9 : ENTRYPOINT ["dotnet", "WebApplication1.dll"]
---> Running in a9345c006948
Removing intermediate container a9345c006948
---> d9dc22edcb71
The last layer id d9dc22edcb71
is the image id resulting of the docker build
command.
1
2
Successfully built d9dc22edcb71
Successfully tagged webapplication1:latest
Once the image is built, we can find it from docker image ls
:
1
2
3
4
5
6
7
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> c6bc468635fe 39 seconds ago 1.79GB
webapplication1 latest d9dc22edcb71 2 hours ago 262MB
mcr.microsoft.com/dotnet/core/sdk 2.2-stretch 3af77ac73731 9 days ago 1.74GB
mcr.microsoft.com/dotnet/core/aspnet 2.2-stretch-slim 3ee0429b27ad 9 days ago 260MB
mcr.microsoft.com/dotnet/core/aspnet latest 3ee0429b27ad 9 days ago 260MB
And we can look at its configuration using docker inspect d9dc22edcb71
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
$ docker inspect d9dc22edcb71
[
{
"Id": "sha256:d9dc22edcb716a92f5e68f915fc5b3debced288737066af5ef7821a0ba3375d4",
"RepoTags": [
"webapplication1:latest"
],
"RepoDigests": [],
"Parent": "sha256:9857d4ca4813255a56469450829fe2a9f85fa2b93c8622061fea0ef93083fe24",
"Comment": "",
"Created": "2019-08-02T18:03:37.1689906Z",
"Container": "a9345c006948bd6eb4f106571c2e9f114a57deb088fcf0a58a752c3331a829e1",
"ContainerConfig": {
"Hostname": "a9345c006948",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"ASPNETCORE_URLS=http://+:80",
"DOTNET_RUNNING_IN_CONTAINER=true",
"ASPNETCORE_VERSION=2.2.6"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"ENTRYPOINT [\"dotnet\" \"WebApplication1.dll\"]"
],
"Image": "sha256:9857d4ca4813255a56469450829fe2a9f85fa2b93c8622061fea0ef93083fe24",
"Volumes": null,
"WorkingDir": "/app",
"Entrypoint": [
"dotnet",
"WebApplication1.dll"
],
"OnBuild": null,
"Labels": {}
},
"DockerVersion": "19.03.1",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"ASPNETCORE_URLS=http://+:80",
"DOTNET_RUNNING_IN_CONTAINER=true",
"ASPNETCORE_VERSION=2.2.6"
],
"Cmd": null,
"Image": "sha256:9857d4ca4813255a56469450829fe2a9f85fa2b93c8622061fea0ef93083fe24",
"Volumes": null,
"WorkingDir": "/app",
"Entrypoint": [
"dotnet",
"WebApplication1.dll"
],
"OnBuild": null,
"Labels": null
},
"Architecture": "amd64",
"Os": "linux",
"Size": 261541404,
"VirtualSize": 261541404,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/15c7304f08de55890d6de74d9a5c0fbdc9cea87019ac01d4c3d763f157893169/diff:/var/lib/docker/overlay2/57d5f1900c0e4859a05b1911af056a1e491c8f029a643d51ac51fcc94854b9ba/diff:/var/lib/docker/overlay2/a0decbde6391daf0bc065778ddec12e27fa4de57d3d92c9658f842e795452921/diff:/var/lib/docker/overlay2/ef9157128986fbeb6625b5bbe2cc4ef6211105527b1f1f9b5478ab2e57a37dbf/diff:/var/lib/docker/overlay2/7213c0db8cf3f2bb71f8709b51d8debf24bce93104a5f375e2b710b369bace4c/diff",
"MergedDir": "/var/lib/docker/overlay2/06fd28ea362b73edb62ee0aefd31d4d4a1015c956ed0916e7e9bf65669f0b025/merged",
"UpperDir": "/var/lib/docker/overlay2/06fd28ea362b73edb62ee0aefd31d4d4a1015c956ed0916e7e9bf65669f0b025/diff",
"WorkDir": "/var/lib/docker/overlay2/06fd28ea362b73edb62ee0aefd31d4d4a1015c956ed0916e7e9bf65669f0b025/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:d56055da3352f918f4d8a42350385ea5b10d0906e746a8fbb4b850f9284deee5",
"sha256:9c894eb0930bc544405419e57fdc34dec3d22ce42e165829fe9e03c6dd8e0758",
"sha256:c6c9de941dfa6e4849e7f0026e180a2d4e5d9263316e9ab6676480c7e299e9e4",
"sha256:6339615de93e6000914871a96e377bd9c4828f23e02491d5fa30ccebd2c97cdb",
"sha256:09874d0e88c646a7e7ac2d94076cfaa50c7e63555ce7e4ff6ff4b6596c6ce099",
"sha256:87f4ccb229bb7484f733ebab6648e7493a2c550167f251819f72523124eacec6"
]
},
"Metadata": {
"LastTagTime": "2019-08-02T18:16:13.109039Z"
}
}
]
The containerConfig
property is particularly interesting:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"ASPNETCORE_URLS=http://+:80",
"DOTNET_RUNNING_IN_CONTAINER=true",
"ASPNETCORE_VERSION=2.2.6"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"ENTRYPOINT [\"dotnet\" \"WebApplication1.dll\"]"
],
"WorkingDir": "/app"
}
It showcases the environment variables set for our image, the command which will be executed when running the container and the working directory where the command is executed from.
Now you might have noticed the <none>
c6bc468635fe
image of size 1.79GB
which showed up in the docker image ls
. The CLI shows <none>
for untagged images. If we look back at the logs, we can see that c6bc468635fe
corresponds to our last layer of our build
stage:
1
2
3
4
5
6
7
8
9
10
Step 5/9 : RUN dotnet publish WebApplication1.csproj -c Release -o /app
---> Running in 7fbc5519b556
Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 21.52 sec for /src/WebApplication1/WebApplication1.csproj.
WebApplication1 -> /src/WebApplication1/bin/Release/netcoreapp2.2/WebApplication1.dll
WebApplication1 -> /app/
Removing intermediate container 7fbc5519b556
---> c6bc468635fe
The role of the stage was to provide the tools to publish the application and allow the next stage to just copy the files already precompiled hence allowing the resulting image to only contain the runtime and strip off the development SDK.
We can see the difference in size from the SDK image of 1.74GB
compared to the runtime image of 260MB
. The difference is non negligible therefore we have to make sure to start from a runtime image and leave behind the SDK image.
One advantage of keeping around the intermediate image is for caching purposes. If we rerun the build, we will see that the step is taken from cache:
1
2
3
Step 5/9 : RUN dotnet publish WebApplication1.csproj -c Release -o /app
---> Using cache
---> c6bc468635fe
If we prune the images docker image prune
, the <none>
image will be cleared and will result in recomputing the layer on build.
The cached layers can be seen using docker image ls -a
. For example if we rebuild the image:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$ docker build -f WebApplication1\Dockerfile -t webapplication1 ./
Sending build context to Docker daemon 18.94kB
Step 1/9 : FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
---> 3af77ac73731
Step 2/9 : WORKDIR /src
---> Running in 8d3e636315d3
Removing intermediate container 8d3e636315d3
---> 9bcd7944b833
Step 3/9 : COPY . .
---> 156063c13984
Step 4/9 : WORKDIR /src/WebApplication1
---> Running in 2a1d5a2063ac
Removing intermediate container 2a1d5a2063ac
---> 5608d2c9e274
Step 5/9 : RUN dotnet publish WebApplication1.csproj -c Release -o /app
---> Running in edbd56b760ba
Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 20.93 sec for /src/WebApplication1/WebApplication1.csproj.
WebApplication1 -> /src/WebApplication1/bin/Release/netcoreapp2.2/WebApplication1.dll
WebApplication1 -> /app/
Removing intermediate container edbd56b760ba
---> 766e5f5eda98
Step 6/9 : FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim
---> 3ee0429b27ad
Step 7/9 : WORKDIR /app
---> Using cache
---> 01e4a68b3a49
Step 8/9 : COPY --from=build /app .
---> Using cache
---> 9857d4ca4813
Step 9/9 : ENTRYPOINT ["dotnet", "WebApplication1.dll"]
---> Using cache
---> d9dc22edcb71
Successfully built d9dc22edcb71
Successfully tagged webapplication1:latest
We can see the untagged image and our webapplication1
image:
1
2
3
4
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 766e5f5eda98 About a minute ago 1.79GB
webapplication1 latest d9dc22edcb71 2 hours ago 262M
And when we display all layers:
1
2
3
4
5
6
7
8
9
$ docker image ls -a
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 766e5f5eda98 50 seconds ago 1.79GB
<none> <none> 5608d2c9e274 About a minute ago 1.74GB
<none> <none> 156063c13984 About a minute ago 1.74GB
<none> <none> 9bcd7944b833 About a minute ago 1.74GB
webapplication1 latest d9dc22edcb71 2 hours ago 262MB
<none> <none> 01e4a68b3a49 2 hours ago 260MB
<none> <none> 9857d4ca4813 2 hours ago 262MB
We see that 5608d2c9e274
, 156063c13984
and 9bcd7944b833
are layers for 766e5f5eda98
. While 01e4a68b3a49
and 9857d4ca4813
are layers for webapplication1
d9dc22edcb71
.
If we delete the image webapplication1
, all the layers for webapplication1
will be removed but the intermediate stage 766e5f5eda98
will not be removed. Therefore if we build again, Docker will be able to take advantage of the caching layer.
Caching is an important part of Docker build as it allows the build to be quicker.
On Windows, with Powershell we can use Measure-Command { <your command here> | Write-Host }
to measure the time of the build.
Building an image consists mostly of copying files. Copying from the build context, or copying from different stages. It can be very easy to mistakenly copy the wrong folder or the wrong files and have the image build with the wrong entrypoint.
To explore docker image we can use a tool called Dive
, which allows us to explore a Docker image, or layer content. Doing so allows us to check for mistake and also allows us to look for potential optimization in regards to the size.
Dive can be downloaded from its Github repository.
After downloading it, we simple run dive <image>
and we will enter the GUI allowing us to inspect the content of our image.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
[● Layers]──────────────────────────────────────────────────────── [Current Layer Contents]─────────────────────────────────────────
Cmp Size Command Permission UID:GID Size Filetree
55 MB FROM sha256:d56055da drwxr-xr-x 0:0 4.6 MB ├── bin
44 MB apt-get update && apt-get install -y --no-install- -rwxr-xr-x 0:0 1.1 MB │ ├── bash
7.0 MB apt-get update && apt-get install -y --no-install- -rwxr-xr-x 0:0 36 kB │ ├── cat
154 MB curl -SL --output aspnetcore.tar.gz https://dotnetcli. -rwxr-xr-x 0:0 64 kB │ ├── chgrp
0 B #(nop) WORKDIR /app -rwxr-xr-x 0:0 60 kB │ ├── chmod
1.1 MB #(nop) COPY dir:5df981166cc4bf1e0b1d1fbb31d69f366ee88f -rwxr-xr-x 0:0 64 kB │ ├── chown
-rwxr-xr-x 0:0 130 kB │ ├── cp
[Layer Details]─────────────────────────────────────────────────── -rwxr-xr-x 0:0 117 kB │ ├── dash
-rwxr-xr-x 0:0 105 kB │ ├── date
Digest: sha256:d56055da3352f918f4d8a42350385ea5b10d0906e746a8fbb4b -rwxr-xr-x 0:0 77 kB │ ├── dd
850f9284deee5 -rwxr-xr-x 0:0 86 kB │ ├── df
Command: -rwxr-xr-x 0:0 131 kB │ ├── dir
#(nop) ADD file:966bd7368f1e5a3e40fe5fab63ebe3c04719f677cc49385462 -rwxr-xr-x 0:0 73 kB │ ├── dmesg
e4dfda4c4096fb in / -rwxrwxrwx 0:0 0 B │ ├── dnsdomainname → hostname
-rwxrwxrwx 0:0 0 B │ ├── domainname → hostname
[Image Details]─────────────────────────────────────────────────── -rwxr-xr-x 0:0 32 kB │ ├── echo
-rwxr-xr-x 0:0 28 B │ ├── egrep
Total Image size: 262 MB -rwxr-xr-x 0:0 32 kB │ ├── false
Potential wasted space: 3.7 MB -rwxr-xr-x 0:0 28 B │ ├── fgrep
Image efficiency score: 99 % -rwxr-xr-x 0:0 62 kB │ ├── findmnt
-rwxr-xr-x 0:0 215 kB │ ├── grep
Count Total Space Path -rwxr-xr-x 0:0 2.3 kB │ ├── gunzip
2 1.5 MB /var/cache/debconf/templates.dat -rwxr-xr-x 0:0 5.9 kB │ ├── gzexe
2 1.5 MB /var/cache/debconf/templates.dat-old -rwxr-xr-x 0:0 102 kB │ ├── gzip
3 244 kB /var/lib/dpkg/status -rwxr-xr-x 0:0 19 kB │ ├── hostname
3 244 kB /var/lib/dpkg/status-old -rwxr-xr-x 0:0 56 kB │ ├── ln
2 29 kB /var/log/dpkg.log -rwxr-xr-x 0:0 53 kB │ ├── login
3 26 kB /etc/ld.so.cache -rwxr-xr-x 0:0 131 kB │ ├── ls
2 23 kB /var/cache/debconf/config.dat -rwxr-xr-x 0:0 81 kB │ ├── lsblk
2 18 kB /var/log/apt/term.log -rwxr-xr-x 0:0 81 kB │ ├── mkdir
3 15 kB /var/lib/apt/extended_states -rwxr-xr-x 0:0 69 kB │ ├── mknod
2 14 kB /var/cache/ldconfig/aux-cache -rwxr-xr-x 0:0 44 kB │ ├── mktemp
2 11 kB /var/log/apt/eipp.log.xz -rwxr-xr-x 0:0 40 kB │ ├── more
2 9.1 kB /var/cache/debconf/config.dat-old -rwxr-xr-x 0:0 44 kB │ ├── mount
2 2.6 kB /var/log/apt/history.log -rwxr-xr-x 0:0 15 kB │ ├── mountpoint
2 0 B /var/lib/dpkg/triggers/Unincorp -rwxr-xr-x 0:0 126 kB │ ├── mv
3 0 B /var/lib/dpkg/triggers/Lock -rwxrwxrwx 0:0 0 B │ ├── nisdomainname → hostname
3 0 B /var/lib/dpkg/lock -rwxrwxrwx 0:0 0 B │ ├── pidof → /sbin/killall5
-rwxr-xr-x 0:0 36 kB │ ├── pwd
-rwxrwxrwx 0:0 0 B │ ├── rbash → bash
On the top left we can see the different instructions which composed the image, while on the right we can explore the filesystem in the resulting image. Layers can also be explored using docker history <image>
.
1
2
3
4
5
6
7
8
9
10
11
12
$ docker history webapplication1
IMAGE CREATED CREATED BY SIZE COMMENT
1805da23bee2 11 hours ago /bin/sh -c #(nop) ENTRYPOINT ["dotnet" "Web… 0B
becdc8ed4269 11 hours ago /bin/sh -c #(nop) COPY dir:5df981166cc4bf1e0… 1.09MB
a027a3092b27 11 hours ago /bin/sh -c #(nop) WORKDIR /app 0B
3ee0429b27ad 9 days ago /bin/sh -c curl -SL --output aspnetcore.tar.… 154MB
<missing> 9 days ago /bin/sh -c #(nop) ENV ASPNETCORE_VERSION=2.… 0B
<missing> 9 days ago /bin/sh -c apt-get update && apt-get ins… 7.02MB
<missing> 9 days ago /bin/sh -c #(nop) ENV ASPNETCORE_URLS=http:… 0B
<missing> 9 days ago /bin/sh -c apt-get update && apt-get ins… 43.8MB
<missing> 3 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 3 weeks ago /bin/sh -c #(nop) ADD file:966bd7368f1e5a3e4… 55.3MB
Lastly tagging multiple time an image as part of building is one way of keeping track of different build for a particular image. For example we could keep track of the version number:
1
docker build -f WebApplication1\Dockerfile -t webapplication1 -t webapplication1:1.0.0 ./
Then we would have the same image with two tags allowing us to easily identify which version is the latest version:
1
2
3
4
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
webapplication1 1.0.0 1805da23bee2 27 minutes ago 262MB
webapplication1 latest 1805da23bee2 27 minutes ago 262MB
We can also see examples on Docker hub of how tags are used to build the same image on different distros.
Today we looked into the details of a Docker image. How it was built, what were the logs provided and what they meant. We looked into the details of what the layers were when building the image, and we looked at how the layers were cache and where they could be found. We then looked into a tool to explore the filesystem built by the layers and we completed the post by looking into the purpose of multiple tags. I hope you liked this post and I see you on the next one!