第4节 Dockerfile常见指令用法

ARG,变量

类似ENV,不过ENV是build阶段定义的变量,docker run阶段也同样可以使用

ARG只能在build阶段生效。

使用场景:

1、ENV就是build阶段定义的变量赋值,然后docker run阶段可以使用-e修改掉

2、ARG就是build阶段定义用的,docker run起来就没有这些变量了。

3、ARG可以写到FROM前面

image-20240514110509107

ARG常用来定义版本号👇

ARG VERSION=3.20.0
FROM alpine-base:$VERSION
LABEL maintainer="oneyearice <oneyearice@gmail.com>"

ARG NGINX_VERSION=1.26.0
ADD nginx-$NGINX_VERSION.tar.gz /usr/local/src/

RUN cd /usr/local/src/nginx-$NGINX_VERSION && ./configure --prefix=/apps/nginx && make && make install && ln -s /apps/nginx/sbin/nginx /usr/bin && addgroup -g 2024 -S nginx && adduser -s /sbin/nologin -S -D -u 2024 -G nginx nginx && mkdir /apps/nginx/conf/conf.d

COPY nginx.conf /apps/nginx/conf/nginx.conf

ADD index.html /apps/nginx/html/index.html
RUN chown -R nginx.nginx /apps/nginx/
#EXPOSE 80 443
#CMD nginx && tail -f /apps/nginx/logs/*
CMD ["nginx","-g","daemon off;"]

VOLUME,持久化

volume的目录可以自动创建的,无需事先创建

image-20240514120010489

相当于同时:①实现数据持久化②也顺便创建了目录

image-20240514120852534

image-20240514120652278

build成功就说明VOLUME创建了目录了,因为entrypoint.sh里有一句echo $HOST > ${DOC_ROOT}index.html没报错,说明目录OK的。

image-20240514120634773

目录exec进去可见

image-20240514121042408

而且整个VOLUME创建的目录是持久化的,所以是独立于容器的目录的

image-20240514121324413

这些LowerDir、MergerDir、UppereDir、WorkDir目录,容器删了,这些目录就没了

image-20240514121732133

但是volume是独立的文件持久化的

测试

image-20240514121959279

image-20240514122239429

image-20240514122415180

而且整个映射出来的宿主上的文件内容改了,容器里也同步的

image-20240514122759590

容器里的所有文件都是在宿主机上存放的其实~

mysql的数据就很需要volume持久化一下

Dockerfile里的VOLUME遗憾

但是宿主机上的目录名称没有任何识别度,就是自动生成的这些volume在宿主上的目录是无法维护的,你都不知道谁是谁👇

image-20240514123647925

容器如果删了,还可以docker inspect 查看谁是谁的谁,容器删了可就没法查了,只能编列cat里面的内容去一个个找了。

还有一个命令可以看volume的

image-20240514150728480

总之Dockerfile里的VOLUME就是没法指定宿主的映射目录的,只能这样,也算是一个缺点。怎么解决,docker run -v可以做宿主和容器里的目录映射,docker compose的yml也可以实现。

image-20240514180813842

image-20240514180831450

也可以使用VOLUME挂载多个容器里的目录出来

image-20240514181112144

EXPOSE仅仅是一个申明

申明的是-P要映射的端口是啥而已。至于是不是容器里监听的,也不一定,没有直接关系。

1、暴露端口的时候,可以用docker run -p 8080:80来 将容器里的80暴露到宿主的8080。

2、也可以用Dockerfile里的EXPOSE来说明容器里暴露的是80或443,但是宿主用哪个端口来对接就是在docker run -P来随机指定了,如果不像随机,那么还是用-p再次指定,此时Dockerfile里的EXPOSE就没意义了。

3、EXPOSE和VOLUME一个德行,都是仅仅申明容器里要暴露的端口和目录。至于暴露成宿主的哪个端口和路径,Dockerfile里没有解决,都是通过docker run -p和-v来解决,然而既然用了-p和-v,那么容器里的端口和目录都是直接写了,无需Dockerfile重复写了。 # 但是EXPOSE和VOLUME的区别是EXPOSE不管容器里是否监听某个端口,只是申明供-P暴露出来;而VOLME是容器里没有这个目录就给你自动创建出来(而且是mkdir -p 的方式来创建多层目录的),然后暴露成宿主的目录。

4、然后EXPOSE就是配合docker -P,大P来使用的,告诉大P暴露容器里的什么端口为宿主的随机端口。

5、凡是EXPOSE写的端口不是容器里监听的端口的,都是坏人~,哪家好人干这种事啊,对不对,不写也是不对的,总不能让别人去猜你nginx或其他app监听的啥吧,不猜就去找脚本,或者你要是默认编译的基本就是80了。

以下截图就看EXPOSE就行了,其他前面的内容

image-20240514182617343

image-20240514182638238

443只是暴露出来,并不代表容器里有监听443,而实际情况是容器里只监听了80,443没有开,暴露是80和443都暴露的,所以👇

image-20240514182731303

WORKDIR,切换工作目录

类似cd,切换文件夹的,确实切掉了,

