天天看点

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

Docker镜像

  • 一、Docker镜像的分层结构
  • 二、Docker镜像的构建
    • 构建方法一(常规)
    • 构建方法二(Dockerfile)
  • 三、Dockerfile详解
  • 四、镜像的封装及优化
    • Docker封装rhel7+nginx镜像实例
    • 封装后镜像的优化

一、Docker镜像的分层结构

镜像的分层结构:

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化
  • 共享宿主机的kernel
  • base镜像提供的是最小的Linux发行版
  • 同一docker主机支持运行多种Linux发行版
  • 采用分层结构的最大好处是:共享资源
Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化
  • Copy-on-Write 可写容器层
  • 容器层以下所有镜像层都是只读的
  • docker从上往下依次查找文件
  • 容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
  • 一个镜像最多127层

二、Docker镜像的构建

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

构建方法一(常规)

  • docker commit 构建新镜像三部曲
    • 运行容器
    • 修改容器
    • 将容器保存为新的镜像
  • 缺点:

    效率低、可重复性弱、容易出错

    使用者无法对镜像进行审计,存在安全隐患

这里我们先在server1上拉取busybox镜像

然后进行构建新镜像三部曲

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化
#运行容器
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镜像的基础上新加了一层

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

构建方法二(Dockerfile)

创建一个Dockerfile

此处需要注意:

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

(1)创建docker目录,在目录中建立编辑dockerfile

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

(2)使用dockerfile创建一个demo:v2新的镜像

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

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

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

三、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)准备软件仓库文件

(3)创建交互式容器,用于测试镜像环境是否损坏

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

(4)将nginx和仓库文件拷贝到容器中,并编辑Dockerfile文件,创建新的镜像

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化
Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

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

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

docker inspect demo查看容器信息,看到分配的ip和在真实主机上挂载的路径

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

(6)在真实主机挂载路径上创建默认发布文件index.html,curl进行访问,可以获取到发布内容

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

封装后镜像的优化

封装好的镜像就可以正常运行了,但是查看镜像历史及列表,会发现该镜像的空间占用较大,不符合轻量化的原则,因此需要进行优化

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

1.减少镜像层数,减少中间产物

重新编辑Dockerfile

vim Dockerfile

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

创建镜像v2,可以看到镜像大小减少了

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

2.使用多阶段构建镜像进行优化

再次编辑Dockerfile:

vim Dockerfile

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

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

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

最终优化需要下载base-debian10.tar ,下载并导入

Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化
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    #查看镜像大小发现笔之前小了很多
           
Linux企业运维——Docker镜像(二)一、Docker镜像的分层结构二、Docker镜像的构建三、Dockerfile详解四、镜像的封装及优化

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