文章最后更新时间: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 . (注意有一个点)
四、基于新镜像创建运行新nginx容器
[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
效果图: