Dockerfile 定制Nginx镜像

柳三千

文章最后更新时间:2022年11月08日已超过752天没有更新。

前言:

  Dockfile是一个用于编写docker镜像生成过程的文件,其有特定的语法。在一个文件夹中,如果有一个名字为Dockfile的文件,其内容满足语法要求,在这个文件夹路径下执行命令:docker build -t name:tag .,就可以按照描述构建一个镜像了!(name是镜像的名字)

  制作镜像的时候,一定要理解镜像分层的概念,你下载官方简化版centos镜像有多少层?你基于简化centos镜像制作新的镜像,又添加多少层呢?理论上,一个容器的镜像,最多可以有127层,问题来了,怎么查看镜像的层数?

1、 docker history 命令就得到正确的答案了,那就是,docker history命令执行时,只看SIZE 大于0的行!

[root@localhost docker_images]# docker history centos_nginx:1.20
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
ac20103ed758   3 days ago      /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "ngin…   0B        
ec1fd1e45ed5   3 days ago      /bin/sh -c #(nop)  EXPOSE 80                    0B        
58618fd69d9c   3 days ago      /bin/sh -c #(nop) WORKDIR /usr/local/nginx/     0B        
2da69b9e24e2   3 days ago      /bin/sh -c #(nop)  ENV PATH=/usr/local/sbin:…   0B        
52ae7bfba773   3 days ago      /bin/sh -c ./configure --prefix=/usr/local/n…   27.9MB    
db85c3ef27c6   3 days ago      /bin/sh -c #(nop) WORKDIR /usr/local/nginx-1…   0B        
52b0a917d776   3 days ago      /bin/sh -c #(nop) ADD file:8c96cbcb0fc1f4a79…   6.4MB     
930032c3aa9b   3 days ago      /bin/sh -c ./configure && make && make insta…   9.69MB    
47f1e266ba57   3 days ago      /bin/sh -c #(nop) WORKDIR /usr/local/pcre-8.…   0B        
03a8be5705b9   3 days ago      /bin/sh -c #(nop) ADD file:e5f245127035870b4…   9.05MB    
f629d8acca91   3 days ago      /bin/sh -c yum -y install make zlib zlib-dev…   374MB     
6c9f58d58724   3 days ago      /bin/sh -c #(nop)  MAINTAINER LDX<xxx.163.co…   0B        
25c1784b5045   10 days ago     bash                                            548B      time calibration
0c0f2dcf7afd   15 months ago   RUN /bin/sh -c yum install wget -y     && mv…   64.5MB    buildkit.dockerfile.v0
<missing>      15 months ago   MAINTAINER "author=yangdejun update=2021-08-…   0B        buildkit.dockerfile.v0
<missing>      2 years ago     /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
<missing>      2 years ago     /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
<missing>      2 years ago     /bin/sh -c #(nop) ADD file:72b194edf3abedf51…   203MB


以上得知,我新制作的size大于0的有八行,也就是有八层,那我基于centos7.8的镜像有多少层呢?

[root@localhost docker_images]# docker images
REPOSITORY                  TAG       IMAGE ID       CREATED         SIZE
centos_nginx                1.20      ac20103ed758   3 days ago      694MB
centos                      7.8       25c1784b5045   10 days ago     268MB
centos_vim                  7.8       e619078d3432   11 days ago     546MB
nginx                       latest    51086ed63d8c   4 weeks ago     142MB
ubuntu                      latest    216c552ea5ba   4 weeks ago     77.8MB
centos                      latest    5d0da3dc9764   13 months ago   231MB
martonyang/centos7.8.2003   latest    0c0f2dcf7afd   15 months ago   268MB
[root@localhost docker_images]# docker history 25c1784b5045
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
25c1784b5045   10 days ago     bash                                            548B      time calibration
0c0f2dcf7afd   15 months ago   RUN /bin/sh -c yum install wget -y     && mv…   64.5MB    buildkit.dockerfile.v0
<missing>      15 months ago   MAINTAINER "author=yangdejun update=2021-08-…   0B        buildkit.dockerfile.v0
<missing>      2 years ago     /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
<missing>      2 years ago     /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
<missing>      2 years ago     /bin/sh -c #(nop) ADD file:72b194edf3abedf51…   203MB

