镜像的制作
dockerfile是制作镜像的配置文件
dockerfile指令:
COPY、ADD:复制宿主机里的文件或目录到容器里的某个目录下
ADD:如果复制的是.tar.gz压缩文件,拷贝到容器里会自动解压
CMD:启动容器的时候运行命令的,启动容器的时候会自动运行cmd里面的程序
ENTRYPOINT指令:
set指令能设置所使用shell的执行方式,可以依照不同的需求来做设置
参数:
-e:若指令传回值不等于0,则立即退出shell
-u:当执行时使用到未定义过的变量,则显示错误信息
-x:执行指令后,会显示该指令的执行过程及参数
案例1 – busybox
使用busybox作为基础镜像+自己编写一个脚本作为业务核心代码=完成自己的一个镜像
-
编写一个shell脚本,做镜像里的核心代码
mkdir /Dockerfile cd /Dockerfile/ [root@sc-docker Dockerfile]# cat while.sh #!/bin/bash i=1 while true do echo "hello,sanchuang$i" let i++ sleep 1 done
-
编辑dockerfile文件
[root@sc-docker Dockerfile]# cat Dockerfile # 指定基础镜像 FROM busybox # 指定进入容器的时候,进入哪个文件夹 docker exec 能看到效果 WORKDIR / # 复制宿主机当前目录下的所有文件和文件夹到容器的/目录下 = docker up COPY . / # 制作镜像的时候需要执行的命令,这些文件会留在做好的镜像里 RUN touch sc.txt && mkdir sanchuang && sleep 10 # 指定容器启动的时候需要执行的命令 # 相当于/bin/sh while.sh ENTRYPOINT ["/bin/sh","/while.sh"]
-
构建镜像
docker build -t scbusybox:1.0 .
-t:指定镜像的名字 scbusybox,1.0版本
.:表示在当前文件夹下制作
-
查看制作好的镜像
docker images
-
使用制作好的镜像
docker run -it --rm --name scbusybox-1 scbusybox:1.0
案例2 – 使用go语言编译好的代码制作镜像
-
编写一个简单的web服务器代码server.go
[root@sc-docker go]# cat server.go package main //server.go是主运行文件 import ( "net/http" "github.com/gin-gonic/gin" ) //gin-->go中的web框架 //入口函数 func main(){ //创建一个web服务器 r:=gin.Default() // 当访问/sc=>返回{"message":"hello, sanchuang"} r.GET("/",func(c *gin.Context){ //200,返回的数据 c.JSON(http.StatusOK,gin.H{ "message":"hello,sanchuanger 2023 nice", }) }) //运行web服务 r.Run() }
-
安装go语言的环境
yum install epel-release -y yum install golang -y
-
开始编译server.go成一个二进制文件
[root@sc-docker go]# pwd /Dockerfile/go go mod init web go env -w GOPROXY=https://goproxy.cn,direct go mod tidy # 运行代码,默认监听的是8080端口,测试server.go文件能否正常运行 go run server.go # 编译server.go成hnweb二进制文件 # . 表示在当前文件目录下找 go build -o hnweb . # 编译完成之后就可以使用./hnweb执行
-
编写Dockerfile
[root@sc-docker go]# cat Dockerfile FROM centos:7 WORKDIR /go COPY . /go RUN ls /go && pwd ENTRYPOINT ["/go/hnweb"]
-
制作镜像
docker build -t hnweb:1.0 .
-
启动容器
docker run -d --name hnweb-1 -p 7788:8080 hnweb:1.0
-d:后台运行
-
去宿主机的浏览器里访问
http://192.168.232.152:7788
镜像分层
一个镜像由很多层数据组成
所有容器底层都是用宿主机的内核
base镜像
base镜像提供的是最小安装的Linux发行版
scratch是一个空的镜像,可以用于构建busybox等超小镜像,可以说是真正的从开始构建属于自己的镜像
bootfs – 容器启动的时候需要的内容
rootfs – 容器内部的操作系统
如何让制作的镜像比较小?
- 使用较小的基础镜像
- 减少使用RUN、COPY、ADD、WORKDIR的次数
- 使用镜像启动容器之后,再在里面安装软件,使用卷挂载数据
使用WORKDIR命令时,如果指定的目录是/,那么不会增加层数
容器启动的时候,内核启动bootfs后直接将基础镜像加载,然后一层一层加载(自下而上)
容器运行后访问文件的时候,从上而下,从可写层,一层一层往下访问
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。
只有容器层是可写的,容器层下面的所有镜像层都是只读的
1.添加文件
在容器中创建文件时,新文件被添加到容器层中。
2.读取文件
在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,打开并读入内存。
3.修改文件
在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
4.删除文件
在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。
分层的好处在于共享资源,比如说有很多的镜像,可以从base镜像构建而来,那么docker host当中只需要在硬盘上保存一份base镜像即可,同时内存当中也只需要加载一份base镜像即可,也就是说我开多少的相同的镜像,内存在上涨值并不明显,就可以给所有的使用该base镜像的容器提供服务,而且镜像的每一层可以被单独的共享,也就是这一层如果跟其他的镜像重复的话,这一层就可以单独拿出来进行共享。