Docker镜像的分层结构、Dockerfile的编写及镜像优化
镜像的分层结构
- 累积木叠加,分层为了共享资源
镜像的构建
- -d打入后台,-a交互
- 删除正在运行的,-f;删除已经退出的,直接rm
- 创建三个文件
- 退出,容器停掉,数据还在
- 给容器起名
- 共享,demo3层v1,加了一层
- 删除demo
- 数据保存在demov1,通过其才能看到
- 每个容器都有ID
- 随机命名
- 不命名时,-rm回收
- 进入到原始没有,在demov1里
- 删镜像,只删了一层
- 没有人共享就可以把它删掉
- 从官方镜像,每一层干了什么清楚,便与审计
- 不用的镜像删掉(推荐)
Dockerfile的编写
- 创建一个镜像目录
- 把一个首页拷贝到nginx默认发布目录
- 默认到指定目录寻找文件
- 自动让容器发布目录
- 这个层是在官方里面构建的
- 做端口映射
- 把页面拷到了镜像内
- 启动镜像、拷文件、固定
- 写一行就是镜像封装成一层
- 要镜像只需要写一个文件,可复用
Dockerfile详解
Dockerfile常用指令之FROM、MAINTAINER、COPY
- 拷贝的数据不支持从根开始
- dockerfile不是绝对路径而是相对路径,根底下文件所有目录发送到docker引擎
- 空目录
Dockerfile常用指令之ADD、ENV
- 拷贝原数据一定要放在构建目录之下
- add来源写url或者压缩包都可以
- 解压一份数据
- 再次构建,下载放进去
- v2
- 交互后回收
- 镜像后面可以指定命令,不指定会运行默认运行的命令
- 删掉demo
- env变量,定义对外暴露的端口,监听
- nginx已经有
- 变量,告诉一些信息
- 这个应用究竟是什么端口(他人构建)
Dockerfile常用指令之EXPOSE、VOLUME、WORKDIR
- 卷——做数据持久化
- 把应用封装到页面不合适
- 默认挂载点
- 直接使用缓存
- 打入后台
- 自动在宿主机创建一个目录,挂接到容器内
- docker创建的卷,如果发现容器目录有数据,会自动拷进去
- docker自动创建卷,引擎自动挂进去,发下有数据,自动拷下来
- 目录在宿主机上,容器内是相通的,默认可写
- 在容器内访问数据与宿主机(修改)共享
- 宿主机持久化到磁盘上
- 镜像尽量是通用的
- 卷就是一种数据结藕的方式
- 删除掉,数据还在持久化——保存下来
- 再访问容器时卷还可以挂上去,这时容器是可以坏的,数据不会损失
Dockerfile常用指令之RUN、CMD与ENTRYPOINT
- RUN:跑一些基本指令,run表示要在构建镜像中做什么事情
- 换一个镜像、centos7的镜像
- 本地加载镜像
- 默认有yum源
- 默认开bash
- 进入后有yum源
- 会从外网连接
- 退出来就没了
- ctrl+p+q,组合键,把容器打入后台
- 还是运行状态
- attach再次连接上
- 改名,可多次执行
- 开始封包,第一层,自动运行
- 每一层干的操作都记录清楚
- CMD是在运行容器时生效,CMD在容器内运行什么样的命令,类似开机自启
- CMD可被覆盖,而其不可被覆盖,也可以结合
Dockerfile两种编译方法
- 环境变量
- 构建
- 输出
- 运行后删掉
- 不会解析变量
- 否则不会解析变量
- 官方推荐
- exec写法
- 交互一下
- cmd会被覆盖,ENTRYPOINT不会被覆盖
- 通常将CMD和ENTRYPOINT结合使用
- 利用cmd可被覆盖的特性
- 类似于shell传参
- 按照自己需求,封装镜像
镜像封装编译
- Centos编译nginx,封装
- add可以支持压缩包
- 扔到mnt中,自动解压
- 编译nginx需要包
- 关闭debug
- 替换
- 前面加一个#号
- 复制写入dockerfile
- 在容器内怎么切工作目录
- 在容器什么目录运行命令
FROM centos:7
ADD nginx-1.21.1.tar.gz /mnt
RUN yum install -y gcc make pcre-devel openssl-devel
WORKDIR /mnt/nginx-1.21.1
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --with-http_ssl_module --with-http_stub_status_module
RUN make
RUN make install
COPY index.html /usr/local/nginx/html
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
- 按照官方写法
- 删除镜像
- make install 后做拷贝
- 会覆盖它默认测试页
- 懂业务部署流程
- 不会默认安装make
- -d打入后台
- 容器起来了
- 地址单调递增
- 成功完成封装
- 编译完成有451兆
- 比官方的差不多,没有意义,废存储和带宽
- 容器镜像和操作系统镜像不一样
容器的镜像优化
- 不指定版本就是最新版
- docker官方指定仓库
- :冒号后接标签
- 选择最精简的镜像
- 编译合并,编译后的清理工作
- 尝试减少了镜像层,大小会不会减小
- run动作装很多依赖包占很多大小
- 把编译好的二进制命令拷贝到目录
- 通过多阶段构建,把编译的工作压缩到一个容器
- 产生的临时数据拷出来
- 查看二进制程序调用的文件
- base镜像要有,也有要依赖文件
- 修改dockerfile
- 拷贝完成,安装到目录下
- 再利用一个镜像,进入到第二个容器
- 从上一个容器拷usr/local/nginx
- 构建v3
- 编译后运行
- 可以运行
- 基础镜像还是很大
[root@server1 new]# cat Dockerfile
FROM nginx:1.18.0 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;"]
- 导入本地镜像
- 库文件有依赖性
- 运行报错,得一个个拷,解决依赖性
- 从官方的二进制程序的库文件拷出
- 把官方数据拷入一个更小的镜像
- 运行不起来,版本不同,base环境不一样
- 用的镜像是当前最新的,用的镜像是当前最新的
- 拷贝后不生效
- 镜像路径发生变化
- 删除原有容器
- 查看拷的文件对不对
- 内置pcre版本不对
- 删除v4
- 起不来
- 再删镜像
- docker镜像仓库,v5优化
- ldd查看动态库文件
- 把dockerfile中路径改掉
- awk删掉