Linux企业运维篇——docker镜像的创建及镜像的优化方法

接上一篇docker文章

一.导入rhel7.tar镜像

dockerfile常用指令

dockerfile常用指令
FROM 指定base镜像,如果本地不存在会从远程仓库下载。
MAINTAINER 设置镜像的作者,比如用户邮箱等。
COPY 把文件从build context复制到镜像支持两种形式COPY src dest 和 COPY [“src”, “dest”]。src必须指定build context中的文件或目录
ADD 用法与COPY类似,不同的是src可以是归档压缩文件,文件会被自动解压到dest,也可以自动下载URL并拷贝到镜像ADD html.tar /var/www或ADD http://ip/html.tar /var/www
ENV 设置环境变量,变量可以被后续的指令使用:ENV HOSTNAME sevrer1.example.com
VOLUME 申明数据卷,通常指定的是应用的数据挂在点:VOLUME ["/var/www/html"]
EXPOSE 如果容器中运行应用服务,可以把服务端口暴露出去:EXPOSE 80
WORKDIR 为RUN、CMD、ENTRYPOINT、ADD和COPY指令设置镜像中的当前工作目录,如果目录不存在会自动创建。
RUN 在容器中运行命令并创建新的镜像层,常用于安装软件包:RUN yum install -y vim
CMD 与 ENTRYPOINT 这两个指令都是用于设置容器启动后执行的命令,但CMD会被docker run后面的命令行覆盖,而ENTRYPOINT不会被忽略,一定会被执行。docker run后面的参数可以传递给ENTRYPOINT指令当作参数。Dockerfile中只能指定一个ENTRYPOINT,如果指定了很多,只有最后一个有效。

在tmp目录下建立docker文件夹,并建立Dockerfile文件

[root@server1 ~]# cd /tmp/
[root@server1 tmp]# mkdir docker
[root@server1 tmp]# cd docker/
[root@server1 docker]# touch Dockerfile

查看已有的镜像

[root@server1 ~]# docker images 

在这里插入图片描述

删除已有镜像的方法

docker rmi 镜像名称:版本名称

[root@server1 ~]# docker rmi ubuntu:v1

在这里插入图片描述
如果在删除镜像时正在被使用是无法删除(可以强制删除),可以先删除对应的容器,再删除镜像

 [root@server1 ~]# docker rmi ubuntu:v2
 Error response from daemon: conflict: unable to remove repository reference "ubuntu:v2" (must force) - container bff47c284a0f is using its referenced image 3433d210d0ff

在这里插入图片描述
查看所有容器进程

[root@server1 docker]# docker ps -a

在这里插入图片描述
删除vm2容器

[root@server1 docker]# docker rm vm2
vm2

再次删除ubuntu:v2就可以了

[root@server1 ~]# docker rmi ubuntu:v2

在这里插入图片描述
查看导入的所有镜像

[root@server1 ~]# docker images

在这里插入图片描述
导入rhel7镜像

[root@server1 ~]# docker load -i rhel7.tar 
[root@server1 ~]# docker images

在这里插入图片描述

[root@server1 ~]# docker history rhel7:latest 

在这里插入图片描述

[root@server1 ~]# docker run -it --name vm2 rhel7 bash #bash
bash-4.2# ls
bin   dev  home  lib64	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 media	opt  root  sbin  sys  usr
bash-4.2# cd /etc/yum.repos.d/
bash-4.2# ls
rhel7.repo
bash-4.2# vi dvd.repo #rhel7镜像还没有vim的命令,所以使用vi命令

在这里插入图片描述

bash-4.2# yum clean all

在这里插入图片描述

bash-4.2# yum repolist  #可以列出就说明yum源没有问题

在这里插入图片描述
在安装软件时可能出现以下rpm数据库问题。解决方法如下

bash-4.2# yum install -y httpd
Rpmdb checksum is invalid: dCDPT(pkg checksums): systemd-libs.x86_64 0:219-30.el7 - u

在这里插入图片描述
最后一行显示出问题
在这里插入图片描述

bash-4.2# rpmdb --rebuilddb  #从已安装的包头文件,反向重建RPM数据库

在这里插入图片描述

  bash-4.2# yum install -y httpd #重新安装httpd服务就可以

ctrl+D退出rhel7

bash-4.2# exit

在这里插入图片描述

[root@server1 ~]# docker rm vm2
vm2

在这里插入图片描述
编辑之前的Dockerfile文件

[root@server1 docker]# cd /tmp/docker/
[root@server1 docker]# vim Dockerfile 
FROM rhel7  #源镜像是rhel7
COPY dvd.repo /etc/yum.repos.d/dvd.repo
RUN rpmdb --rebuilddb && yum install -y httpd
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

在这里插入图片描述

[root@server1 docker]# vim dvd.repo
[dvd]
name=rhel7.3
baseurl=http://172.25.70.250/westos
gpgcheck=0

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

[root@server1 docker]# docker build -t rhel7:v1 .  #.表示在当前目录下


在这里插入图片描述

[root@server1 docker]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rhel7               v1                  3b4803a9cfd0        4 minutes ago       193MB

