Linux企业运维——Docker镜像(二)

本文详细介绍了Docker镜像的分层结构及其优势,包括如何通过常规方法和Dockerfile构建镜像。重点讲解了Dockerfile的常用指令,并提供了Dockerfile示例。此外,还探讨了镜像的封装技巧,如选择精简基础镜像、减少层数和优化网络请求,以及多阶段构建进行优化的方法。最后,通过实例展示了如何封装和优化RHEL7+nginx镜像,实现镜像的小型化和高效运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Docker镜像的分层结构

镜像的分层结构:
在这里插入图片描述

  • 共享宿主机的kernel
  • base镜像提供的是最小的Linux发行版
  • 同一docker主机支持运行多种Linux发行版
  • 采用分层结构的最大好处是:共享资源

在这里插入图片描述

  • Copy-on-Write 可写容器层
  • 容器层以下所有镜像层都是只读的
  • docker从上往下依次查找文件
  • 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
  • 一个镜像最多127层

二、Docker镜像的构建

镜像的分层结构:base image提供了根文件系统,所有容器数据都分类存放在/var/lib/docker目录中,可以共享资源,减少网络带宽资源占用

构建方法一(常规)

  • docker commit 构建新镜像三部曲

    • 运行容器
    • 修改容器
    • 将容器保存为新的镜像
  • 缺点:
    效率低、可重复性弱、容易出错
    使用者无法对镜像进行审计,存在安全隐患

这里我们先在server1上拉取busybox镜像
然后进行构建新镜像三部曲
在这里插入图片描述

#运行容器
docker run -it --name demo busybox
#修改容器 (以下命令在容器内运行)
echo helloworld > testfile
#将容器保存为新的镜像
docker commit  demo demo:v1
#查看镜像
docker images demo:v1

将demo容器提交保存为demo:v1新的镜像后,查看比较busybox和demo:v1可以看到demo:v1是在busybox镜像的基础上新加了一层
在这里插入图片描述

构建方法二(Dockerfile)

创建一个Dockerfile
此处需要注意:

  • dockerfile有审计功能,每新加一层镜像都会有动作审计说明
  • dockerfile不能放在根下,否则会把根下所有数据发送给docker引擎

(1)创建docker目录,在目录中建立编辑dockerfile
在这里插入图片描述
(2)使用dockerfile创建一个demo:v2新的镜像

在这里插入图片描述
(3)新的镜像已经建立为demo:v2,查看比较busybox和demo:v2可以看到demo:v2是在busybox镜像的基础上新加了一层
在这里插入图片描述

三、Dockerfile详解

dockerfile常用指令

  • FROM
    指定base镜像,如果本地不存在会从远程仓库下载。

  • MAINTAINER
    设置镜像的作者,比如用户邮箱等。

  • COPY
    把文件从build context复制到镜像
    支持两种形式:COPY src dest 和 COPY [“src”, “dest”]
    src必须指定build context中的文件或目录

  • ADD
    用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest,也可以自动下载URL并拷贝到镜像:
    ADD html.tar /var/www
    ADD http://ip/html.tar /var/www

  • ENV
    设置环境变量,变量可以被后续的指令使用:
    ENV HOSTNAME sevrer1.example.com

  • EXPOSE
    如果容器中运行应用服务,可以把服务端口暴露出去:
    EXPOSE 80

  • VOLUME
    申明数据卷,通常指定的是应用的数据挂在点:
    VOLUME ["/var/www/html"]

  • WORKDIR
    为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建。

  • RUN
    在容器中运行命令并创建新的镜像层,常用于安装软件包:
    RUN yum install -y vim

  • CMD 与 ENTRYPOINT
    这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。
    docker run后面的参数可以传递给ENTRYPOINT指令当作参数。
    Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。

Shell和exec格式的区别

Shell格式底层会调用/bin/sh -c来执行命令,可以解析变量,而下面的exec格式不会:

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

shell需要改写成以下形式:

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

Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外参数可以在容器启动时动态替换。在shell格式时ENTRYPOINT会忽略任何CMD或docker run提供的参数。

cat Dockerfile 
///
FROM busybox
ENTRYPOINT ["/bin/echo", "hello"]
CMD ["world"]

下面可以看出在运行容器时的区别:
官方推荐使用exec格式书写

///Exec
docker run --rm busybox:v1
hello world
///Sell
docker run --rm busybox:v1 linux
hello linux

四、镜像的封装及优化

  • 选择最精简的基础镜像
  • 减少镜像的层数
  • 清理镜像构建的中间产物
  • 注意优化网络请求
  • 尽量去用构建缓存
  • 使用多阶段构建镜像

Docker封装rhel7+nginx镜像实例

(1)删除之前建立的所有demo容器,真实主机下载rhel7和nginx的镜像源压缩包并发送给server1

docker rmi `docker images | grep ^demo | awk '{print $3}'`   #删除之前所有的demo容器
///真机中
scp rhel7.tar nginx-1.20.1.tar server1:

(2)准备软件仓库文件

cp /etc/yum.repos.d/dvd.repo .  #将rhel7的仓库拷贝到当前doker目录下 

(3)创建交互式容器,用于测试镜像环境是否损坏
在这里插入图片描述
(4)将nginx和仓库文件拷贝到容器中,并编辑Dockerfile文件,创建新的镜像
在这里插入图片描述在这里插入图片描述

docker built -t rhel7:v1   #创建镜像

(5)使用rhel7镜像创建一个容器demo

在这里插入图片描述
docker inspect demo查看容器信息,看到分配的ip和在真实主机上挂载的路径
在这里插入图片描述
(6)在真实主机挂载路径上创建默认发布文件index.html,curl进行访问,可以获取到发布内容
在这里插入图片描述

封装后镜像的优化

封装好的镜像就可以正常运行了,但是查看镜像历史及列表,会发现该镜像的空间占用较大,不符合轻量化的原则,因此需要进行优化
在这里插入图片描述
1.减少镜像层数,减少中间产物
重新编辑Dockerfile
vim Dockerfile

在这里插入图片描述

创建镜像v2,可以看到镜像大小减少了
在这里插入图片描述
2.使用多阶段构建镜像进行优化
再次编辑Dockerfile:
vim Dockerfile
在这里插入图片描述

创建镜像v3,可以看到镜像更小了

在这里插入图片描述

最终优化需要下载base-debian10.tar ,下载并导入
在这里插入图片描述

vim Dockerfile
////
FROM nginx as base
ARG Asia/Shanghai

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

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

docker build -t rhel7:v4     #创建新的rhel7镜像
docker images rhel7    #查看镜像大小发现笔之前小了很多

在这里插入图片描述

优化为如此小之后依然可以运行一个容器,通过curl看到nginx发布的页面!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值