docker镜像介绍_Dockerfile详解、构建nginx镜像、镜像优化

一、镜像的分层结构

1、共享宿主机的kernel
2、base镜像提供的是最小的Linux发行版
3、同一docker主机支持运行多种Linux发行版
4、采用分层结构的最大好处是:共享资源
在这里插入图片描述
5、Copy-on-Write 容器层可写
6、容器层以下所有镜像层都是只读的
7、docker从上往下依次查找文件
8、容器层保存镜像变化的部分,并不会对镜像本身进行任何修改
9、一个镜像最多127层
在这里插入图片描述

二、镜像的构建

1、docker commit 构建

用docker commit 构建镜像分为三步:
(1)运行容器
(2)修改容器
(3)将容器保存为新的镜像
-it:交互方式,Ctrl+D:退出容器,Ctrl+p+q:退出时让容器在后台运行

docker load -i busybox.tar  ##导入镜像
docker run -it --name test busybox:latest  ##以交互方式运行容器

echo helloworld > testfile  ##在容器中执行命令

docker commit test test:v1  ##容器保存为新的镜像
docker images  ##查看镜像

在这里插入图片描述
在这里插入图片描述

2、Dockerfile 构建

(1)创建一个Dockerfile

mkdir docker
vim docker/Dockerfile

FROM busybox
RUN echo westos > testfile

(2)构建镜像

docker build -t test:v2 /root/docker/
docker images

在这里插入图片描述

3、查看镜像的分层结构

  • 镜像都为三层结构,用docker commit创建的镜像容器层不会显示具体的操作命令,用Dockerfile创建的镜像容器会显示具体的操作命令
  • 删除镜像实质是删除了容器层,再次创建只是添加了容器层
docker history test:v2

在这里插入图片描述

docker history test:v2
docker rmi test:v2
docker history busybox:latest

在这里插入图片描述

三、Dockerfile详解

1、Dockerfile常用指令

  • FROM
    指定base镜像,如果本地不存在会从远程仓库下载
  • MAINTAINER
    设置镜像的作者,比如用户邮箱等
  • COPY
    把文件从建立Dockerfile的目录复制到镜像
    支持两种形式:COPY src destCOPY ["src", "dest"]
    src必须指定建立Dockerfile的目录中的文件或目录
echo hello linux > index.html
vim Dockerfile

FROM busybox
RUN echo westos > testfile  ##RUN后面可以跟shell语句
RUN echo hello word > testfile1
COPY index.html /  ##COPY复制当前目录的index.html到容器的根目录下

docker build -t test:v3 /root/docker/  ##构建容器
docker run -it --name test test:v3  ##运行容器

在这里插入图片描述

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

FROM busybox
RUN echo westos > testfile
RUN echo hello word > testfile1
COPY index.html /
ADD nginx-1.20.1.tar.gz /

docker build -t test:v4 /root/docker/
docker run -it --rm test:v4  ##`--rm`表示运行完容器后,不会保存容器

在这里插入图片描述
使用-rm后,查看docker ps -a时不会看到新建的容器
在这里插入图片描述

  • ENV
    设置环境变量,变量可以被后续的指令使用:
    ENV HOSTNAME sevrer1.example.com
  • EXPOSE
    如果容器中运行应用服务,可以把服务端口暴露出去:
    EXPOSE 80
  • VOLUME
    申明数据卷,通常指定的是应用的数据挂载点:
    VOLUME ["/var/www/html"]
vim Dokerfile

FROM busybox
RUN echo westos > testfile
RUN echo hello word > testfile1
COPY index.html /
ADD nginx-1.20.1.tar.gz /
ENV HOSTNAME server1  ##重新定义变量HOSTNAME为server1
EXPOSE 80  ##设定端口为80
VOLUME ["/data"]  ##设定挂载目录为/data

docker build -t test:v5 /root/docker/
docker run -it --name demo test:v5

在这里插入图片描述

查看data是否挂载成功:

docker inspect demo ##查看demo容器的详细信息

在这里插入图片描述
进入上图的路径查看:

cd /var/lib/docker/volumes/85d2dc62ee308813d1840e2b1807e2f7f2a1f13370d986c6efb93e28e5011dc4/_data

在这里插入图片描述
再进入容器查看:

docker start demo  ##启动容器
docker attach demo  ##进入容器

在这里插入图片描述

  • WORKDIR
    为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建
  • RUN
    在容器中运行命令并创建新的镜像层,常用于安装软件包:
    RUN yum install -y vim
  • CMD 与 ENTRYPOINT
    这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。
    docker run后面的参数可以传递给ENTRYPOINT指令当作参数。
    Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。

CMD的使用:

vim Dockerfile

FROM busybox
RUN echo westos > testfile
RUN echo hello word > testfile1
COPY index.html /
ADD nginx-1.20.1.tar.gz /
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
WORKDIR /data  ##设定工作目录为/data
CMD echo "hello $HOSTNAME"  ##运行命令输出 hello world

docker build -t test:v6 /root/docker/
docker run -it --rm test:v6

在这里插入图片描述