在这里插入图片描述
可以看到多了三层,就是Dockerfile文件里执行的

[root@server1 docker]# docker history rhel7:v1
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
3b4803a9cfd0        7 minutes ago       /bin/sh -c #(nop)  CMD ["/usr/sbin/httpd" "-…   0B                  
af9674ea515d        7 minutes ago       /bin/sh -c rpmdb --rebuilddb && yum install …   52.7MB              
74ffa6d4e593        7 minutes ago       /bin/sh -c #(nop) COPY file:d3452dc04a09ad4d…   66B                 
0a3eb3fde7fd        4 years ago                                                         140MB               Imported from -

在这里插入图片描述

[root@server1 docker]# cat Dockerfile 

在这里插入图片描述
删除之前建立的2048小游戏容器vm1

[root@server1 docker]# docker rm vm1

在这里插入图片描述
运行rhel7:v1,起名为apache,端口映射为80

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

在这里插入图片描述
在浏览器中访问172.25.70.1可以看见apache的官方页面
在这里插入图片描述
添加默认访问页

[root@server1 docker]# vim index.html
welcome to China!

在这里插入图片描述

[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"]

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

[root@server1 docker]# docker build -t rhel7:v2 .

在这里插入图片描述

[root@server1 docker]# docker history rhel7:v2

在这里插入图片描述
强制删除

[root@server1 docker]# docker rm -f apache
apache

在这里插入图片描述

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

在这里插入图片描述
浏览器重新访问就会看到设置的默认发布页
在这里插入图片描述
强制删除apache容器(也可以不删除,但是以后建立的容器名称不能重复)

[root@server1 docker]# docker rm -f apache 
apache

指定路径

[root@server1 docker]# docker run -d --name apache -p 80:80 -v /tmp/docker/website/:/var/www/html rhel7:v2
ae77f2ed404a6df542e341ef1c1e897c1692a382167d586ac91bb17e260951e6

在这里插入图片描述

[root@server1 docker]# docker inspect apache

在这里插入图片描述
修改默认发布页的内容

[root@server1 docker]# cd website/
[root@server1 website]# ls
index.html
[root@server1 website]# vim index.html    
welcome to China!
hello world!

在这里插入图片描述
重新访问172.25.70.1
在这里插入图片描述

 [root@server1 website]# docker images

在这里插入图片描述

[root@server1 docker]# docker run -it --name vm1 rhel7 bash

在这里插入图片描述

二.导入busybox.tar镜像,比较Shell和exec格式

获得 busybox.tar镜像,导入

[root@server1 ~]# docker load -i busybox.tar 

在这里插入图片描述

[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# vim Dockerfile #shell格式
FROM rhel7
ENV name world
ENTRYPOINT echo "hello, $name"

在这里插入图片描述

[root@server1 docker]# docker build -t busybox:v1 .

在这里插入图片描述

[root@server1 docker]# docker run --rm busybox:v1 # --rm表示执行过后就删除
hello, world

在这里插入图片描述
Shell格式底层会调用/bin/sh -c来执行命令,可以解析变量,而下面
的exec格式不会

[root@server1 docker]# vim Dockerfile 
FROM rhel7
ENV name world
ENTRYPOINT ["/bin/echo","hello, $name"]

在这里插入图片描述
重新构建镜像尝试

[root@server1 docker]# docker build -t busybox:v2 .

在这里插入图片描述

[root@server1 docker]# docker run --rm busybox:v2
hello, $name

在这里插入图片描述

正确的exec格式如下

[root@server1 docker]# vim Dockerfile 
FROM rhel7
ENV name world
ENTRYPOINT ["/bin/sh", "-c", "echo hello, $name"]

在这里插入图片描述
[root@server1 docker]# docker build -t busybox:v3 .
在这里插入图片描述

[root@server1 docker]# docker run --rm busybox:v3 hello, world

在这里插入图片描述

Exec格式时,ENTRYPOINT可以通过CMD提供额外参数,CMD的额外
参数可以在容器启动时动态替换。在shell格式时ENTRYPOINT会忽略
任何CMD或docker run提供的参数。

[root@server1 docker]# vim Dockerfile 
FROM rhel7
ENTRYPOINT ["/bin/echo","hello"]
CMD ["world"]

在这里插入图片描述

[root@server1 docker]# docker build -t busybox:v4 .

在这里插入图片描述

[root@server1 docker]# docker run --rm busybox:v4
hello world

在这里插入图片描述

[root@server1 docker]# docker run --rm busybox:v4 westos
hello westos

在这里插入图片描述

三.在rhel7镜像中搭建nginx,优化镜像

镜像的优化方法:

l 选择最精简的基础镜像
l 减少镜像的层数
l 清理镜像构建的中间产物
l 注意优化网络请求
l 尽量去用构建缓存
l 使用多阶段构建镜像

搭建nginx
首先要获取nginx-1.15.8.tar.gz包和nginx.tar镜像

[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;"]

在这里插入图片描述
把nginx-1.15.8.tar.gz移动到/tmp/docker目录下

[root@server1 ~]# mv nginx-1.15.8.tar.gz /tmp/docker/

构建nginx镜像

[root@server1 ~]# cd /tmp/docker/
[root@server1 docker]# docker build -t nginx:v1 . #构建过程中可以看见下载和编译的过程

在这里插入图片描述

[root@server1 docker]# docker build -t nginx:v1 .

在这里插入图片描述
可以看出nginx:v1有276M,这算是很大的了

[root@server1 docker]# docker images nginx 

在这里插入图片描述
删除所有容器,清除环境

[root@server1 docker]# docker ps -a 
[root@server1 docker]# docker rm vm1
vm1
[root@server1 docker]# docker rm -f apache
apache
[root@server1 docker]# docker run -d --name nginx -p 80:80 nginx:v1
cd36daf667548967288b5c1f75ae3b2c98f26e4642e56d1e73db1876c3222cab

在这里插入图片描述
访问172.25.70.1出现nginx欢迎界面
在这里插入图片描述

[root@server1 docker]# docker rm -f nginx
nginx

构建第二个nginx镜像

[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
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]

在这里插入图片描述

[root@server1 docker]# docker build -t nginx:v2 .

在这里插入图片描述

[root@server1 docker]# docker run -d --name nginx -p 80:80 nginx:v2
e45c9d75c309d8f878bc6107489678e3a01cbf45d5a712c613d023a405b0f87b

在这里插入图片描述
比较两个镜像的层级

[root@server1 docker]# docker history nginx:v1

在这里插入图片描述

[root@server1 docker]# docker history nginx:v2

在这里插入图片描述

[root@server1 docker]# docker inspect nginx

在这里插入图片描述

[root@server1 docker]# cd /var/lib/docker/volumes/cb19d35ba4f2340578f6aaf1b90decd14842d9994817dcbd89275ebc9c7b4259/_data
[root@server1 _data]# ls
50x.html  index.html

index.html里写的是nginx的欢迎页面

[root@server1 _data]# cat index.html 

在这里插入图片描述
编写一个测试页test.html

[root@server1 _data]# vim test.html
www.test.org

在这里插入图片描述
访问172.25.70.1/test.html
在这里插入图片描述
删除nginx容器,但是数据还在

[root@server1 _data]# cd
[root@server1 ~]# docker rm -f nginx
nginx
[root@server1 ~]# cd -
/var/lib/docker/volumes/cb19d35ba4f2340578f6aaf1b90decd14842d9994817dcbd89275ebc9c7b4259/_data
[root@server1 _data]# ls
50x.html  index.html  test.html

查看之前的卷数据

[root@server1 ~]# docker volume ls

在这里插入图片描述
清除所有没有使用的卷数据

[root@server1 ~]# docker volume prune 

在这里插入图片描述
再次查看已经没有卷数据了
[root@server1 ~]# docker volume ls
在这里插入图片描述
查看容器进程

[root@server1 ~]# docker ps
[root@server1 ~]# docker ps -a

在这里插入图片描述
清理没有使用的容器

[root@server1 ~]# docker container prune 

在这里插入图片描述

1.减少镜像层数,清理镜像构建的中间产物

[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 && 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 #清理中间产物 /mnt/nginx-1.15.8
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]

在这里插入图片描述

[root@server1 docker]# docker build -t nginx:v3 .

在这里插入图片描述
查看重构后的镜像大小,比原来小了26MB

   [root@server1 docker]# docker images nginx

在这里插入图片描述

2.使用多阶段构建镜像
编辑Dockerfile

[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;"]

在这里插入图片描述

[root@server1 docker]# docker build -t nginx:v4 .

在这里插入图片描述
查看大小减小到141M

[root@server1 docker]# docker images nginx

在这里插入图片描述

[root@server1 docker]# docker run -d --name nginx -p 80:80 nginx:v4

在这里插入图片描述

[root@server1 docker]# curl 172.17.0.2

在这里插入图片描述

3.选择最精简的基础镜像
可以在https://github.com/GoogleContainerTools上下载
获取distroless.tar ,加载镜像

[root@server1 ~]# cd
[root@server1 ~]# docker load -i distroless.tar 
668afdbd4462: Loading layer  18.39MB/18.39MB
Loaded image: gcr.io/distroless/base:lates

编辑Dockerfile文件

[root@server1 ~]# cd -
[root@server1 docker]# vim Dockerfile 
FROM nginx:1.14.2 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 /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 docke]# docker build -t nginx:v5 .

在这里插入图片描述
查看重构后的镜像大小,只有23.5MB,所以在实际构建中尽量选择最精简的base镜像。

[root@server1 docker]# docker images nginx

在这里插入图片描述
删除之前的nginx容器

[root@server1 docker]# docker rm -f nginx
nginx

在这里插入图片描述

[root@server1 docker]# docker run -d --name nginx -p 80:80 nginx:v5
27e74db0b00a748fb9f9f3fa5b881bb0be7cf2f2776d460bd1537f81d99f6f82

在这里插入图片描述
查看ip地址

[root@server1 docker]# docker inspect nginx

在这里插入图片描述
看到nginx欢迎界面的html语句说明nginx搭建没有问题

[root@server1 docker]# curl 172.17.0.2

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44321116/article/details/90679868