Docker(二)–镜像构建–commit与dockerfile与镜像优化

  • Post author:
  • Post category:其他




1. 镜像的分层结构

在这里插入图片描述

在这里插入图片描述

1. base 镜像简单来说就是不依赖其他任何镜像,完全从0开始建起,
	其他镜像都是建立在他的之上,可以比喻为大楼的地基,docker镜像的鼻祖。
	
	base 镜像有两层含义:
	(1)不依赖其他镜像,从 scratch 构建;
	(2)其他镜像可以之为基础进行扩展。
	所以,能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,
	比如 Ubuntu, Debian, CentOS 等。
  • 镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。
  • 添加文件:在容器中创建文件时,新文件被添加到容器层中。 读取文件:在容器中读取某个文件时,Docker会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后打开并读入内存。
  • 修改文件:在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
  • 删除文件:在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。
  • 只有当需要修改时才复制一份数据,这种特性被称作Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。



2. 镜像的构建



2.1 容器的简单操作

[root@server1 ~]# ls
busybox.tar  game2048.tar  mario.tar
[root@server1 ~]# docker load -i busybox.tar  ##相当于一个最小系统
8a788232037e: Loading layer   1.37MB/1.37MB
Loaded image: busybox:latest
[root@server1 ~]# docker images 
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
busybox      latest    59788edf1f3e   2 years ago   1.15MB
[root@server1 ~]# docker run -it busybox
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # uname -r 
3.10.0-957.el7.x86_64
/ # [root@server1 uname -r
3.10.0-957.el7.x86_64

[root@server1 ~]# docker history busybox:latest   
[root@server1 ~]# docker ps -a    ##查看进程和id
CONTAINER ID   IMAGE     COMMAND   CREATED              STATUS                          PORTS     NAMES
0df8b43139da   busybox   "sh"      About a minute ago   Exited (0) About a minute ago             pedantic_wu(随即生成的容器名字)
[root@server1 ~]# docker start 0df8b43139da   ##通过id启动容器
0df8b43139da
[root@server1 ~]# docker container attach 0df8b43139da  ##通过id进入容器
[root@server1 ~]# docker rm 0df8b43139da   ##通过id删除容器

[root@server1 ~]# docker rm -f demo 

[root@server1 ~]# docker run -it --rm busybox   ##ctrl+d直接退出,清空
/ # [root@server1 ~]# docker ps -a 
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

在这里插入图片描述

在进入容器还是存在刚才新建的文件

在这里插入图片描述

rm 参数—-> ctrl+d之后直接退出

在这里插入图片描述



2.2 commit提交

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

-   运行容器
		# docker run -it --name test busybox
	修改容器 (以下命令在容器内运行)
		# echo helloworld > testfile
	将容器保存为新的镜像
		# docker commit  test test:v1
	查看镜像
		# docker images test:v1
[root@server1 ~]# docker run  -it --name  demo busybox  ##生成容器demo
/ # ls
bin    etc    file2  home   root   tmp    var
dev    file1  file3  proc   sys    usr

/ # [root@server1 ~]# docker ps -a 
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS                     PORTS     NAMES
cf8ac9c4e00f   busybox   "sh"      51 seconds ago   Exited (0) 8 seconds ago             demo

[root@server1 ~]# docker commit -m "add files" demo demo:v1 ##通过容器生成镜像

[root@server1 ~]# docker images   ##v1是生成的镜像
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
demo         v1        16b70d3f6375   13 seconds ago   1.15MB
busybox      latest    59788edf1f3e   2 years ago      1.15MB
game2048     latest    19299002fdbe   4 years ago      55.5MB
mario        latest    9a35a9e43e8c   5 years ago      198MB

直接使用commit提交生成镜像,没有审计,完全不知道里面干过什么。只有一个描述add file。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



2.3 通过Dockerfile提交

## 创建一个Dockerfile
[root@server1 ~]# mkdir docker
[root@server1 ~]# cd docker
[root@server1 docker]# vim Dockerfile
[root@server1 docker]# cat Dockerfile 
FROM busybox
RUN touch file1
RUN mkdir westos

##构建镜像
[root@server1 docker]# docker build -t demo:v1 .


dockerfile的创建原理—>相当于一个一个进行提交。


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在新建一个镜像,使用的是是一个镜像v1的缓存。

在这里插入图片描述



3. Dockerfile详解(dockerfile常用指令)


ctel+q+p 可以将容器打入后台,而不直接瑞出。


没用的先删掉!

在这里插入图片描述



3.1 FROM

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



3.3 MAINTAINER

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

在这里插入图片描述



3.3 COPY

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

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



3.4 ADD

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

在这里插入图片描述

在这里插入图片描述



3.5 ENV

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

在这里插入图片描述



3.6 EXPOSE

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

下载一个 nginx做实验。

在这里插入图片描述

我这里是下载好的包。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



3.7 VOLUME

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

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

进入到目录删除之后,文件消失

在这里插入图片描述

释放掉volume卷

在这里插入图片描述



3.8 WORKDIR

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



3.9 RUN

在容器中运行命令并创建新的镜像层,常用于安装软件包:

