Docker镜像里到底有啥东西?

2023-05-16

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网络模型

  我的视频号  

点亮再看哦👇

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Docker镜像里到底有啥东西? 的相关文章

随机推荐

  • 树莓派+Ubuntu16.04 MATE+ROS(kinetic)的安装

    树莓派 43 Ubuntu16 04 MATE 43 ROS xff08 kinetic xff09 的安装 零 准备工作 1 树莓派板子 2 电源 xff1a 3A以上 xff0c 供电要充足 xff0c 否则无法启动或影响使用 3 显示
  • canal

    目录 搭建canal测试canal 监控MySQL的binlog的工具 搭建canal 1 开启mysql binlog cp usr share mysql my medium cnf etc my cnf 修改my cnf vim et
  • docker 镜像注册【图文教程】

    docker镜像官网 xff1a https hub docker com 进行登录注册 账号 只能使用4到30个字母和数字 那就名字拼音吧 邮箱 正确的邮箱即可 后续会验证 xff0c 务必真实 密码 密码至少为9个字符 第一个勾选框 偶
  • 使用gazebo实现turtlebot入门级开发

    实验室准备新进两台Turtlebot2 xff0c 为了更快上手 xff0c 便提前开始熟悉一下Turtlebot xff0c 通果查阅相关资料 xff0c 我写了一个demo程序 xff0c 并在gazebo模拟环境下进行了测试 该dem
  • 手写智能指针(类)

    基础知识 xff1a 智能指针的设计与实现 1 智能指针类将一个计数器与类指向的对象相关联 xff0c 引用计数跟踪该类有多少个对象共享同一指针 2 每次创建类的新对象时 xff0c 初始化指针并将引用计数置为1 xff1b 3 当对象作为
  • 求职历程

    前言 xff1a 个人求职有大部分的时间花在了城市与企业性质的纠结上 首先是个人打算 xff0c 因研究生课题偏嵌入式相关 xff0c 所以给自己定下的目标是找嵌入式相关的工作 xff0c 而弱化了互联网求职的刷题关和计算机基础关 而在求职
  • 剑指 Offer 57 - II. 和为s的连续正数序列

    剑指 Offer 57 II 和为s的连续正数序列 难度 简单 输入一个正整数 target xff0c 输出所有和为 target 的连续正整数序列 xff08 至少含有两个数 xff09 序列内的数字由小到大排列 xff0c 不同序列按
  • 使用层次遍历重建二叉树并遍历

    58同城的一道题 xff0c 蛮有意思的 利用层次遍历后的数组 xff0c 进行二叉树的重建 数值 1代表NULL 解题思路 xff1a 那么我们依然使用队列 xff0c 进行层次遍历 xff0c 进行重建 xff0c 这边有的问题是当示例
  • C++秋招知识点总结

    先介绍下本人的情况 xff0c 本人研究生双非院校 xff0c 本科也是普通二本 xff0c 也无实习无项目非科班出生 刷了将近半年的题和自学了相关知识点 xff0c 最终拿到华为 海康 大华 同花顺 深信服 CVTE 紫光展锐offer
  • MPU6050软件姿态解算

    我是勤劳的搬运工 转自 http blog sina com cn s blog c5a00db10102wd7d html http mini eastday com mobile 180306210610472 html 使用MPU60
  • AD布线的线宽

    线宽关系图 xff1a 覆铜厚度与电流的关系 xff1a
  • AD16 Unknown Pin 和Failed to add class member 问题

    转载 xff1a http www 51hei com bbs dpj 39227 1 html 相信很多人在使用DXP 和AD 的时候 xff0c 都遇到过Unknown Pin 和Failed to add classmember 的问
  • 加速度计求二次积分

    我是勤劳的搬运工 xff1a https blog csdn net u011006622 article details 56286833 摘要 此文档描述并使用MMA7260QT三轴加速计和低功耗的9S08QG8八位单片机实现求解位置的
  • 卡尔曼滤波算法的深入理解

    以前对于这个算法只会调用 xff0c 并没有深入的理解 现在碰到一个项目 xff0c 没办法只能硬着头皮去理解了 网上看了很多资料 xff0c 感觉写的也一般般 xff0c 现在我讲自己的理解 卡尔曼滤波算法的核心是动态调整权值 用过互补滤
  • win10下删除ubuntu及其引导项

    转载 xff1a https blog csdn net g1027785756 article details 82999451 本文主要针对UEFI和GPT双系统下Ubuntu EFI分区及启动项的删除 1 查看电脑分区信息 电脑分区信
  • VSLAM综述

    传统SLAM算法及相关成果的介绍 根据传感器的分类可将VSLAM大致分为单目SLAM 双目SLAM xff08 立体 xff09 和RGB D SLAM 有根据对图像信息不同的处理方式可分为直接法SLAM和基于特征SLAM 直接法主要有直接
  • 计算机网络-网络分层模型及基本网络协议

    1 网络分层模型 1 1 分层模型图示 1 2 七层模型及各层含义 1 物理层 xff08 Physical Layer xff09 激活 维持 关闭通信端点之间的机械特性 电气特性 功能特性以及过程特性 该层为上层协议提供了一个传输数据的
  • 多进程

    39 39 39 生活中 xff0c 你可能一边听歌 xff0c 一边写作业 xff1b 一边上网 xff0c 一边吃饭 这些都是生活中的多任务场景 电脑也可以执行多任务 xff0c 比如你可以同时打开浏览器上网 xff0c 听音乐 xff
  • SpringSecurity的基础操作,登录认证,授权认证等

    文章目录 SpringSecurity1 SpringSecurity简介2 第一个SpringSecurity程序3 UserDetailsService接口4 PasswordEncoder接口5 自定义登录逻辑6 自定义登录页面7 自
  • Docker镜像里到底有啥东西?

    Docker 容器的本质是一个特殊的进程 xff0c 而 Docker 镜像则是容器运行所需的文件系统 可以说Docker容器是Docker镜像的实例 xff0c 镜像是容器的模板 容器是在镜像的基础上运行的 xff0c 当我们修改原镜像时