Docker镜像里到底有啥东西?

c582b1966d01cffae484951f27092c13.png

Docker 容器的本质是一个特殊的进程,而 Docker 镜像则是容器运行所需的文件系统。可以说Docker容器是Docker镜像的实例,镜像是容器的模板。容器是在镜像的基础上运行的,当我们修改原镜像时,并不会对正在运行的容器产生影响。

那么Docker镜像里面到底包含哪些东西那?要想知道Docker镜像里面含有什么东西,我们需要先看看Docker镜像是怎么来的,最常见的构建Docker镜像的方式是通过编写Dockerfile。

FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
  • 如上是一个简单的Dockerfile文件,其中FROM指定基础镜像为 nginx

  • RUN命令执行shell命令向index.html 文件中写入Hello, Docker!

编写好Dockerfile后,我们可以执行命令:docker build -t nginx:v1 . 来构建镜像:

C02D9251MD6R :: ~/Downloads » docker build -t nginx:v1 .                    1 ↵
[+] Building 9.3s (6/6) FINISHED
...
 => [internal] load metadata for docker.io/library/nginx:latest            3.8s
 => [1/2] FROM docker.io/library/nginx@sha256:b8f2383a95879e1ae064940d9a2  4.9s
...
 => [2/2] RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/inde  0.4s
 => exporting to image                                                     0.0s
 => => exporting layers                                                    0.0s
 => => writing image sha256:e8b2a9dd1015eb395f7f18d3b4502050d9c4ab919d253  0.0s
 => => naming to docker.io/library/nginx:v1                                0.0s

如上可知,第一步是下载基础镜像nginx,第二步是执行echo命令修改ngnix镜像里面的index.html文件的内容

执行完毕build命令后,我们的docker镜像nginx:v1就在本地构建好嘞,我们可使用docker images查看:

C02D9251MD6R :: ~/Downloads » docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
nginx         v1        e8b2a9dd1015   9 minutes ago   142MB
httpd         latest    6e794a483258   5 days ago      145MB
nginx         latest    a99a39d070bf   12 days ago     142MB

如上可知 nginx v1的大小只有142MB,因为我们镜像里面只是修改了nginx镜像里面的内容,本身并没有新增任何大的东西,所以我们需要看看nginx镜像里面有什么,那我们可看看构建ngnix的Dockerfile(https://github.com/nginxinc/docker-nginx/blob/5ce65c3efd395ee2d82d32670f233140e92dba99/mainline/debian/Dockerfile)里面有什么:

#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "update.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#
FROM debian:bullseye-slim

LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"

ENV NGINX_VERSION   1.23.3
ENV NJS_VERSION     0.7.9
ENV PKG_RELEASE     1~bullseye

RUN set -x \
# create nginx user/group first, to be consistent throughout docker variants
    && addgroup --system --gid 101 nginx \
    && adduser --system --disabled-login --ingroup nginx --no-create-home --home /nonexistent --gecos "nginx user" --shell /bin/false --uid 101 nginx \
    && apt-get update \
    && apt-get install --no-install-recommends --no-install-suggests -y gnupg1 ca-certificates \
    && \
    NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \
    found=''; \
    for server in \
        hkp://keyserver.ubuntu.com:80 \
        pgp.mit.edu \
    ; do \
        echo "Fetching GPG key $NGINX_GPGKEY from $server"; \
        apt-key adv --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \
    done; \
    test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \
    apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \
    && dpkgArch="$(dpkg --print-architecture)" \
    && nginxPackages=" \
        nginx=${NGINX_VERSION}-${PKG_RELEASE} \
        nginx-module-xslt=${NGINX_VERSION}-${PKG_RELEASE} \
        nginx-module-geoip=${NGINX_VERSION}-${PKG_RELEASE} \
        nginx-module-image-filter=${NGINX_VERSION}-${PKG_RELEASE} \
        nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE} \
    " \
    && case "$dpkgArch" in \
        amd64|arm64) \
# arches officialy built by upstream
            echo "deb https://nginx.org/packages/mainline/debian/ bullseye nginx" >> /etc/apt/sources.list.d/nginx.list \
            && apt-get update \
            ;; \
        *) \
# we're on an architecture upstream doesn't officially build for
# let's build binaries from the published source packages
            echo "deb-src https://nginx.org/packages/mainline/debian/ bullseye nginx" >> /etc/apt/sources.list.d/nginx.list \
            \
# new directory for storing sources and .deb files
            && tempDir="$(mktemp -d)" \
            && chmod 777 "$tempDir" \
# (777 to ensure APT's "_apt" user can access it too)
            \
# save list of currently-installed packages so build dependencies can be cleanly removed later
            && savedAptMark="$(apt-mark showmanual)" \
            \
# build .deb files from upstream's source packages (which are verified by apt-get)
            && apt-get update \
            && apt-get build-dep -y $nginxPackages \
            && ( \
                cd "$tempDir" \
                && DEB_BUILD_OPTIONS="nocheck parallel=$(nproc)" \
                    apt-get source --compile $nginxPackages \
            ) \