RUN yum install -y vim



4.0 CMD 与 ENTRYPOINT

这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。

docker run后面的参数可以传递给ENTRYPOINT指令当作参数。

Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。

CMD

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

- Shell和exec格式的区别
	# cat Dockerfile 
	FROM busybox
	ENV name world
	ENTRYPOINT echo "hello, $name"
	
- Shell格式底层会调用/bin/sh -c来执行命令,可以解析变量,而下面的exec格式不会:
	# cat Dockerfile 
	FROM busybox
	ENV name world
	ENTRYPOINT ["/bin/echo", "hello, $name"]

- 需要改写成以下形式:
	# cat Dockerfile 
	FROM busybox
	ENV name world
	ENTRYPOINT ["/bin/sh", "-c", "echo hello, $name"]
	
- 官方推荐使用exec格式书写

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

- Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外参数可以在容器启动时动态替换。在shell格式时ENTRYPOINT会忽略任何CMD或docker run提供的参数。
	# cat Dockerfile 
	FROM busybox
	ENTRYPOINT ["/bin/echo", "hello"]
	CMD ["world"]

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



4. 阿里云加速器的使用

首先注册帐号

在这里插入图片描述

登陆成功选择控制台

在这里插入图片描述

选择产品服务

在这里插入图片描述

查看镜像加速器码和操作步骤

在这里插入图片描述

设置加速器

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

测试拉取速度

在这里插入图片描述

在这里插入图片描述

拉取后版本新的替换掉版本旧的,然后删除掉没用的images

在这里插入图片描述

在这里插入图片描述



5. 镜像的优化—搭建最简nginx

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

删除镜像,保证实验环境纯净

在这里插入图片描述

在这里插入图片描述

我们使用rhel7.0作为最小系统

在这里插入图片描述



5.1 通过Dockerfile文件安装nginx容器

[root@server1 docker]# pwd
/root/docker
[root@server1 docker]# vim dvd.repo   ##编写所用仓库
[root@server1 docker]# cat dvd.repo 
[dvd]
name=rhel7.6
baseurl=http://172.25.13.250/rhel7.6
gpgcheck=0

在这里插入图片描述

[root@server1 docker]# vim Dockerfile 
[root@server1 docker]# cat Dockerfile 
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN rpmdb --rebuilddb
RUN yum install -y gcc make pcre-devel zlib-devel
RUN ./configure
RUN make
RUN make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]


[root@server1 docker]# docker build -t webserver:v1 .
[root@server1 docker]# docker images
##比较images大小

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

[root@server1 docker]# docker inspect webserver  ##查看ip并测试是否访问成功

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



5.2 减少镜像层数,清理镜像构建的中间产物

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



5.3 使用多阶段构建镜像

[root@server1 docker]# vim Dockerfile 
[root@server1 docker]# cat Dockerfile 
FROM rhel7 as build
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.18.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.18.0
RUN rpmdb --rebuilddb && yum install -y gcc make pcre-devel zlib-devel &> /dev/null && ./configure &> /dev/null && make &> /dev/null && make install &> /dev/null && rm -fr /mnt/nginx-1.18.0 && yum remove -y gcc make &&  yum clean all

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

[root@server1 docker]# docker build -t webserver:v3 .
[root@server1 docker]# docker images webserver
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
webserver    v3        9318bb8566e1   37 seconds ago   144MB  ##缩减到了144M,但还是比nginx官方镜像133M大很多
webserver    v2        ac33a92dfa33   8 minutes ago    233MB
webserver    v1        3c76174a3370   33 minutes ago   303MB

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



5.4 选择最精简的基础镜像(google)

[root@server1 docker]# docker run -it --rm webserver:v3 bash
bash-4.2# ldd /usr/local/nginx/sbin/nginx   ##执行nginx,base中下面的执行文件、库文件都必须有。这些都需要复制到base中
	linux-vdso.so.1 =>  (0x00007ffeb0d8a000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f34521ff000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3451fe3000)
	libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f3451dac000)
	libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f3451b4b000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f3451935000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f3451574000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3452403000)
	libfreebl3.so => /lib64/libfreebl3.so (0x00007f34512f5000)


## 更精简的镜像:(goole准备好了)


在这里插入图片描述


github上的查找方法(下载一般需要外网)

在这里插入图片描述

在这里插入图片描述

可以通过命令直接下载最简单的base(不需要外网)

在这里插入图片描述

在这里插入图片描述


我们使用下载好的包


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

[root@server1 ~]# cd nginx/
[root@server1 nginx]# pwd
/root/nginx
[root@server1 nginx]# vim Dockerfile
[root@server1 nginx]# cat Dockerfile

FROM nginx:1.18.0 as base  ##下载一个nginx1.18.0
# 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;"]

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



6. 总结补充

- 镜像常用子命令
	images	显示镜像列表
	history	显示镜像构建历史
	commit	从容器创建镜像
	build	从Dockerfile构建镜像
	tag	给镜像打标签
	search	搜索镜像
	pull	从仓库拉取镜像
	push	上传镜像到仓库
	rmi	删除镜像



版权声明:本文为qwerty1372431588原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。