【DOCKER】-4 dockerfile镜像管理
文章目录
- 1、镜像分层原理
- 1.1 镜像分层的实际应用案例
- 2、dockerfile基础与语法
- 2.1 指令分解
- 2.2 编写dockerfile的注意事项
- 3、dockerfile制作镜像实践
- 4、dockerfile镜像优化
- 4.1 镜像的优化策略
- 4.2 镜像优化实战
- 4.2.1 减少镜像层,减少无效缓存
- 4.2.2 选择更合适的基础镜像
- 4.2.3 多阶段构建
1、镜像分层原理
1.1 镜像分层的实际应用案例
- 在开发过程中,开发人员可以通过Dockerfile快速构建应用程序的镜像。由于Docker镜像采用分层结构,因此每次构建时只需要重新生成发生变化的层,从而大大提高了构建效率。
- 在持续集成/持续部署(CI/CD)流程中,Docker镜像的分层结构使得每次构建、测试和部署都变得更加快速和可靠。通过利用缓存机制,可以避免重复构建相同的层,从而加速整个流程。
- 在容器编排场景中,如Kubernetes等容器编排工具可以利用Docker镜像的分层结构来优化存储和网络传输。通过只传输发生变化的层,可以大大减少网络带宽的占用和存储空间的消耗。
2、dockerfile基础与语法
【注】:ARG为运行时所执行的命令
2.1 指令分解
FROM:指定基础镜像
指定构建新镜像时使用的基础镜像,通常必须是Dockerfile的第一个有效指令# 格式
FROM <image:[版本标签]># 指定基础镜像
FROM centos
FROM ubuntu:20.04# 说明:如果不指定版本标签,默认使用latestLABEl:添加镜像的元数据
LABEL一般使用键值对方式。# 格式
LABEL <key>=<value> <key>=<value>....# 为镜像添加元数据
LABEL version="2.0" description="业务系统第二个版本"# 说明:一条LABEL可以指定多条元数据,尽量不要写多个LABERUN:构建镜像时执行的命令
有两种执行方式方式一:shell执行# 格式
RUN <command># 示例
RUN yum update -y# 说明:RUN 指令创建的中间镜像会被缓存,并在下次构建中使用。可以在构建时使用--no-cache取消缓存:
docker build --no-cacheENV:在容器内部设置环境变量
# 格式
ENV <key> <value># 示例
ENV MYPATH /usr/localADD:将本地文件添加到镜像中
相当于scp。只是scp 需要将用户名和密码的权限验证,而ADD 不用。tar 类型文件会自动解压,可以访问网络资源,类似 wget# 语法
ADD <src> <dest>
ADD ["src", "dest"]# 示例
COPY nginx.tar /opt# 说明:路径可以是相对路径或绝对路径,建议使用绝对路径。
# 尽量不要把<src> 写成一个文件夹,如果<src> 是一个文件夹,复制整个目录的内容COPY:将文件或目录复制到镜像中。
功能类似 ADD,但不会自动解压文件,也不能访问网络资源# 语法
COPY <src> <dest>
COPY ["<src>", "<dest>"]VOLUME:指定持久化目录
# 格式
VOLUME ["/path/to/dir"]# 示例
VOLUME ["/data"]
VOLUME ["/data/log", "/data/config"]
# 一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统
容器使用的是AUFS,这种文件系统不能持久化数据,当容器关闭后,所有的更改都会丢失。所以如果想要数据持久化,就得使用VOLUME功能说明:卷可以在容器间共享和重用;修改卷后会立即生效;对卷的修改不会对镜像产生影响CMD:容器启动时运行的命令(不常用)
# 语法
CMD ["executable","param1","param2"]
CMD command param1 param2# 示例
CMD echo $LANGENTRYPOINT:容器启动时运行的命令(常用)
# 语法
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2# 示例
ENTRYPOINT java -jar /data/config.jarENTRYPOINT:容器启动时运行的命令(常用)
# 语法
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2# 示例
ENTRYPOINT java -jar /data/config.jarENTRYPOINT和CMD的异同点:共同点:都可以用来指定容器的启动命令
区别:ENTRYPOINT指定的容器启动命令优先级更高,如果ENTRYPOINT和CMD同时存在,那么
CMD指定的内容将作为ENTRYPOINT指定的命令传入参数使用。
COPY可以在多阶段构建种复制构建结果到当前构建中EXPOSE:暴露容器运行时的监听端口给外部
# 格式:
EXPOSE <port> [<port>...]# 示例:
EXPOSE 8080
EXPOSE 443/tcp 80/tcpEXPOSE 并不会让容器的端口访问到主机。 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口如果没有暴露端口,后期也可以通过docker run -p 8080:8080 方式映射端口,但不能通过 -P 形式映射
2.2 编写dockerfile的注意事项
- 精简镜像:尽量使用官方的基础镜像,减少不必要的文件和依赖,以降低镜像大小。
- 优化指令:合理安排Dockerfile中的指令顺序,利用Docker的缓存机制,提高构建效率。
- 权限设置:注意文件和目录的权限设置,确保容器运行时的安全性
- 可读性:保持Dockerfile的简洁明了,添加必要的注释,提高可读性。
3、dockerfile制作镜像实践
示例:
#创建工作目录
[root@localhost ~]# mkdir /opt/nginx_dockerfile
[root@localhost ~]# cd /opt/nginx_dockerfile#编写dockerfile
# 使用官方的Nginx基础镜像
FROM nginx:alpine# 将当前目录下的内容复制到容器的/usr/share/nginx/html目录下
COPY . /usr/share/nginx/html# 暴露80端口供外部访问
EXPOSE 80# 当Docker容器启动时,自动启动Nginx服务
CMD ["nginx", "-g", "daemon off;"]#准备网站页面
[root@localhost ~]# echo "this is nginx web" > index.html#制作镜像
[root@localhost ~]# docker build -t nginx:v1 . --no-cache#运行容器
docker run -d --name nginx_v1 -p 1218:80 nginx:v1#测试访问
#浏览器访问 http://主机IP:1218/
#或curl http://主机IP:1218
4、dockerfile镜像优化
4.1 镜像的优化策略
- 选择轻量级基础镜像:如Alpine、Debian等,避免使用过于庞大的基础镜像。
- 多阶段构建:利用Dockerfile的多阶段构建特性,只将必要的文件和依赖打包到最终镜像中。
- 使用.dockerignore文件:在构建镜像时,通过.dockerignore文件排除不必要的文件和目录,减少构建上下文的大小。
- 清理无用文件和缓存:在Dockerfile中使用命令清理编译过程中生成的临时文件和缓存,减小镜像体积。
4.2 镜像优化实战
4.2.1 减少镜像层,减少无效缓存
##将RUN指令合并,把频繁变动的COPY指令后移,减少缓存失效FROM centos:7
RUN rm -rf /etc/yum.repos.d/*
COPY CentOS-aliyun-lhr.repo epel-aliyun.repo /etc/yum.repos.d/
ADD nginx-1.22.0.tar.gz /opt
RUN yum clean all && yum makecache &> /dev/null && \yum -y install pcre-devel zlib-devel gcc gcc-c++ make &> /dev/null && \useradd -M -s /sbin/nologin nginx
ADD nginx-1.22.0.tar.gz /opt
RUN cd /opt/nginx-1.22.0 && \./configure --prefix=/usr/local/nginx --user=nginx --group=nginx &> /dev/null && \make &> /dev/null && \make install &> /dev/null && \ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin
EXPOSE 80
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
4.2.2 选择更合适的基础镜像
FROM alpine:3.22.0
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/' /etc/apk/repositories \&& apk update && apk --no-cache add \tzdata gcc make net-tools \libc-dev libcurl \pcre-dev zlib-dev libnfs pcre pcre2 \&& addgroup -g 888 -S nginx \&& adduser -s /sbin/nologin -S -D -u 888 -G nginx nginxADD nginx-1.22.0.tar.gz /usr/local/srcRUN cd /usr/local/src/nginx-1.22.0 \&& ./configure --prefix=/usr/local/nginx \&& make \&& make install \&& ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/nginx \&& chown -R nginx:nginx /usr/local/nginx/ \&& apk add bash
EXPOSE 80
CMD ["usr/local/nginx/sbin/nginx","-g","daemon off;"]
4.2.3 多阶段构建
# 第一阶段:构建环境
FROM alpine:3.18 as builderARG NGINX_VERSION=1.22.0
RUN apk add --no-cache \gcc \libc-dev \make \openssl-dev \pcre-dev \zlib-dev \&& wget -O nginx.tar.gz http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \&& tar -xzf nginx.tar.gz \&& cd nginx-${NGINX_VERSION} \&& ./configure --prefix=/usr/local/nginx \&& make \&& make install# 第二阶段:运行时镜像
FROM alpine:3.18 as runtimeCOPY --from=builder /usr/local/nginx /usr/local/nginx
#COPY nginx.conf /usr/local/nginx/conf/nginx.conf
#COPY html/ /usr/local/nginx/html/RUN adduser -D nginx \&& chown -R nginx:nginx /usr/local/nginxUSER nginx
EXPOSE 80
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]