内容简介: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`》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
产品经理修炼之道
费杰 / 机械工业出版社华章公司 / 2012-7-30 / 59.00元
本书由资深产品经理、中国最大的产品经理沙龙Pmcaff创始人费杰亲自执笔,微软、腾讯、百度、新浪、搜狐、奇虎、阿里云、Evernote等国内外20余家大型互联网企业资深产品经理和技术专家联袂推荐。用系统化的方法论和丰富的实战案例解读了优秀产品经理所必须修炼的产品规划能力、产品设计能力、产品执行能力,以及思考、分析和解决问题的能力和方法,旨在为互联网产品经理打造核心竞争力提供实践指导。 全书一......一起来看看 《产品经理修炼之道》 这本书的介绍吧!