要使用Exec格式时,需修改CMD为以下形式:

vim Dockerfile

CMD ["/bin/sh", "-c", "echo hello $HOSTNAME"]

docker build -t test:v7 /root/docker
docker run -it --rm test:v7

在这里插入图片描述
ENTRYPOINT的使用:

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

vim Dockerfile

FROM busybox
RUN echo westos > testfile
RUN echo hello word > testfile1
COPY index.html /
ADD nginx-1.20.1.tar.gz /
ENV HOSTNAME server1
EXPOSE 80
VOLUME ["/data"]
WORKDIR /data  ##设定工作目录为/data
ENTRYPOINT ["/bin/echo", "hello"]
CMD ["world"]

docker build -t test:v8 /root/docker
docker run -it --rm test:v8
docker run -it --rm test:v8 linux

在这里插入图片描述

2、快捷删除镜像

docker rmi `docker images | grep ^test |awk '{print $3}'`

在这里插入图片描述

四、构建nginx镜像

  • 提前准备好rhel7.tarnginx-1.20.1.tar.gz

1、导入rhel7的镜像,发现大小为140M

docker load -i rhel7.tar

在这里插入图片描述2、编写软件仓库文件

vim dvd.repo

[dvd]
name=dvd
baseurl=http://172.25.36.250/rhel7.6
gpgcheck=0

3、编写Dockerfile

vim /root/docker/Dockerfile

FROM rhel7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]  ##挂载目录
COPY dvd.repo /etc/yum.repos.d/  ##复制软件仓库文件
ADD nginx-1.20.1.tar.gz /mnt  ##解压到指定目录
RUN rpmdb --rebuilddb  ##仓库记录清理
RUN yum install -y gcc pcre-devel zlib-devel make
WORKDIR /mnt/nginx-1.20.1
RUN ./configure &> /dev/null
RUN make &> /dev/null
RUN make install &> /dev/null
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]

4、创建镜像,运行容器

docker build -t rhel7:v1 /root/docker/
docker run -d --name demo rhel7:v1
docker inspect demo  ##查看新建容器信息

在这里插入图片描述挂载的数据目录:
在这里插入图片描述查看到ip地址:
在这里插入图片描述5、访问ip地址
(1)访问报错是因为真实路径下没有数据

curl 172.17.0.2

在这里插入图片描述(2)添加数据再访问

cd /var/lib/docker/volumes/91387133be81617cc32aabd3d1cd146a102a821644a3cba0d367da655e5893c8/_data
echo www.westos.org > index.html
curl 172.17.0.2

在这里插入图片描述

五、优化镜像

1、查看新建镜像大小,发现是rhel7的两倍还多,所以就需要进行优化镜像大小

docker images

在这里插入图片描述
2、优化镜像大小的方法

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

3、针对上面建立的nginx镜像进行优化
(1)把RUN命令放到一起,中间用&&连接起来,因为RUN命令运行一次就会增加一层镜像层,同时关闭nginx编译debug模块,清楚缓存及nginx编译目录

vim Dockerfile

FROM rhel7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
COPY dvd.repo /etc/yum.repos.d/
ADD  nginx-1.20.1.tar.gz  /mnt
WORKDIR /mnt/nginx-1.20.1
RUN  rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure &> /dev/null &&  make &> /dev/null &&  make install &> /dev/null && rm -rf /mnt/nginx-1.20.1 /var/cache/*
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

docker build -t rhel7:v2 /root/docker/
docker run -d --name demo1 rhel7:v2
docker images

在这里插入图片描述
镜像大小有所变化,但变化较小,需要继续优化
(2)使用多模块(用基础模块生成nginx,再复制基础模块中的/usr/local/nginx目录即可)

vim Dockerfile

FROM rhel7 as build
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
COPY dvd.repo /etc/yum.repos.d/
ADD  nginx-1.20.1.tar.gz  /mnt
WORKDIR /mnt/nginx-1.20.1
RUN  rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure &> /dev/null &&  make &> /dev/null &&  make install &> /dev/null && rm -rf /mnt/nginx-1.20.1 /var/cache/*
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

FROM rhel7
COPY --from=build /usr/local/nginx  /usr/local/nginx
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

docker build -t rhel7:v3 /root/docker/
docker run -d --name demo2 rhel7:v3
docker images

在这里插入图片描述rhel7:v3镜像的大小明显变小,且创建时速度明显变快,但还是可以进一步优化
(3)rhel7镜像中很多模块并没有被使用,消耗大量空间,所以更换轻量级源镜像,同时安装nginx需要的函数库

需要提前下载base-debian10.tar(轻量级源镜像)

docker load -i base-debian10.tar  ##先导入轻量级源镜像
vim Dockerfile

FROM nginx:latest as base

# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ARG TIME_ZONE
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
ENTRYPOINT ["nginx", "-g", "daemon off;"]

docker build -t rhel7:v4 /root/docker/
docker run -d --name demo3 rhel7:v4
docker images

在这里插入图片描述在这里插入图片描述查看镜像大小仅为31.9M,达到优化效果

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值