以上两个案例前三次镜像分层是否一样?我基于centos7.8制作的nginx镜像,最下面几层肯定是一样的,好好感受下分层的概念!


2、通过docker inspect 命令,寻找RootFS代码片段,在Layers中,有多少行(sha256)就代表镜像有多少层

[root@localhost docker_images]# docker inspect ac20103ed758
"RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:fb82b029bea0a2a3b6a62a9c1e47e57fae2a82f629b2d1a346da4fc8fb53a0b6",
                "sha256:c0cd7924335682967ab4689ff4a93cbabca6a29a856b59c8afe9bd19f50acef9",
                "sha256:199048ec1cd0a30e395c8576bc50fb41521a828da6d254d6cb87fcdeb87cbf2e",
                "sha256:7d14007007c4116285020229b0b80ca905c9e5da3e02f4420aab9794187a3ba5",
                "sha256:54bbee18d5e57c57dee2fd9dc78190ff73a9332ff74ea2caa03d038aabd59a7b",
                "sha256:ff5a2abea1cc7a2b998f497e372a6c2dd31ad1fac0eea080702876887964816e",
                "sha256:d94be22f19c5704ba8aa0504ddf23a635f2f73f1f02f201027b9af9f74800d80",
                "sha256:ba35802c1d21bb162e940819c067629fcf619d397b378847cfaa6b13512f8f79"
            ]
        },
        "Metadata": {
            "LastTagTime": "2022-11-04T11:50:22.594297543+08:00"
        }
    }
]

这些层是怎么来的?

  在Dockerfile中的ADD、COPY、RUN,或者创touch建新(配置)文件的命令,都会触发新建一层镜像,这层镜像一般会被称为中间层镜像(它类似游戏的存档,可以随时回来玩儿,也类似于一种缓存机制,使得后续镜像可以复用),直接通过docker images命令是看不到的(docker image ls -a 可以看到)。

Dockerfile指令说明简洁版:
 FROM         构建镜像基于哪个镜像
 MAINTAINER   镜像维护者姓名或邮箱地址
 RUN          构建镜像时运行的指令
 CMD          运行容器时执行的shell环境
 VOLUME       指定容器挂载点到宿主机自动生成的目录或其他容器
 USER         为RUN、CMD、和 ENTRYPOINT 执行命令指定运行用户
 WORKDIR      为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录
 HEALTHCHECH  健康检查
 ARG          构建时指定的一些参数
 EXPOSE       声明容器的服务端口(仅仅是声明)
 ENV          设置容器环境变量
 ADD          拷贝文件或目录到容器中,如果是URL或压缩包便会自动下载或自动解压
 COPY         拷贝文件或目录到容器中,跟ADD类似,但不具备自动下载或解压的功能
 ENTRYPOINT   运行容器时执行的shell命令

任务环境:

  基于centos7.8的系统安装Nginx服务

一、准备官方centos7.8镜像并完善时间校准

[root@localhost ~]# docker images
REPOSITORY                  TAG       IMAGE ID       CREATED         SIZE
martonyang/centos7.8.2003   latest    0c0f2dcf7afd   14 months ago   268MB

[root@localhost ~]# docker run -it martonyang/centos7.8.2003 bash

[root@ec22e09ae181 /]# cat /etc/redhat-release 
CentOS Linux release 7.8.2003 (Core)


容器里面时间不准确,校准时区

[root@localhost ~]# docker run -it --name centos7 martonyang/centos7.8.2003 bash
[root@f3a8b1015053 /]# date
Fri Oct 28 08:11:27 UTC 2022
[root@f3a8b1015053 /]# mv /etc/localtime /root/localtime.bak
[root@f3a8b1015053 /]# cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
[root@f3a8b1015053 /]# date
Fri Oct 28 16:12:23 CST 2022


提交一个新的镜像

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE                       COMMAND   CREATED         STATUS         PORTS     NAMES
f3a8b1015053   martonyang/centos7.8.2003   "bash"    4 minutes ago   Up 4 minutes             centos7

#提交新镜像
[root@localhost ~]# docker commit -m="time calibration" -a="ldx" f3a8b1015053 centos:7.8
sha256:25c1784b504586e43b895a751280950a34e5bb33a632fb96f37c7cee82b10345

