docker(容器)——构建镜像(nginx)的具体流程+多阶段优化构建镜像(dockerfile)

一、构建过程
1.清空之前的实验环境(rm删除容器、rmi删除镜像)
2.获取nginx软件包和rhel7的镜像文件

[root@server1 ~]# cd docker/
[root@server1 docker]# ls
Dockerfile  nginx-1.18.0.tar.gz  rhel7.tar  testfile
[root@server1 docker]# docker load -i rhel7.tar  导入镜像
e1f5733f050b: Loading layer [============================>]  147.1MB/147.1MB
安装nginx要解决一些依赖性所以必须配置yum源
[root@server1 docker]# cp /etc/yum.repos.d/westos.repo .  
[root@server1 docker]# ls
Dockerfile  nginx-1.18.0.tar.gz  rhel7.tar  testfile  westos.repo

编写dockerfile
在这里插入图片描述
解决

[root@server1 docker]# cat Dockerfile 
FROM rhel7 指定镜像
EXPOSE 80  指定80端口
MAINTAINER wsp439@sina.com  说明联系人
COPY westos.repo /etc/yum.repos.d/  将本地的yum源文件复制到容器中的/etc/yum.repo.d/目录下:此行书写错误导致上图报错现已更改
RUN rpmdb --rebuilddb   重新构建镜像  rpmdb命令用于初始化和重建rpm数据库
RUN yum install -y gcc make pcre-devel zlib-devel 指定安装所需的软件
ADD nginx-1.18.0.tar.gz /mnt/  指定解压路径下
WORKDIR /mnt/nginx-1.18.0  指定解压后的目录名称
RUN ./configure --prefix=/usr/local/nginx   预编译
RUN make  编译
RUN make install 编译安装
ENTRYPOINT ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]  启动运行nginx服务后台运行
[root@server1 docker]# docker build -t nginx:v1 .  再次构建成功注意命令后有一个点,表示当前目录下
[root@server1 docker]# docker images   可以看到nginx303M特大
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v1                  245f9de6f74e        4 minutes ago       303MB

对nginx进行优化:方便跨平台部署
一般解压后的目录,编译扮装的软件所产产生的垃圾文件一般存放于/var/cache/yum/
可以在构建镜像的时候直接清除缓存
第一次优化:更改dockerfile文件清理编译之后不需要的一些文件目录及yum缓存

[root@server1 docker]# vim Dockerfile 
[root@server1 docker]# cat  Dockerfile 
FROM rhel7
EXPOSE 80
MAINTAINER wsp439@sina.com
COPY westos.repo /etc/yum.repos.d/
RUN rpmdb --rebuilddb
RUN yum install -y gcc make pcre-devel zlib-devel && yum clean all  清除yum缓存
ADD nginx-1.18.0.tar.gz /mnt/
WORKDIR /mnt/nginx-1.18.0
RUN ./configure --prefix=/usr/local/nginx 
RUN make
RUN make install
RUN rm -rf /mnt/nginx-1.18.0  安装完成后删除解压文件
ENTRYPOINT ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
[root@server1 docker]# docker build -t nginx:v2 .  再次构建镜像
[root@server1 docker]# docker images 可以看到重新构建的v2只有277MB
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v2                  438bc20d33c5        44 seconds ago      277MB
nginx               v1                  245f9de6f74e        25 minutes ago      303MB

第二次优化:减少镜像构建层数
下图可以看到我们构建镜像的层数非常多(12层)
在这里插入图片描述
Dockerfile进行优化可以整合对个RUN运行的命令
整合顺序不能错乱
在这里插入图片描述

[root@server1 docker]# docker build -t nginx:v3  .
[root@server1 docker]# docker images 此时只有258MB
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v3                  0c469008341a        5 minutes ago       258MB
nginx               v2                  438bc20d33c5        19 minutes ago      277MB
nginx               v1                  245f9de6f74e        43 minutes ago      303MB

第三次优化:多阶段构建镜像,最大化缩减容器占比
多阶段构建介绍1 :在多阶段构建中,需要在 Dockerfile 中多次使用 FROM 声明。每次 FROM 指令可以使用不同的基础镜像,并且每次 FROM 指令都会开始新阶段的构建。可以选择将构件从一个阶段复制到另一个阶段,在最终镜像中,不会留下不需要的所有内容。
多阶段构建介绍2多阶段构建(Multi-stage builds),旨在解决Docker构建应用容器中的一些痛点。在日常构建容器的场景中,经常会遇到在同一个容器中进行源码的获取,编译和生成,最终才构建为镜像。这样做的劣势在于:

1.不得不在容器中安装构建程序所必须的运行时环境
2.不得不在同一个容器中,获取程序的源码和构建所需的一些生态工具
3.构建出的镜像甚至包含了程序源码和一些不必要的文件,导致容器镜像尺寸偏大

当然,还有一种稍微优雅的方式,就是我们事先在外部将项目及其依赖库编译测试打包好后,再将其拷贝到构建目录中,这种虽然可以很好地规避第一种方式存在的风险点,但是也需要考虑不同镜像运行时,对于程序运行兼容性所带来的差异。
其实,这些痛点,Docker也想到了,官方提供了简便的多阶段构建 (multi-stage build) 方案。所谓多阶段构建,也即将构建过程分为多个阶段,在同一个Dockerfile中,通过不同的阶段来构建和生成所需要的应用文件,最终将这些应用文件添加到一个release的镜像中。这样做能完全规避上面所遇到的一系列问题。实现多阶段构建,主要依赖于新提供的关键字:from 和 as 。
下面进行演示

