企业之Docker容器之Dockfile及其镜像的构建和优化

一.Dockfile的简介及其参数介绍

1.Dockerfile简介

  • Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令。

  • Docker程序将读取Dockerfile,根据指令生成定制的image。相比image这种黑盒子,Dockerfile这种显而易见的脚本更容易被使用者接受,它明确的表明image是怎么产生的。有了Dockerfile,当我们需要定制自己额外的需求时,只需在Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻烦。

  • Dockerfile的指令根据作用可以分为两种,构建指令和设置指令。构建指令用于构建image,其指定的操作不会在运行image的容器上执行;设置指令用于设置image的属性,其指定的操作将在运行image的容器中执行。

在这里插入图片描述

二.Dockerfile常用命令介绍

1.FROM:

用法:FROM
说明:第一个指令必须是FROM了,其指定一个构建镜像的基础源镜像,如果本地没有就会从公共库中拉取,没有指定镜像的标签会使用默认的latest标签,可以出现多次,如果需要在一个Dockerfile中构建多个镜像。

2.MAINTAINER
用法:MAINTAINER
说明:描述镜像的创建者,名称和邮箱

3.RUN
用法:RUN “command” “param1” “param2”
说明:RUN命令是一个常用的命令,执行完成之后会成为一个新的镜像,这里也是指镜像的分层构建。一句RUN就是一层,也相当于一个版本。这就是之前说的缓存的原理。我们知道docker是镜像层是只读的,所以你如果第一句安装了软件,用完在后面一句删除是不可能的。所以这种情况要在一句RUN命令中完成,可以通过&符号连接多个RUN语句。RUN后面的必须是双引号不能是单引号(没引号貌似也不要紧),command是不会调用shell的,所以也不会继承相应变量,要查看输入RUN “sh” “-c” “echo” “HOME",而不是RUN"echo""
HOME",而不是RUN"echo""HOME”。

4.EXPOSE
告诉Docker服务器容器对外映射的容器端口号,在docker run -p的时候生效。

5.ENV
设置环境变量,变量可以被后续的指令使用

6.ADD
说明:复制本机文件或目录或远程文件,添加到指定的容器目录,支持GO的正则模糊匹配。路径是绝对路径,不存在会自动创建。如果源是一个目录,只会复制目录下的内容,目录本身不会复制。ADD命令会将复制的压缩文件夹自动解压,这也是与COPY命令最大的不同。

7.COPY
说明:COPY除了不能自动解压,也不能复制网络文件。其它功能和ADD相同。

8.VOLUME
说明:在主机上创建一个挂载,挂载到容器的指定路径。docker run -v命令也能完成这个操作,而且更强大。这个命令不能指定主机的需要挂载到容器的文件夹路径。但docker run -v可以,而且其还可以挂载数据容器

9.WORKDIR
为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工
作目录,如果目录不存在会自动创建。

10.CMD 与 ENTRYPOINT
这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。

docker run后面的参数可以传递给ENTRYPOINT指令当作参数。

Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。

二.使用Dockfile构建镜像

1.在容器中执行相应的命令

1.清理实验环境,删除创建的容器及其相应的镜像

[root@server1 ~]# docker rm -f vm2
[root@server1 ~]# docker rm -f vm1
[root@server1 ~]# docker rmi ubuntu:v1
[root@server1 ~]# docker rmi ubuntu:v2

2.下载rhel7的镜像并且将镜像导入本地

[root@server1 ~]# ls
anaconda-ks.cfg  docker  game2048.tar  rhel7.tar  ubuntu.tar
[root@server1 ~]# docker load -i rhel7.tar 

3.以该镜像建立容器并且指定其工作环境为bash,进入容器之后是读bash下的文件的,但是可以写入文件

在这里插入图片描述

编写repo文件需要在文件中添加yum源:

在这里插入图片描述

4.下载htppd时会出现下面报错,是因为rpm数据库损坏需要重建

在这里插入图片描述

因此需要在 “yum install …” 前使用 “rpm –rebuilddb” 重建数据库,再次安装如下:

在这里插入图片描述