[root@localhost ~]# docker images
REPOSITORY                  TAG       IMAGE ID       CREATED         SIZE
centos                      7.8       25c1784b5045   7 seconds ago   268MB
centos_vim                  7.8       e619078d3432   25 hours ago    546MB
nginx                       latest    51086ed63d8c   3 weeks ago     142MB
ubuntu                      latest    216c552ea5ba   3 weeks ago     77.8MB
centos                      latest    5d0da3dc9764   13 months ago   231MB
martonyang/centos7.8.2003   latest    0c0f2dcf7afd   14 months ago   268MB

[root@localhost ~]# docker run --name centos7.8 -it 25c1784b5045 bash

#时间准确
[root@b1874719f4d7 /]# date
Fri Oct 28 16:17:53 CST 2022


二、新建一个目录,编写Dockfile文件

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

[root@localhost ~]# mkdir /docker_images
[root@localhost ~]# cd /docker_images/
#该目录下准备好两个安装包
[root@localhost docker_images]# ls
nginx-1.20.2.tar.gz  pcre-8.35.tar.gz
[root@localhost docker_images]# vim Dockerfile
#基于该镜像构成新的镜像
FROM centos:7.8

#作者维护信息
MAINTAINER LDX<xxx.163.com>

#安装依赖包
RUN yum -y install make zlib zlib-devel gcc-c++ libtool  openssl openssl-devel

#导入并解压pcre-8.35文件
ADD pcre-8.35.tar.gz /usr/local/

#切换到pcre-8.35目录,类似于CD效果
WORKDIR  /usr/local/pcre-8.35

#编译安装
RUN ./configure && make && make install

#导入并解压nginx-1.20文件
ADD nginx-1.20.2.tar.gz /usr/local/

#切换到nginx-1.20.2目录
WORKDIR /usr/local/nginx-1.20.2

#编译安装
RUN ./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre=/usr/local/pcre-8.35 && make && make install

#设置环境变量
ENV PATH $PATH:/usr/local/nginx/sbin

#切换到nginx目录
WORKDIR /usr/local/nginx/

#展示80端口
EXPOSE 80

#使得nginx运行在前台,所有信息直接输出控制台
CMD nginx -g 'daemon off;'


注意事项:

之前自定义构建nginx,很多都是运行失败的,一运行容器就自动关闭,仿佛从来没运行过一样,上网找了大量资料,终于解决此问题:

Dockerfile 启动命令
docker run启动结果
CMD nginx端口无映射
CMD nginx -g 'daemon off;'端口正常映射
CMD ['nginx']
端口无映射
CMD["nginx","-g","daemon off;"]
端口正常映射

   执行失败是因为docker容器默认会把容器内部第一个进程,也就是pid=1的程序作为docker容器是否正在运行的依据,如果docker容器里pid=1的进程结束了,那么docker容器便会直接退出。
   docker run的时候把command为容器内部命令,如果使用nginx,那么nginx程序将后台运行,这个时候nginx并不是pid为1的程序,而是执行bash,这个bash执行了nginx指令后就结束了,所以容器也就退出,端口没有进行映射。
   所以就需要加-g 'daemon off;'的启动参数。daemon的作用是否让nginx运行后台;默认为on,调试时可以设置为off,使得nginx运行在前台,所有信息直接输出控制台。

参考链接:https://blog.csdn.net/zyy247796143/article/details/110457652


三、根据Dockferile文件构建新的nginx镜像

#docker build -t 新镜像的名字:版本号 .
docker build -t centos_nginx:1.20 .  (注意有一个点)

图片.png


四、基于新镜像创建运行新nginx容器

图片.png

[root@localhost docker_images]# docker ps
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS         PORTS                                     NAMES
8e687e521a1a   centos_nginx:1.20   "/bin/sh -c 'nginx -…"   2 minutes ago   Up 2 minutes   0.0.0.0:49153->80/tcp, :::49153->80/tcp   naughty_sammet


效果图:

图片.png



文章版权声明:除非注明,否则均为柳三千运维录原创文章,转载或复制请以超链接形式并注明出处。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码