[root@server1 docker]# cat Dockerfile 
FROM rhel7 as build
EXPOSE 80
MAINTAINER wsp439@sina.com
COPY westos.repo /etc/yum.repos.d/
ADD nginx-1.18.0.tar.gz /mnt/
WORKDIR /mnt/nginx-1.18.0
RUN sed -i 's/CFLAGS="$CFLAGS-g"/#CFLAGS="$CFLAGS-g"/g' auto/cc/gcc && rpmdb --rebuilddb && yum install -y gcc make pcre-devel zlib-devel && yum clean all && ./configure --prefix=/usr/local/nginx && make && make install &&  rm -rf /mnt/nginx-1.18.0
上面的FROM主要是生成nginx的二进制文件
FROM rhel7 
EXPOSE 80
MAINTAINER wsp439@sina.com
设置数据卷;添加数据卷挂载位置
VOLUME ["/usr/local/nginx/html"]  配置数据目录,与物理机上的默认发布页面同步,若要更改只需更改物理机的默认配置页面
COPY --from=build /usr/local/nginx /usr/local/nginx  build表示上面的FROM
ENTRYPOINT ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]

[root@server1 docker]# docker build -t nginx
nginx     nginx:v1  nginx:v2  nginx:v3  
[root@server1 docker]# docker build -t nginx:v4 .
[root@server1 docker]# docker images
可以看到这次减少了许多,我们是以rhel7为镜像的它本身就有140MB,所有我们的nginx实际只有不到1MB
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v4                  eacb07b8625e        7 seconds ago       141MB
nginx               v3                  0c469008341a        About an hour ago   258MB
nginx               v2                  438bc20d33c5        About an hour ago   277MB
nginx               v1                  245f9de6f74e        About an hour ago   303MB
busybox             latest              59788edf1f3e        20 months ago       1.15MB
game2048            latest              19299002fdbe        3 years ago         55.5MB
ubuntu              latest              07c86167cdc4        4 years ago         188MB
rhel7               latest              0a3eb3fde7fd        5 years ago         140MB

第四次优化:最后的优化
优化思路:从底层优化
导入一个distroless和nginx镜像
distroless”镜像只包含应用程序及其运行时依赖项,不包含程序包管理器、shell以及在标准Linux发行版中可以找到的任何其他程序;用distroless去除容器中所有不必要的东西

导入镜像
[root@server1 ~]# docker load -i distroless.tar
668afdbd4462: Loading layer [=============================>]  18.39MB/18.39MB
Loaded image: gcr.io/distroless/base:latest
[root@server1 ~]# docker load -i nginx.tar
014cf8bfcb2d: Loading layer [=============================>]  58.46MB/58.46MB
832a3ae4ac84: Loading layer [=============================>]  53.91MB/53.91MB
e89b70d28795: Loading layer [=============================>]  3.584kB/3.584kB
Loaded image: nginx:latest

在这里插入图片描述
编写Dockerfile

[root@server1 ~]# mkdir distroless
[root@server1 ~]# cd distroless/
[root@server1 distroless]# vim Dockerfile
FROM nginx as base

# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

ARG Asia/Shanghai

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 /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.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libdl.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libpthread.so.* /opt && \
    cp -a --parents /lib/x86_64-linux-gnu/libcrypt.so.* /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
COPY --from=base /opt /
EXPOSE 80   
ENTRYPOINT ["nginx", "-g", "daemon off;"]

构建镜像
在这里插入图片描述
在这里插入图片描述

构建容器并测试
[root@server1 distroless]# docker run -d --name nginx nginx:v5  运行nginx服务名称为nginx
e5b99ef16d3f95c3a188bf5849d851f052a15349513181bc9094a8c5c5102702
[root@server1 distroless]# docker ps  查看已经运行
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
e5b99ef16d3f        nginx:v5            "nginx -g 'daemon of…"   11 seconds ago      Up 10 seconds       80/tcp              nginx
[root@server1 distroless]# docker inspect nginx 查看ip

在这里插入图片描述
测试访问
在这里插入图片描述
在这里插入图片描述

[root@server1 distroless]# yum whatprovides */brctl
[root@server1 distroless]# yum install -y bridge-utils-1.5-9.el7.x86_64
[root@server1 distroless]# brctl show  可以看到镜像的网卡桥接在docker0上,所以只有物理机可以访问
bridge name	bridge id		STP enabled	interfaces
docker0		8000.024289ff8a42	no		vethe02d183

两个不同的网段的访问本机可以访问容器:在安装容器后的时候会自动生成一个docker0的网卡,本机访问是通过docker0去访问镜像,但是目前只有本机可以访问,其他用户不可访问镜像,因为根本没有端口进入。
在这里插入图片描述
制作端口映射把容器镜像的80端口映射到主机的80端口;访问物理机的80端口就是访问容器80

[root@server1 distroless]# docker rm -f nginx 
nginx
[root@server1 distroless]# docker run -d -p 80:80 --name nginx nginx:v5 确保本机80端口没有使用
d75e632503458555093180fcdcc04b28abc78dedcfefbe2caf70f90ee043f2b2

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值