但是如果在Dockerfile里 RUN cd xxx/xx/xx 也仅仅是在这一条RUN里切换了路径,下一行又回到容器里的/根了。实验测试下👇

1、原材料

image-20240515094644911

2、build

image-20240515094700929

2、run看效果👇

image-20240515094614219

所以RUN cd和WORKDIR是不一样的,前置式只在RUN cd的哪一行临时切过去,后面又回到了默认的/路径,而WORKDIR就是后面都切过去了。

至于RUN一行里用&& 还是; 都行,一行都是临时切过去了。

image-20240515095903604

image-20240515100158240

ONBUILD,

父镜像build指定的CMD在当时不执行,在子镜像build的时候才执行。

举例:rm -rf /,就是说父镜像ONBUILD制定了rm -rf /,一旦子镜像继承了就把子镜像的根删掉。 # 你要继承我,我就把你删了。。。 这里只是一个没人这个干的例子,呵呵。 也许你不想让别人用的镜像作为父镜像,就可以这么做,ONBUILD RUN rm -rf /* 呵呵。

那么问题来了:

WORKDIR /bin
ONBUILD touch helo.log

这个touch在子镜像build的时候创建的,那么是在子镜像的/下还是下/bin下呢?是子镜像的/bin下的,

因为子镜像FROM xxx的时候已经继承了WORKDIR的默认工作目录已经是/bin了,然后ONBUILD又是子镜像才执行显然是在FROM以后的。

1、首先父镜像里是没有touch helo.log文件的👇

image-20240515103149872

顺便看一个视频中的典型错误案例👇

image-20240515103423386

图中错误就是,entrypoint.sh不会被执行,因为找不到路径,

image-20240515104435532

理由很简单:你看下图是不是一样

image-20240515103500341

解释给你听哦:①你要让光秃秃的xxx.sh,这种不带绝对/相对路径的脚本直接执行,那就要让xxx.sh放到$PATH变量里的路径里去;②结果你上面COPY是放到/根③你WORDIR /切到/根,人家也不会去/当前目录根里找这个xxx.sh的。哈哈,不要学到了K8S还在这里闹小学一年级的笑话~还说什么WORKDIR没切过去,这是WORKDIR的事嘛~,基础不牢地动山摇,人心不稳王座倾塌。

下面就是Dockerfile制作一个父镜像,然后再Dockerfile.son做一个子镜像,其中父镜像里的是ONBUILD touch,哦错了,是ONBUILD RUN touch才对👇

image-20240515113331660

由于父镜像里已经WORKDIR /bin了,所以父镜像docker run起来进去就是/bin下的;

同样子镜像是继承的父镜像,所以子镜像的工作目录就是/bin的,所以再执行ONBUILD RUN touch helo.log就生成了文件了👇

image-20240515113645135

判断下ONBUILD的 echo的动作是在WORKDIR前还是后

image-20240515114127155

判读是在后,因为WORKDIR是父镜像build的时候就会执行,一旦执行,子镜像继承了就是工作目录默认就是/bin了,然后ONBUILD echo是CMD还是ENTRYPOINT啊,我的意思是在build阶段还是在docker run阶段生效啊? 就算ONBUILD是build生效,那也是子镜像执行,而子镜像FROM xxx继承父镜像这个FROM就是父镜像的WORKDIR已经完成了,所以ONBUILD是肯定是在WORKDIR的目录里的了。

​ 然后ONBUILD RUN或ONBUILD ENV、ONBUILD ARG、ONBUILD ENTRYPOINT

image-20240515114701564

再看

image-20240515115756000

buid一下,注意build的时候,镜像不要用之前的镜像名称,会有问题,待会单独研究。

image-20240515120431365

验证结论的时候到了,

image-20240515120645577

验证如下👇

image-20240515120602587

image-20240515120626395

看案例,就是父镜像没再次build导致子镜像还是用的之前的父镜像的Dockerfile👇,总之看CACHE比较明朗就:

image-20240515121020476

然后为什么会有之前的影响,继续研究

image-20240515121116670

还是还原故障

还原个屁,是自己搞错了,父镜像没有build覆盖原来的tag导致的

image-20240515122105517

这里图中打叉的地方-t写错了,本来是覆盖nginx_env_web:1.5这个父镜像的,结果写成了_son了,所以原来的父镜像没变,也就是说ONBUILD echo '123321' > helo.log本来就在,所以子镜像继承了,人家CACHE既然看到了就说明利用了之前的分层了,就说明父镜像没有变了。

USER,指定后续指令的执行者

image-20240515134826639

HEALTHCHECK,健康检查

image-20240515135052422

image-20240515140746110

注意👆上图IP:=哪里写错了,PORT也写错了,复习变量高级用法去,nnd。

image-20240515140809849

starting就是正在检查中

image-20240515140819699

过一会就发现检查失败了

image-20240515144541185

失败的原因是HEALTHCHECK里的CMD里的变量高级用法写错了,

修改后OK👇

image-20240515152651760

上图👆就是默认的时间是30s timeout,30s检查ok了就判定为healthy。如果30s检查不OK,就retries 3次也就是90s才会判定unhealthy。