# we don't remove APT lists here because they get re-downloaded and removed later
            \
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
# (which is done after we install the built packages so we don't have to redownload any overlapping dependencies)
            && apt-mark showmanual | xargs apt-mark auto > /dev/null \
            && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; } \
            \
# create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be)
            && ls -lAFh "$tempDir" \
            && ( cd "$tempDir" && dpkg-scanpackages . > Packages ) \
            && grep '^Package: ' "$tempDir/Packages" \
            && echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list \
# work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes")
#   Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied)
#   ...
#   E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages  Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied)
            && apt-get -o Acquire::GzipIndexes=false update \
            ;; \
    esac \
    \
    && apt-get install --no-install-recommends --no-install-suggests -y \
                        $nginxPackages \
                        gettext-base \
                        curl \
    && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \
    \
# if we have leftovers from building, let's purge them (including extra, unnecessary build deps)
    && if [ -n "$tempDir" ]; then \
        apt-get purge -y --auto-remove \
        && rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \
    fi \
# forward request and error logs to docker log collector
    && ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log \
# create a docker-entrypoint.d directory
    && mkdir /docker-entrypoint.d

COPY docker-entrypoint.sh /
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
ENTRYPOINT ["/docker-entrypoint.sh"]

EXPOSE 80

STOPSIGNAL SIGQUIT

CMD ["nginx", "-g", "daemon off;"]

如上可知nginx本身的构建基于基础镜像debian:bullseye-slim,nginx在基础镜像基础上大概新增了60M的内容,主要是拷贝的文件、创建临时目录、已经安装一些软件。

下面我么看看基础镜像debian:bullseye-slim(https://github.com/debuerreotype/docker-debian-artifacts/blob/64b13cf5860ac15c1d909abd7239516db9748fea/bullseye/slim/Dockerfile),其是比较常用的基础镜像,其Dockerfile如下:

FROM scratch
ADD rootfs.tar.xz /
CMD ["bash"]
  • scratch是官方提供一个空镜像,其用来构建基础镜像比如(debian,busybox)或者体积超级小的镜像时候特别有用。

  • rootfs.tar.xz是用户空间的文件系统。

这里我们又必须要说下,Linux操作系统由内核空间和用户空间组成。Linux刚启动时会加载bootfs文件系统,之后bootfs会被卸载掉。用户空间的文件系统是rootfs,包含我们熟悉的 /dev、/proc、/bin等目录。对于基础镜像来说,底层复用用Host的kernel,镜像本身只需要包含rootfs就行了。而对于一个精简的OS, rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了。

所以Docker镜像里面其实并不包含linux内核文件,而仅仅是包含用户空间的文件系统rootfs,另外Docker镜像里面还包含开发者自己的应用文件,仅此而已。最后所有的Docker容器运行时是复用主机操作系统的内核的,但是每个Docker容器有自己独立的用户空间的文件系统。

戳下面阅读

👇

我的第三本书    我的第二本书    我的第一本书

程序员的办公神器    ForkJoinPool    K8s网络模型

  我的视频号  

点亮再看哦👇

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Docker 镜像容器化的基础,它们是由文件层组成的,并且包含了运行一个特定应用所需的软件和配置。Docker Hub 是一个流行的官方和社区共享的 Docker 镜像仓库,其中存储了大量的预构建镜像,这些镜像Docker Inc. 或者开源贡献者维护,可以用于快速启动基于各种软件的基础环境。 除了 Docker Hub,还有其他一些地方可以找到 Docker 镜像: 1. **私有仓库**:企业和组织可能会使用自己的私有Docker Registry,如 Docker Trusted Registry (DTR) 或 Docker Cloud,来存储内部使用的镜像,以保护敏感信息。 2. **GitHub**: 许多开发者会在 GitHub 上托管 Dockerfile,允许用户通过 `git clone` 和 `docker build` 来构建自己的镜像。 3. **Quay.io**: Quay.io 也是一个公共镜像仓库,类似于 Docker Hub,但更加侧重于开发者和企业的使用。 4. **GitLab Container Registry**: GitLab 提供的镜像存储服务,常用于那些已经使用 GitLab 作为代码管理平台的团队。 5. **Google Cloud Marketplace**: Google 提供的云市场中也有许多官方和第三方的 Docker 镜像。 6. **AWS Elastic Container Registry (ECR)**: Amazon Web Services 的官方镜像仓库,适用于 AWS 用户。 7. **Azure Container Registry (ACR)**: Microsoft Azure 的镜像存储服务。 每个镜像都是从一个基础镜像(比如 Ubuntu, Alpine, 或者 CentOS)开始,然后通过 Dockerfile 增加或修改软件和服务,形成特定功能的镜像。所以,虽然 Docker Hub 是最常见的来源,但镜像的多样性意味着它们可以在多个平台上获取。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值