内容简介:If you want to understand a Docker image, there is no more useful tool than theLet’s see what this command does, what it can teach us about the construction of Docker images, and some examples of why it’s so useful.Consider the following Docker image:
If you want to understand a Docker image, there is no more useful tool than the docker history
command.
Whether it’s telling you why your image is so large, or helping you understand how a base image was constructed, the history
command will let you peer into the innards of any image, allowing you to see the good, the bad, and the ugly.
Let’s see what this command does, what it can teach us about the construction of Docker images, and some examples of why it’s so useful.
The construction of a Docker image
Consider the following Docker image:
$ docker image ls mysteryimage REPOSITORY TAG IMAGE ID SIZE mysteryimage latest 24e6dd67bf8a 165MB
Given an image, we might have some questions:
- What does it do?
- What will happen when I run it?
- How was it created?
The docker image history
command, or it’s older synonym docker history
, can help answer all these questions.
$ docker image history mysteryimage IMAGE CREATED CREATED BY SIZE 24e6dd67 2 mins #(nop) ENTRYPOINT ["python" "exa… 0B 59102aef 2 mins #(nop) COPY file:cc6452cd5813b9d2… 0B 9d84edf3 7 weeks #(nop) CMD ["python3"] 0B <missing> 7 weeks set -ex; savedAptMark="$(apt-ma… 8MB <missing> 7 weeks #(nop) ENV PYTHON_GET_PIP_SHA256… 0B <missing> 7 weeks #(nop) ENV PYTHON_GET_PIP_URL=ht… 0B <missing> 7 weeks #(nop) ENV PYTHON_PIP_VERSION=20… 0B <missing> 7 weeks cd /usr/local/bin && ln -s idle3… 32B <missing> 7 weeks set -ex && savedAptMark="$(apt-… 80MB <missing> 7 weeks #(nop) ENV PYTHON_VERSION=3.8.3 0B <missing> 7 weeks #(nop) ENV GPG_KEY=E3FF2839C048B… 0B <missing> 7 weeks apt-get update && apt-get install… 7MB <missing> 7 weeks #(nop) ENV LANG=C.UTF-8 0B <missing> 7 weeks #(nop) ENV PATH=/usr/local/bin:/… 0B <missing> 7 weeks #(nop) CMD ["bash"] 0B <missing> 7 weeks #(nop) ADD file:4d35f6c8bbbe6801c… 69MB
Docker images are constructed in layers, each layer corresponding to a first approximation to a line in a Dockerfile
.
The history
command shows these layers, and the commands used to create them.
So what we have here is more or less the equivalent of the Dockerfile
that constructed the image.
And we can use this to answer a number of questions.
What is this Docker image going to run?
To figure out what the image will run, we just need to find the topmost ENTRYPOINT
or CMD
.
We can use the --no-trunc
argument to show the full, untruncated commands:
$ docker image history mysteryimage --no-trunc | grep ENTRYPOINT sha256:24e6dd67bf8a 4 minutes ago /bin/sh -c #(nop) ENTRYPOINT ["python" "example.py"]
What was in the base image?
We can see what went into constructing the base image: you can differentiate the base image from the current image by the creation time for each layer. The base image was apparently created 7 weeks ago.
You can also see the ID of the base image, in case you want to docker run
it.
What commands made the image size larger?
Notice that the output above has a SIZE column, showing you the size of each layer.
That means you can tell which specific steps in the Dockerfile
contributed the most to the image size.
In this example, 80MB came from one particular step:
$ docker image history mysteryimage --no-trunc | grep 80MB <missing> 7 weeks ago /bin/sh -c set -ex && savedAptMark="$(apt-mark showmanual)" && apt-get update && apt-get install -y --no-install-recommends dpkg-dev gcc libbluetooth-dev libbz2-dev libc6-dev libexpat1-dev libffi-dev libgdbm-dev liblzma-dev libncursesw5-dev libreadline-dev libsqlite3-dev libssl-dev make tk-dev uuid-dev wget xz-utils zlib1g-dev $(command -v gpg > /dev/null || echo 'gnupg dirmngr') && wget -O python.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" && wget -O python.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" && export GNUPGHOME="$(mktemp -d)" && gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$GPG_KEY" && gpg --batch --verify python.tar.xz.asc python.tar.xz && { command -v gpgconf > /dev/null && gpgconf --kill all || :; } && rm -rf "$GNUPGHOME" python.tar.xz.asc && mkdir -p /usr/src/python && tar -xJC /usr/src/python --strip-components=1 -f python.tar.xz && rm python.tar.xz && cd /usr/src/python && gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" && ./configure --build="$gnuArch" --enable-loadable-sqlite-extensions --enable-optimizations --enable-option-checking=fatal --enable-shared --with-system-expat --with-system-ffi --without-ensurepip && make -j "$(nproc)" LDFLAGS="-Wl,--strip-all" && make install && ldconfig && apt-mark auto '.*' > /dev/null && apt-mark manual $savedAptMark && find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec ldd '{}' ';' | awk '/=>/ { print $(NF-1) }' | sort -u | xargs -r dpkg-query --search | cut -d: -f1 | sort -u | xargs -r apt-mark manual && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false && rm -rf /var/lib/apt/lists/* && find /usr/local -depth \( \( -type d -a \( -name test -o -name tests -o -name idle_test \) \) -o \( -type f -a \( -name '*.pyc' -o -name '*.pyo' \) \) \) -exec rm -rf '{}' + && rm -rf /usr/src/python && python3 --version 80MB
Apparently this step compiles Python from source.
Not just the Dockerfile
The commands reported by docker image history
are even more useful than the original Dockerfile
insofar as they also include the values of build arguments in any subsequent RUN
commands.
This can be useful for security auditing.
For example, you might discover the image made the mistake of using the ARG
command for build secrets, thus unintentionally leaking credentials:
$ docker pull itamarst/verysecure ... $ docker image history itamarst/verysecure IMAGE CREATED BY 0b51ddadfcd |1 ANOTHER_SECRET=oscillation-overthruster /… <missing> /bin/sh -c #(nop) WORKDIR /tmp <missing> /bin/sh -c #(nop) ARG ANOTHER_SECRET ...
There are of course other, more secure ways to use build secrets in Docker .
Or you might discover the name of an internal server in a commercially-built Docker image, and the fact they’re still using FTP:
$ docker history --no-trunc image_name_elided | grep ftp <missing> 4 weeks ago |2 FTP_PATH=ftp://kits-ftp/kits/unreleased_ftp/PRODUCTS//PRODUCT-dockerubuntux64.tar.gz ....
The primary use case: figuring out why your image is too large
While docker history
is useful in understanding how images are built, and occasionally for getting a glimpse into an insecure setup, the thing it’s most useful for is figuring out why an image is too large.
The first thing you should do when you have an overly large image is use docker image history
to see which layers are contributing the most to image size.
Often that’ll be enough to tell you exactly what’s going on.
以上所述就是小编给大家介绍的《A tableau of crimes and misfortunes: the ever-useful `docker history`》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python Cookbook
Alex Martelli、Anna Ravenscroft、David Ascher / 高铁军 / 人民邮电出版社 / 2010-5-1 / 99.00元
本书介绍了Python应用在各个领域中的一些使用技巧和方法,从最基本的字符、文件序列、字典和排序,到进阶的面向对象编程、数据库和数据持久化、 XML处理和Web编程,再到比较高级和抽象的描述符、装饰器、元类、迭代器和生成器,均有涉及。书中还介绍了一些第三方包和库的使用,包括 Twisted、GIL、PyWin32等。本书覆盖了Python应用中的很多常见问题,并提出了通用的解决方案。书中的代码和方......一起来看看 《Python Cookbook》 这本书的介绍吧!