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

目录

1. 镜像简介

1.1 Docker镜像是什么

1.2 镜像的表示  

1.3 镜像的分层结构

2. 镜像的构建

2.1 commit提交

2.2 通过Dockerfile提交

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

3.1 FROM

3.2 MAINTAINER

3.3 COPY

3.4 ADD

3.5 ENV

3.6 EXPOSE

3.7 VOLUME

3.8 WORKDIR

3.9 RUN

3.10 CMD 与 ENTRYPOINT

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

4.1 centos中安装nginx

4.2 通过Dockerfile文件安装nginx容器

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

5.4 使用多阶段构建镜像

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

5. 总结补充 


1. 镜像简介

1.1 Docker镜像是什么

传统企业是以交付应用的方式进行发布的,交付应用相当于可执行性程序,其整个应用与环境是分开维护的。随着容器技术的兴起,提出了交付环境的概念。交付环境与交付应用相比,交付的不仅是可执行程序,还交付可执行程序依赖的配置文件、类库甚至是整个文件系统。在Docker语境里面,环境就是镜像。从上图左下角镜像示例图可以看出,镜像本身的组织结构是分层的。其优点是,虽然它包含了所有的依赖,但是发布部署的时候不会显著增加信息的传输量。

1.2 镜像的表示  

镜像的表示分为四部分:红色的部分是镜像中心域名,黄色的部分是镜像命名空间,我们可以根据命名空间进行权限控制等操作,绿色是镜像的名称,每个镜像有一个版本(即标签)。Docker官方的镜像不需要镜像中心的域名,有一些镜像可以省略命名空间。

1.3 镜像的分层结构

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 commit提交

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

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

uname 容器与真机公用同一个内核

2.2 通过Dockerfile提交

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 file2 file3

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

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

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

ctel+q+p 可以将容器打入后台,而不直接瑞出。
运行中的使用rm -f
暂停状态使用rm
删除镜像使用rmi 

3.1 FROM

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

3.2 MAINTAINER

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

3.3 COPY

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

3.4 ADD

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

3.5 ENV

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

3.6 EXPOSE

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

mario测试8080端口

80映射容器的8080docker会自动开启虚拟网络宅

3.7 VOLUME

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

查看挂载点位置 改变目录里的内容容器也会改变 

3.8 WORKDIR

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

3.9 RUN

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

3.10 CMD 与 ENTRYPOINT

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

- 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"]

CMD

ENTRYPOINT和CMD

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

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

4.1 centos中安装nginx

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

将nginx源码包复制进容器 配置阿里云软件仓库解决依赖性编译​​​​​​​注释掉debug编译更快​​​​​​​查看进程 

4.2 通过Dockerfile文件安装nginx容器

官网提供的nginx包​​​​​​​

[root@server1 docker]# vim Dockerfile 
[root@server1 docker]# cat Dockerfile 
FROM centos
COPY CentOS-Base.repo /etc/yum.repos.d/
ADD nginx-1.20.0.tar.gz /mnt
WORKDIR /mnt/nginx-1.20.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大小

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

结果与5.2的大小接近

5.4 使用多阶段构建镜像

[root@server1 docker]# vim Dockerfile 
[root@server1 docker]# cat Dockerfile 
FROM centos as build
COPY CentOS-Base.repo /etc/yum.repos.d/
ADD nginx-1.20.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

结果相差甚远,说明多阶段确实可以减少内存

5.5 选择最精简的基础镜像(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(不需要外网) 我们使用下载好的包 找到Dockerfile的配置文档

 

[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;"]

查看镜像为31.7MB比之前三组都要小 

5. 总结补充 

- 镜像常用子命令
	images	显示镜像列表
	history	显示镜像构建历史
	commit	从容器创建镜像
	build	从Dockerfile构建镜像
	tag	给镜像打标签
	search	搜索镜像
	pull	从仓库拉取镜像
	push	上传镜像到仓库
	rmi	删除镜像
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值