然后研究下curl 和 wget的静默用法👇

image-20240515154933039

FROM nginx

# 添加健康检查脚本
COPY healthcheck.sh /usr/bin/healthcheck.sh
RUN chmod +x /usr/bin/healthcheck.sh

# 定义健康检查命令
HEALTHCHECK --interval=30s --timeout=3s \
  CMD /usr/bin/healthcheck.sh   # 这里为啥不能直接写curl和wget,肯定可以的啊,脚本结果还导致少了一个人家健康检查无法执行的返回值2
if curl -I http://localhost:80/health >/dev/null 2>&1; then
  exit 0
else
  exit 1
fi
#!/bin/sh
if wget -q --spider http://localhost:80/health; then
  exit 0
else
  exit 1
fi
所以这样写就行了
#HEALTHCHECK --start-period=3s CMD wget -q --spider http://${IP:-0.0.0.0}:${PORT:-80}/
HEALTHCHECK --start-period=3s CMD curl -I http://${IP:-0.0.0.0}:${PORT:-80}/ &> /dev/null
#这样做的好处,就是docker logs里就没有多余的curl wget信息了,不过这些系也是timeout到了才会出现,比如默认30s就是要到最后一秒才会出现curl或wget日志,不太能理解,因为--start-perod=3s默认就是3秒就执行了啊,我以为日志就容器起来3s就curl就会有日志了,结果docker logs查看发现要等timeout30秒到了才会有日志出来。

HEALTHCHECK 后面的CMD只是HEALTHCHECK里的一个固定参数,不要理解成Dockerfile 的CMD哦

image-20240515144131411

如果健康检查失败还需要进一步去处理故障的,GPT给了一些思路,不过有待后面学到docker-compose的时候验证:

image-20240515163353013

工作案例-抓某个软件的包

1、背景

公司打不开discord的客户端软件

软件还不是浏览器,无法通过F12直接看到那些URL打不开

2、需求

需要定位某个软件访问了那些域名,然后进一步写hosts,然后放行

3、classwire只能看到已经正常运行了的软件,对于打不开得,就是比如discord还在update,以及update好了还在starting的状态下是看不到 discord这个app的流量统计的。至少我的免费版看不到

4、落地方案,如下

参考两个链接

一个cmd里findstr如何写or 👇

https://blog.csdn.net/zhigang0529/article/details/86240577

一个是如何抓包抓软件👇

https://blog.csdn.net/weixin_51309915/article/details/122382555

方法1:有白名单限制的情况下进行

1、打开wireshark软件开始抓包

2、打开软件discord,让其update转圈圈,后面update好了starting一样的处理思路

这个已经没法复现了,我已经解决了,所以仅文字描述了

3、打开任务管理器

image-20240514170017687

找到pid,

4、打开cmd

手动不断回车,配合discord update界面出现的时间,下图findstr 后面空格是或的关系,表示同时抓这些PID。

image-20240514170106728

已经ESTABLISHED基本是OK的,不用管

找到SYN SENT

image-20240514170200398

5、wireshark过滤该ip

提取第一个该ip出现的时间

image-20240514170346121

然后取消过滤,再全部信息里,找到时间点的这条抓包,往上看到DNS解析对应的域名👇

image-20240514170704323

这就知道了该软件目前需要访问的域名了,重复多次,找到需要访问的所有域名

然后①域名解析本地dns固定成一个IP②路由指向vpn③vpn节点放行该ip。这就是海外白名单管理的思路。

以上就是app如何抓包的思路,要抓到域名嘛

除此之外,还有一个方法

方法2:取消白名单限制去做统计

★放开本地的海外白名单,针对自己的IP,然后打开GlassWire软件,此时由于海外全通,所以discord可以打开,包括update,start都行, 这样等软件正常运行了,GlassWire就可以正常显示该软件的域名访问了。

由于已经升级和能够打开了,所以还需要手动升级来让classwire看到流量

操作①需要退出软件②打开③手动升级

image-20240514171436177

image-20240514171925875

发现不全少了一个dl.discordapp.net,这个域名。可见上面的手动方法还是要掌握的。至少可以先用方法2,然后再用方法1查漏补缺。

说明

image-20240514173044055

这种情况就是PID3118一开始不断和130.221.15.150去TCP CONN,但是dns解析写道104.18.52.172后,软件方面也延迟了一小会然后IP解析更正过来了以后,就可以了。

image-20240514173219069

上图同样是通过wireshark过滤IP,找到时间,然后在全部信息里找到时间,看上面的A记录里的域名。

一开始是SYN还是和130.211.15.150建立,后面我解析固定后,discord这个APP的连接请求也就自动更正了

image-20240514173241119

然后通过上面的实验发现

1、wireshark抓了很多很多很的包后,截图软件存在差距

2、微信截图依然顺序好用,但是PixPin截图异迟钝,慢的很咯,关闭wireshark后PinxPin截图反映速度恢复正常。

image-20240514173527372

Copyright 🌹 © oneyearice@126.com 2022 all right reserved,powered by Gitbook文档更新时间: 2024-08-06 11:17:50

results matching ""

    No results matching ""