会显示httpd已经安装,但是实际在安装htppd的时候出现了问题,在容器内是由root用户的,如果命令执行成功则会返回给用户0,则证明该条命令的返回数值为0

发现在容器中执行相应的命令后无法成功安装httpd,因此就是要构建新的镜像里面添加新的应用。

补充知识:

Linux user namespace 为正在运行的进程提供安全相关的隔离(其中包括 uid 和 gid),限制它们对系统资源的访问,而这些进程却感觉不到这些限制的存在。

对于容器而言,阻止权限提升攻击(privilege-escalation attacks)的最好方法就是使用普通用户权限运行容器的应用程序。

然而有些应用必须在容器中以 root 用户来运行,这就是我们使用 user namespace 的最佳场景。我们通过 user namespace 技术,把宿主机中的一个普通用户(只有普通权限的用户)映射到容器中的 root 用户。在容器中,该用户在自己的 user namespace 中认为自己就是 root,也具有 root 的各种权限,但是对于宿主机上的资源,它只有很有限的访问权限(普通用户)。

2.Dockfile构建新的镜像

1.在/tmp/docker中编写Dockerfile文件

[root@server1 ~]# mkdir -p /tmp/docker
[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# vim Dockerfile
文件编辑内容如下:
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

在这里插入图片描述

RUN指令做的是在镜像里安装一些软件,或者做一些需要的操作。Docker RUN之后执行了Shell指令,它对镜像里面的内容做了一些改动,最后再执行Docker COMMIT,把当前容器里面的改动持久化到镜像里面。RUN命令可以执行多次。但是通常来说建议把需要的指令都写在一条RUN命令里面,用&&符号连接起来,好处是镜像只增加了一层,可以加快镜像构建的速度,减少镜像的层次。

2.创建构建新镜像时所要用到的yum源文件

[root@server1 docker]# pwd
/tmp/docker
[root@server1 docker]# vim dvd.repo
文件编辑内容如下:
[rhel7.3]
name=rhel7.3
baseurl=http://172.25.254.77/file
gpgcheck=0

3.根据给定的Dockerfile和上下文以构建Docker镜像,注意后面要加点,代表是在当前目录下面

在这里插入图片描述

会出现执行过程,并且最后显示安装完成

在这里插入图片描述
查看时可以发现新构建的镜像:

在这里插入图片描述

4.以新建的镜像运行容器要添加端口映射并且查看端口

[root@server1 docker]# docker run -d --name apache -p 80:80  rhel7:v1 

在这里插入图片描述

浏览器上访问查看:

在这里插入图片描述
5.在Dockerfile中添加访问测试页再次测试

//在dockerfile中添加访问默认测试页:
[root@server1 docker]# pwd
/tmp/docker
[root@server1 docker]# vim Dockerfile 
文件编辑内容如下:
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd
COPY index.html /var/www/html/index.html
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

//在该目录下编辑默认访问测试页的文件:
[root@server1 docker]# vim index.html
文件编辑内容如下:
<h1>www.westos.org</h1>

//再次以该dockerfile生成新的镜像
[root@server1 docker]# docker build -t rhel7:v2 .

//使用该镜像新建容器
[root@server1 docker]# docker run -d --name apache -p 80:80  rhel7:v2

在浏览器上再次查看,为添加默认访问页面下的内容

在这里插入图片描述

6.创建容器时对其指定挂载点

//运行容器指定挂载点,注意指定之后会在该目录下自动生成website挂载点
[root@server1 docker]# docker run -d --name apache -p 80:80 -v /tmp/docker/website:/var/www/html rhel7:v2
//编辑挂载点下的测试文件
[root@server1 docker]# ls
Dockerfile  dvd.repo  index.html  website
[root@server1 docker]# cd website/
[root@server1 website]# ls
[root@server1 website]# vim index.html
文件编辑内容如下:
<h1>zll.westos.org zll.westos.org</h1>

在浏览器再次测试查看:

在这里插入图片描述

三.对镜像进行优化

1.下载nginx的镜像并且导入到本地

[root@server1 ~]# ls
anaconda-ks.cfg  docker        nginx-1.15.8.tar.gz  rhel7.tar
busybox.tar      game2048.tar  nginx.tar            ubuntu.tar
[root@server1 ~]# docker load -i nginx.tar 

2.下载nignx的安装包到本地,因为实验中需要用到,并且编写dockfile文件

//在/tmp/docker中添加已经下载的nginx的安装包
[root@server1 ~]# mv nginx-1.15.8.tar.gz /tmp/docker/
[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# ls
Dockerfile  dvd.repo  index.html  nginx-1.15.8.tar.gz  website

//编写Dockfile文件
[root@server1 docker]# vim Dockerfile 
文件编辑内容如下:
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD  nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc make zlib-devel pcre-devel
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure  --prefix=/usr/local/nginx
RUN make
RUN make install
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

//以dockerfile生成新的镜像
[root@server1 docker]# ls
Dockerfile  dvd.repo(yum源文件之前已经写好)  index.html  nginx-1.15.8.tar.gz(nginx安装包)
[root@server1 docker]# docker build -t nginx:v1 .

//查看生成的镜像

//使用新生成的镜像运行容器
[root@server1 docker]# docker run -d --name nginx -p 80:80 nginx:v1   -d表示打入后台,-f表示添加端口映射

在这里插入图片描述
查看生成的镜像及其内存大小为276MB:

在这里插入图片描述

在浏览器查看:

在这里插入图片描述

3.重新编写dockerfile文件添加端口及其挂载点

//编写dockerfile:
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD  nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc make zlib-devel pcre-devel
RUN sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure  --prefix=/usr/local/nginx
RUN make
RUN make install
EXPOSE 80   端口
VOLUME ["/usr/local/nginx/html"]  挂载点
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

//删除原来生成的镜像并建立新的镜像

在这里插入图片描述

//运行新的镜像:

在这里插入图片描述

//使用新的镜像运行容器
在这里插入图片描述

//查看运行的容器的详细信息会发现挂载点

在这里插入图片描述

在这里插入图片描述

//在挂载点上添加要发布的内容,挂载点下默认有测试页及其相关内容

在这里插入图片描述

//在浏览器上查看

在这里插入图片描述

//查看挂载点并且清空挂载点

在这里插入图片描述

镜像的优化:

1.减少镜像层数

//编辑dockerfile
[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# vim Dockerfile 
文件编写的内容如下:
FROM rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD  nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc make zlib-devel pcre-devel && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc &&  ./configure  --prefix=/usr/local/nginx && make &&  make install
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

//运行新的镜像v2并且查看大小,发现比v1少了20MB
[root@server1 docker]# docker build -t nginx:v2 .
[root@server1 docker]# docker images nginx
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               v2                  57c313c825dd        22 seconds ago      250MB
nginx               v1                  0f28d8eb67fe        20 minutes ago      276MB

2.清理镜像构建的中间产物并且使用多阶段构建镜像

//编辑dockerfile
[root@server1 docker]# pwd
/tmp/docker
[root@server1 docker]# vim Dockerfile 
文件
FROM rhel7 as build
COPY dvd.repo /etc/yum.repos.d/dvd.repo
ADD  nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc make zlib-devel pcre-devel && yum clean all && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc &&  ./configure  --prefix=/usr/local/nginx && make &&  make install &&rm -rf /mnt/nginx-1.15.8


FROM rhel7
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

在这里插入图片描述//重新以dockerfile创建新的镜像并且查看大小发现变为144MB
在这里插入图片描述

在这里插入图片描述

3.终极优化从底层优化

//下载distroless镜像并且进行本地导入
[root@server1 docker]# docker load -i distroless.tar

//编写dockerfile
[root@server1 docker]# pwd
/tmp/docker
[root@server1 docker]# 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 docker]# docker build -t busybox:v5  .

查看发现优化后变为20多MB
在这里插入图片描述

//使用新的镜像运行容器看是否能够使用

在这里插入图片描述

输入http://172.25.254.1/ ,发现访问成功

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值