6.1 构建应用程序镜像

实验过程
任务一:对比不同父镜像
在这个任务中,我们将创建两个基于不同父镜像(Ubuntu和Alpine)的Dockerfile,以比较它们在镜像大小上的差异。
1、创建目录
mkdir /root/compare
cd /root/compare
2、创建两个 Dockerfile 文件
touch Dockerfile-1 Dockerfile-2
3、编辑Dockerfile文件内容
Dockerfile-1 文件内容(基于Ubuntu):
Dockerfile-2 文件内容(基于Alpine):
4、构建两个镜像
使用 Dockerfile-1 构建 golang:ubuntu 镜像:
使用 Dockerfile-2 构建 golang:alpine 镜像:
-t
:指定构建的镜像名称和标签,格式为name:tag
-f
:指定使用的Dockerfile文件路径,当Dockerfile不是默认文件名或不在当前目录时使用.
:构建上下文路径,Docker会将这个路径下的所有文件发送给Docker守护进程
5、对比镜像大小
docker images golang
任务二:对比镜像层数
在这个任务中,我们将创建两个Dockerfile来对比镜像层数对最终镜像大小的影响。
1、在 /root/compare
中创建文件 Dockerfile-3 和 Dockerfile-4,内容如下:
Dockerfile-3(多层构建):
Dockerfile-4(减少层数):
2、构建两个镜像,名称分别为 l3 和 l4
构建l3镜像:
构建l4镜像:
3、对比两个镜像的层数
docker history
命令可以查看镜像的层数:
任务三:基于 VNC 的 Firefox 镜像(了解)
在这个任务中,我们将创建一个包含Firefox浏览器和VNC服务器的Docker镜像,让用户可以通过网页远程访问容器中运行的Firefox。
1、创建目录
mkdir /root/firefox-vnc
cd /root/firefox-vnc
2、创建 Dockerfile 文件
vim Dockerfile
为什么在一条 RUN 指令中执行两次 apt-get,而不是拆成两条 RUN 指令?
答:这是为了减少镜像层数。每一个RUN指令都会创建一个新的镜像层,而通过&&连接多个命令,可以在一个层中完成多个操作,从而减小最终镜像的大小。另外,将apt-get update和apt-get install放在同一个RUN命令中可以确保使用的是最新的软件包列表。
3、构建镜像
docker build -t firefox-vnc .
4、查看镜像列表
5、启动容器
docker run --rm -p 8080:8080 --name ff-vnc firefox-vnc
--rm
:容器停止运行后自动删除容器,避免占用磁盘空间-p 8080:8080
:将容器内部的8080端口映射到主机的8080端口,使外部能够访问容器内的VNC服务--name ff-vnc
:给容器指定一个易记的名称firefox-vnc
:使用的镜像名称
6、打开浏览器,输入 ip:8080/vnc.html
任务四:对比多阶段构建
在这个任务中,我们将对比单阶段构建和多阶段构建的镜像大小差异,了解多阶段构建的优势。
1、创建项目目录
mkdir /root/go
cd /root/go
2、创建一个名为 app.go 的文件,其内容如下:
package main
import "fmt"
func main() {
fmt.Println("Hello World!")
}
3、创建 Dockerfile-1(多阶段构建)
vim Dockerfile-1
文件内容如下:
上面的Dockerfile使用了多阶段构建:
- 第一阶段(builder):使用golang:alpine镜像编译Go应用程序
- 第二阶段:使用最小的alpine镜像,只复制第一阶段中编译好的可执行文件 这样可以大大减小最终镜像的大小,因为最终镜像中不包含编译工具和源代码。
4、构建镜像
5、查看镜像列表
多阶段构建的镜像大小是 9.96 MB。
6、创建 Dockerfile-2 用来单阶段构建
7、构建镜像,名为 go:v2
8、查看镜像列表
分阶段构建的 go:v1 大小是 9.96MB,单阶段构建的 go:v2 大小是 406MB。
总结
构建Docker镜像的三个核心原则:
- 选择满足需求的尽量小的父镜像:例如使用Alpine替代Ubuntu可以大幅减小镜像体积
- 尽量减少镜像层数:合并RUN命令,使用&&连接多个操作
- 使用多阶段构建:将构建环境与运行环境分离,只保留必要的产物
遵循这些原则可以确保你的Docker镜像既高效又轻量,带来以下好处:
- 更快的镜像拉取和部署速度
- 更少的存储空间占用
- 更小的攻击面,提高安全性
- 更好的资源利用率
在实际项目中,应根据应用的具体需求,合理应用这些原则,构建出最适合你应用的Docker镜像。