Partial Docker image of operation and maintenance actual combat container

Mirrored hierarchy

  • Shared host kernel

  • base image provides the smallest linux system

  • The same docker host supports running multiple linux distributions

  • The biggest advantage of adopting hierarchical structure is to share resources

Copy in write writable container layer

  • All mirror layers below the container layer are read-only

  • docker looks for files from top to bottom

  • The container layer saves the changed part of the image without any modification to the image itself

  • A mirror can only have 127 layers at most

Construction of image

Dockerfile mode is adopted

##Download the original image busybox
docker pull busybox
##Create containers interactively and simply test
[root@Server1 ~]# docker run -it --name Busybox busybox
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # mkdir Test
/ # ls
Test  bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # 

##Exit interactive mode
ctrl+ d 			Exit and close the container
ctrl+ pq 			Exit and drive the container into the background

##Create an empty directory to store Dockerfile
[root@Server1 ~]# cd /mnt/
[root@Server1 mnt]# mkdir Docker
[root@Server1 Docker]# vim Dockerfile

##Document content
FROM busybox
RUN touch Test
RUN cd Test
RUN touch file{1..10}

##Use the Dockerfile of the current directory to build the image
[root@Server1 Docker]# docker build -t testbox .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM busybox
 ---> 388056c9a683
Step 2/3 : RUN mkdir Test
 ---> Running in 0bbfb83c4a2f
Removing intermediate container 0bbfb83c4a2f
 ---> 2dd01c73369c
Step 3/3 : RUN touch file{1..10}
 ---> Running in 9c15b75bfdfe
Removing intermediate container 9c15b75bfdfe
 ---> aa4cd0b3c97a
Successfully built aa4cd0b3c97a
Successfully tagged testbox:latest

##Viewing the native image, you can see the newly built testbox
[root@Server1 Docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
testbox             latest              aa4cd0b3c97a        17 seconds ago      1.23MB
busybox             latest              388056c9a683        2 weeks ago         1.23MB

##Looking at the construction history, you can see that each operation has become a new layer
[root@Server1 Docker]# docker history testbox:latest 
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
aa4cd0b3c97a        43 seconds ago      /bin/sh -c touch file{1..10}                    0B                  
2dd01c73369c        44 seconds ago      /bin/sh -c mkdir Test                           0B                  
388056c9a683        2 weeks ago         /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           2 weeks ago         /bin/sh -c #(nop) ADD file:8d57331dc331805f0...   1.23MB  

Using Dockerfile, you can see the records and operation contents of the new layer built based on busybox

If you use the commit method, it will be slightly different

Commit mode is adopted

##Delete the container just created in Dockerfile mode
[root@Server1 Docker]# docker rmi testbox:latest 
Untagged: testbox:latest
Deleted: sha256:aa4cd0b3c97a7fcf23834549a7a5a169c93b84e4f1b2cc4e77fd6deba2996a8a
Deleted: sha256:3961fc3b6ac0630016bbcab16b49c69294b7b12727995db5ec416b7d961c936e
Deleted: sha256:2dd01c73369c25ce7d6605e4f144a5660e30eef40368a1aece8b08ba5a6c5288
Deleted: sha256:80b97add01edb4a71fc8c4e3a11823cef75fb312d6ed0a74ac0f4dd5b8ff18a4
[root@Server1 Docker]# docker run -it --name Busybox busybox
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # mkdir Test
/ # cd Test/
/Test # touch file{1..10}

ctrl+p q exits interactive mode and puts the container into the background

[root@Server1 Docker]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
7b38fd8cf7b9        busybox             "sh"                31 seconds ago      Up 31 seconds                           Busybox
##Commit the update and generate a new image testbox
[root@Server1 Docker]# docker commit -m "V1" Busybox testbox:V1
sha256:1f68ffbebec57daf89e32b9e444679406651bb24817a84eb1e4c0cefb2bdc49e
[root@Server1 Docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
testbox             V1                  1f68ffbebec5        5 seconds ago       1.23MB
busybox             latest              388056c9a683        2 weeks ago         1.23MB
##Looking at the history of image construction, you can see that the specific content of the new layer is not displayed
[root@Server1 Docker]# docker history testbox:V1 
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
1f68ffbebec5        12 seconds ago      sh                                              41B                 V1
388056c9a683        2 weeks ago         /bin/sh -c #(nop)  CMD ["sh"]                   0B                  
<missing>           2 weeks ago         /bin/sh -c #(nop) ADD file:8d57331dc331805f0...   1.23MB         

Therefore, it is recommended to use Dockerfile to build images

Dockerfile details

  • FROM

    Specify the base image. If it does not exist locally, it will be pulled from the network

  • MAINTAINER

    Set the author of the image, such as user mailbox, etc

  • Copy

    • Copy the file from the build context to the image from the local machine
    • Two forms are supported: COPY src dest and COPY ["src", "dest"]
    • It should be noted that the native file must be located in the build context, that is, the directory where the Dockerfile is located
  • ADD

    • The usage is similar to that of COPY. The difference is that src can be an archive compressed file. The file will be decompressed and put into the container
    • Native files do not need to be in the build context
    • You can also download files from the network and copy them to the image
  • ENV

    Set environment variables, which can be used by subsequent instructions

    • For example, env hostname Server1 example. com
  • EXPOSE

    If the application service is running in the container, it should be used when the service port needs to be exposed

    • Export 80, i.e. exposed port 80
  • VOLUME

    • Declare the data volume, which usually specifies the data mount point of the application
    • The purpose of mounting directories is to persist
    • Example VOLUME ["/var/www/html"]
  • WORKDIR

    • Set the current working directory in the image for the run, CMD, entry, add and copy instructions
    • If the directory does not exist, it is created automatically
  • RUN

    • Run the command in the container and create a new mirror layer, which is often used to install software packages
    • Example: RUN yum install -y vim
  • CMD and ENTRYPOINT

    • Both of these specifications are used to set the commands to be executed after the container is started
    • The difference is that CMD will be overwritten by the command line after RUN, and ENTRYPOINT will not be ignored / executed
    • The parameters after docker run can be passed to the ENTRYPOINT instruction as parameters
    • Only one entry point can be specified in Dockerfile. If many are specified, only the last one is valid

Differences between SHELL and EXEC formats

FROM busybox
ENV name world
ENTRYPOINT echo "hello, $name"

The bottom layer of Shell format will call / bin/sh -c to execute instructions, which can resolve variables, while the following Exec format will not

FROM busybox
ENV name world
ENTRYPOINT ["/bin/echo" "hello, $name"]

You must rewrite it to the following form to resolve variables normally

FROM busybox
ENV name world
ENTRYPOINT ["/bin/sh" "-c" "echo hello, $name"]

In Exec format, ENTRYPOINT can provide additional parameters through CMD, and the additional parameters of CMD can be dynamically replaced when the container is started

In Shell format, ENTRYPOINT will ignore any parameters provided by CMD or docker run

Operation process

[root@Server1 Docker]# vim Dockerfile 
[root@Server1 Docker]# touch index.html
[root@Server1 Docker]# echo Server1 > index.html 
[root@Server1 Docker]# ls
Dockerfile  index.html  nginx-1.18.0.tar.gz

##Dockerfile content
FROM busybox
RUN mkdir Test
RUN touch /Test/Testfile
COPY index.html /
ADD nginx-1.18.0.tar.gz /
RUN mv nginx-1.18.0 Nginx
ENV HOSTNAME Server1
EXPOSE 80
VOLUME ["/data"]
WORKDIR /Test
ENTRYPOINT ["/bin/echo", "hello"]
CMD ["world"]

[root@Server1 Docker]# docker build -t demo .
Sending build context to Docker daemon  1.043MB
Step 1/12 : FROM busybox
 ---> 388056c9a683
Step 2/12 : RUN mkdir Test
 ---> Running in 939e77e989f6
Removing intermediate container 939e77e989f6
 ---> 9537fc624d09
Step 3/12 : RUN touch /Test/Testfile
 ---> Running in 2ce46791eec2
Removing intermediate container 2ce46791eec2
 ---> 169b8b8c81f7
Step 4/12 : COPY index.html /
 ---> 6abd12f14c62
Step 5/12 : ADD nginx-1.18.0.tar.gz /
 ---> 7fd946b03383
Step 6/12 : RUN mv nginx-1.18.0 Nginx
 ---> Running in 9ac35e723827
Removing intermediate container 9ac35e723827
 ---> a817a5a3b1eb
Step 7/12 : ENV HOSTNAME Server1
 ---> Running in 5a494de50eb1
Removing intermediate container 5a494de50eb1
 ---> eb900f03448c
Step 8/12 : EXPOSE 80
 ---> Running in 77affb4662d8
Removing intermediate container 77affb4662d8
 ---> e17a7d084fcb
Step 9/12 : VOLUME ["/data"]
 ---> Running in 4208622c722a
Removing intermediate container 4208622c722a
 ---> 281920256f8d
Step 10/12 : WORKDIR /Test
 ---> Running in 31f5db039dd2
Removing intermediate container 31f5db039dd2
 ---> 73b41cdf5a3c
Step 11/12 : ENTRYPOINT ["/bin/echo", "hello"]
 ---> Running in bb798ebc3335
Removing intermediate container bb798ebc3335
 ---> bb598d50bedf
Step 12/12 : CMD ["world"]
 ---> Running in 3ac90fc7965b
Removing intermediate container 3ac90fc7965b
 ---> bae4405b5d28
Successfully built bae4405b5d28
Successfully tagged demo:latest
[root@Server1 Docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
demo                latest              bae4405b5d28        6 seconds ago       13.7MB
busybox             latest              388056c9a683        2 weeks ago         1.23MB
[root@Server1 Docker]# docker run --rm demo:latest 
hello world
[root@Server1 Docker]# docker run --rm demo:latest linux
hello linux

--rm parameter is often used for temporary test content. When the command is executed, the temporarily generated container will be closed and deleted

The parameters that follow are passed to the container for use

Therefore, when parameters are not passed, the output content is hello world according to the content of Dockerfile

When linux is passed, CMD parameters are overwritten, and the output content is hello linux

Example of VOLUME

[root@Server1 Docker]# docker run -it test
/Test # mount | grep data
/dev/mapper/rhel-root on /data type xfs (rw,relatime,attr2,inode64,noquota)

Back to the virtual machine, check the container and its persistence path

[root@Server1 volumes]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
df2e62b200ba        test                "sh"                About a minute ago   Up About a minute   80/tcp              agitated_pasteur
[root@Server1 volumes]# docker inspect df2e62b200ba
[
    {
        "Id": "df2e62b200bafe221739f6535fc89264b9791e60aa698537619ded42b3686e9b",
        "Created": "2021-04-27T03:01:58.831986169Z",
        "Path": "sh",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 17440,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-04-27T03:01:59.097958403Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:73b41cdf5a3c2bc7251b046f768859cd633e02f19c6a61ce5dd6931ba026d3c4",
        "ResolvConfPath": "/var/lib/docker/containers/df2e62b200bafe221739f6535fc89264b9791e60aa698537619ded42b3686e9b/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/df2e62b200bafe221739f6535fc89264b9791e60aa698537619ded42b3686e9b/hostname",
        "HostsPath": "/var/lib/docker/containers/df2e62b200bafe221739f6535fc89264b9791e60aa698537619ded42b3686e9b/hosts",
        "LogPath": "/var/lib/docker/containers/df2e62b200bafe221739f6535fc89264b9791e60aa698537619ded42b3686e9b/df2e62b200bafe221739f6535fc89264b9791e60aa698537619ded42b3686e9b-json.log",
        "Name": "/agitated_pasteur",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "Capabilities": null,
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/59faba205ad3939e7a17f0127ae3c8cde7ff1360088c52df1e0793d66f39bf45-init/diff:/var/lib/docker/overlay2/6a304244cf9f7712409a6fa2c95c4c51d14a5085873e0d58457713dc772831d0/diff:/var/lib/docker/overlay2/ceaa36629aa9b33f4e898f8bb10797379487b746251e6da9773f36ec3addb809/diff:/var/lib/docker/overlay2/96cc89b932c5d43df2052ee68c93ddafd5aa3966018abc87f6111015b2b8e4a5/diff:/var/lib/docker/overlay2/e272c5d92a4906480fc601b600f6310f2c065f0c85a649d9d322db837aace931/diff:/var/lib/docker/overlay2/03d7b22fc476b81aac770b2be9f3d55db1a405a7e5e341ef7038e8c97c378edd/diff:/var/lib/docker/overlay2/04834c81f78ab1e77f9d2f32ab79e19b11ff34af47af0dca505824dd8b5805ad/diff",
                "MergedDir": "/var/lib/docker/overlay2/59faba205ad3939e7a17f0127ae3c8cde7ff1360088c52df1e0793d66f39bf45/merged",
                "UpperDir": "/var/lib/docker/overlay2/59faba205ad3939e7a17f0127ae3c8cde7ff1360088c52df1e0793d66f39bf45/diff",
                "WorkDir": "/var/lib/docker/overlay2/59faba205ad3939e7a17f0127ae3c8cde7ff1360088c52df1e0793d66f39bf45/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [
            {
                "Type": "volume",
                "Name": "30b75ff3583bd344cecbc68ba19a023a61c4b9be8e98332adba879f9ac78136c",
                "Source": "/var/lib/docker/volumes/30b75ff3583bd344cecbc68ba19a023a61c4b9be8e98332adba879f9ac78136c/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
        "Config": {
            "Hostname": "df2e62b200ba",
            "Domainname": "",
            "User": "",
            "AttachStdin": true,
            "AttachStdout": true,
            "AttachStderr": true,
            "ExposedPorts": {
                "80/tcp": {}
            },
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": true,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "HOSTNAME=Server1"
            ],
            "Cmd": [
                "sh"
            ],
            "Image": "test",
            "Volumes": {
                "/data": {}
            },
            "WorkingDir": "/Test",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "c6391e8cdc95aaf864677d0d82f982093bca840a86de81f8565f9d4f29573cfa",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "80/tcp": null
            },
            "SandboxKey": "/var/run/docker/netns/c6391e8cdc95",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "d2a94cbedd95fdca62af4755c865f968077b498418df14f033ab238b08d2adc7",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "65b6bbdf4f1fc36862cd679fcc5fc6fc2c6b5326f8c9c7f76d1e4508975ae6c4",
                    "EndpointID": "d2a94cbedd95fdca62af4755c865f968077b498418df14f033ab238b08d2adc7",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

[root@Server1 volumes]# cd /var/lib/docker/volumes/30b75ff3583bd344cecbc68ba19a023a61c4b9be8e98332adba879f9ac78136c/_data
[root@Server1 _data]# ls
[root@Server1 _data]# touch Testfile
  • You can see that there are no files under the original path
  • When we create a test file, the file can also be seen in the test container
/ # cd /data/
/data # ls
Testfile
  • Similarly, any modification / deletion of the file on either side will be reflected on the other side

Image optimization

Optimization logic

  • Select the thinnest base image
  • Reduce the number of mirror layers
  • Clean up the intermediate products of image construction
  • Pay attention to optimizing network requests
  • Try to build a cache with
  • Use multistage to build mirrors

give an example

  • First, try to create an image of Nginx. Here, the reduced version of RHEL7 is used as the base image
FROM rhel7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
COPY NeuWings.repo /etc/yum.repos.d/NeuWings.repo
RUN rm -rf /etc/yum.repos.d/rhel7.repo
RUN rpmdb --rebuilddb
RUN yum install -y gcc pcre-devel zlib-devel > /dev/null
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN ./configure --prefix=/usr/local/nginx > /dev/null
RUN yum install -y make > /dev/null
RUN make > /dev/null
RUN make install > /dev/null
CMD ["/usr/local/nginx/sbin/nginx", "-g" "daemon off;"]
  • View the size of the completed build: 346M
[root@Server1 Docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
demo                latest              181d43b6a7dc        40 seconds ago      346MB
rhel7               latest              0a3eb3fde7fd        6 years ago         140MB

Try to streamline

  • The number of layers of compressed images, which can be executed in the same command, are integrated into the same image
FROM rhel7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
COPY NeuWings.repo /etc/yum.repos.d/NeuWings.repo
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN rm -rf /etc/yum.repos.d/rhel7.repo && rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make > /dev/null && /mnt/nginx-1.18.0/configure --prefix=/usr/local/nginx > /dev/null && yum install -y make > /dev/null && make > /dev/null && make install > /dev/null && yum clean all > /dev/null && rm -rf /mnt/nginx-1.18.0
CMD ["/usr/local/nginx/sbin/nginx", "-g" "daemon off;"]
  • View the size of the completed build: 258M
[root@Server1 Docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
demo2               latest              7f186836d1d9        14 seconds ago      258MB
demo                latest              181d43b6a7dc        8 minutes ago       346MB
rhel7               latest              0a3eb3fde7fd        6 years ago         140MB

It is known that what we need is only the binary files of Nginx. The dependencies installed in the middle of compilation and the contents generated during compilation are not used in the service

  • Using the method of multi-stage construction, create a temporary image for compilation, and copy the compiled binary file to the final image to be created
FROM rhel7 as build
COPY NeuWings.repo /etc/yum.repos.d/NeuWings.repo
ADD nginx-1.18.0.tar.gz /mnt
RUN rm -rf /etc/yum.repos.d/rhel7.repo && rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make > /dev/null && cd /mnt/nginx-1.18.0 && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx > /dev/null && yum install -y make > /dev/null && make > /dev/null && make install > /dev/null && yum clean all > /dev/null && rm -rf /mnt/nginx-1.18.0 && rm -rf /var/cache/yum

FROM rhel7
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g" "daemon off;"]
  • First, build an image and compile and install Nginx in the image
  • Build the second image in stages and copy the Nginx binary file in the first image
  • In this way, the dependency of Midway installation and compilation content are omitted, and the image size is greatly reduced
[root@Server1 Docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
demo2               latest              94f2bf6f8c66        7 seconds ago       141MB
<none>              <none>              56fe29ab9d19        8 seconds ago       258MB
demo                latest              181d43b6a7dc        24 minutes ago      346MB
rhel7               latest              0a3eb3fde7fd        6 years ago         140MB

  • Check the size of the built image: 141M, which is only 1m larger than the base image

  • If you want to continue to compress, you can only find a leaner base image

FROM nginx as base

# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ARG TIME_ZONE

RUN mkdir -p /opt/var/cache/nginx && \
    cp -a --parents /usr/lib/nginx /opt && \
    cp -a --parents /usr/share/nginx /opt && \
    cp -a --parents /var/log/nginx /opt && \
    cp -aL --parents /var/run /opt && \
    cp -a --parents /etc/nginx /opt && \
    cp -a --parents /etc/passwd /opt && \
    cp -a --parents /etc/group /opt && \
    cp -a --parents /usr/sbin/nginx /opt && \
    cp -a --parents /usr/sbin/nginx-debug /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/ld-* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libc* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libdl* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpthread* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libcrypt* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \
    cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
    cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtime

FROM gcr.io/distroless/base-debian10

COPY --from=base /opt /

EXPOSE 80 443

ENTRYPOINT ["nginx", "-g", "daemon off;"]
  • Operation process
##Get the thinnest basic image
[root@Server1 Docker]# docker load < base-debian10.tar 
de1602ca36c9: Loading layer  3.041MB/3.041MB
1d3b68b6972f: Loading layer  17.77MB/17.77MB
Loaded image: gcr.io/distroless/base-debian10:latest
##Build the required nginx image
[root@Server1 Docker]# docker build -t webserer:V1 -f Dockerfile2 .
##View build results
[root@Server1 Docker]# docker images
REPOSITORY                        TAG                 IMAGE ID            CREATED             SIZE
webserer                          V1                  059742ab983d        6 seconds ago       31.9MB
<none>                            <none>              2cb570a37c5b        8 seconds ago       146MB
nginx                             latest              62d49f9bab67        13 days ago         133MB
gcr.io/distroless/base-debian10   latest              d48fcdd54946        51 years ago        19.2MB
  • View the size of the completed build: 31.9M

Keywords: Docker

Added by Fruct0se on Fri, 18 Feb 2022 03:27:54 +0200