Dokcer使用DokcerFile定制镜像
定制docker镜像的方式有两种:
- 手动修改容器内容,导出新的镜像。
- 基于dockerfile自行编写指令,基于指令流程创建镜像。
Dockerfile简介
镜像是多层存储,每一层都是在前一层的底子上举行修改;
容器也是多层存储,以镜像为底子层,在其底子上加一层作为容器运行时的存储层。
刚才说了,创建镜像的两个方法:
- 手动修改容器内容,然后dokcer commit提交容器为新的镜像
- 通过在dockerfile中界说一系列的下令和参数构建成的脚本,然后这些下令应用于底子镜像,依次添加层,终极天生一个新的镜像。极大的简化了摆设工作。
Dockerfile紧张构成部门
底子镜像信息 FROM centos:7.9 制作镜像操作指令 RUN yum install -y nginx 容器启动时实验指令 CMD ["/bin/bash"]宿主机直接摆设软件流程与Dockerfile摆设软件流程对比
需求 : 安装一个mysql,并启动。
捏造机摆设情势:
1. 开启vmware 2. 运行某一个捏造即,centos7 3. centos7安装mysql yum install mysql-server 4. 通过脚本大概下令,启动mysql即可摆设迟钝,且修改了宿主机的情况,删除较为贫苦,占用宿主机的一个3306端口
容器的摆设情势:
1. 开始vmware 2. 运行捏造机centos7(宿主机) 3. 安装docker容器软件 4. 获取mysql镜像即可,docker pull mysql:tag(你无法自由控制,该mysql的底子镜像时什么发行版本,你获取的镜像,是别人定制好的,你下载使用的默认时Debian发行版,你盼望得到一个基于centos7.9的发行版本,运行mysql) 5. 直接运行该镜像,通过端口映射,运行mysql 6. 访问宿主机对的一个映射端口,访问到容器内的mysql想自界说镜像,就得自己写脚本,也就是dockerfile了
Dokcerfile指令
FROM 指定底子镜像MAINTAINER 指定维护者信息,可以没有RUN 你想让它干啥(在下令前面加上RUN即可)ADD 添加宿主机的文件到容器内,还多了一个主动解压的功能# RUN tar -Zxf /opt/xx.tgz # 报错!该tgz文件不存在! !COPY 作用和ADD是一样的,都是拷贝宿主机的文件到容器内, COPY就是仅仅拷贝WORKDIR 相称于cd下令,设置当前工作目次VOLUME 设置目次映射,挂载主机目次EXPOSE 指定对外的端口,在容器内袒露一个端口,端口 EXPORT 80CMD 指定容器启动后的要干的事故ENTRYPOINT 作用和CMD一样,都是在指定容器启动程序以及参数。# 当指定了ENTRYPOINT之后,CMD指令的语义就有了厘革,而是把CMD的内容看成参数通报给ENTRYPOINT指令。ARG 设置情况变量# ARG只是用于构建镜像必要设置的变量,容器运行时就消散了ENV 和ARG一样,都是设置情况变量# 区别在于ENV无论是在镜像构建时,还是容器运行,该变量都可以使用USER 用于改变情况,用于切换用户ONBUILD 用于设置镜像触发器Dokcerfile实践
需求:通过dockerfile,构建nginx镜像,且运行容器后,天生的页面是"Docker mhg"。
1. 创建Dockerfile,注意文件名,必须是这个mkdir /root/learn_dockercd /root/learn_dockervim DockerfileFROM nginxRUN echo "<meta charset=utf-8>Docker mhg" > /usr/share/nginx/html/index.html2. 构建Dockerfiledocker build .
3. 修改镜像名字docker images[root@qzcsbj-harbor learn_docker]# docker tag 531f41ec3c5a my_nginx4. 运行该镜像docker run -d -p 9080:80 my_nginx5. 查察宿主机的9080端口http://192.168.117.160:9080/Dokcerfile干系指令用法
COPY
copy指令从宿主机复制文件大概目次到新的一层镜像内如:copy nana.py /opt支持多个文件,以及通配符情势的复制,语法要满意Golang的filepath.Matchcopy na* /tmp/cc?.txt /optCOPY指令可以大概保留源文件的元数据,访问时间等等,这点很紧张ADD
特性和COPY根本划一,不外多了些功能1. 源文件是一个URL,此时dockcer引擎会下载该链接,放入目的路径,且权限主动设为600。若这不是盼望效果,还得增长一层RUN指令举行调整# ADD nana.tgz /home# RUN xxx修改下令2. 源文件是一个URL,且是一个压缩包,不会主动解压,也得单独用RUN指令解压3. 源文件是一个压缩文件,且是gzip,bzip,xz,tar情况,ADD指令会主动解压压缩该文件到没有文件CMD
用法,注意是双引号# CMD在容器内运行某个下令,启动程序# 该镜像在运行容器实例的时间,实验的详细参数是什么CMD["参数1","参数2"]在指定了entrypoint指令后,用CMD指定详细的参数dokcer不是捏造机,容器就是一个历程,既然是历程,那么程序在启动的时间必要指定些运行参数,这就是CMD指令作用比方centos镜像默认的CMD是/bin/bash,直接docker run -it centos会直接进入bash表明器。也可以启动容器时间,指定参数: docker run -it centos cat /etc/os-releaseCMD ["/bin/bash"]# 该容器运行时,实验的下令# 等同于下令行的直接操作:docker run -it centos cat /etc/os-releaseCMD ["cat","/etc/os-release"]容器内运行程序
这里要注意的是,docker不是捏造机的概念,捏造机的程序运行,根本上都是在配景运行,使用systemctl运行,但是容器内没有配景历程的概念,必须在前台运行。
容器就是为了主历程而存在的,主历程假如退出了,容器也就失去意义,主动退出。
比方一个经典的标题:# 如许的写法是错误的,容器会立即退出CMD systemctl start nginx由于systemctl start nginx是以保卫历程(默认在配景运行)的情势启动nginx,且CMD下令会转化为CMD ["sh","-c","systemctl start nginx" ]如许的下令主历程是sh表明器,实验完毕后立即竣事了,因此容器也就退出了。# 相称于nginx -g daemon off因此准确的做法应该是 CMD ["nginx","-g","daemon off;"]把宿主机安装,启动nginx的理念放入到dockerfile中
1. RUN yum install nginx2. RUN 设置文件修改 sed# RUN systemctl start nginx 容器内的程序必须在前台运行,容器时启动不了的3. 准确的写法应该时CMD ["nginx","-g","daemon off;"]ENTRYPOINT
dokcer口试题:ENTRYPOINT和CMD的区别以及用法! ! !CMD:指定这个容器启动的时间要运行的下令,只有末了一个会生效,可被替换ENTRYPOINT:指定这个容器启动的时间要运行的下令,可以追加下令ENTRYPOINT作用和CMD一样,都是在指定容器启动程序以及参数。当指定了ENTRYPOINT之后,CMD指令的语义就有了厘革,而是把CMD的内容看成参数通报给ENTRYPOINT指令。ENTRYPOINT和CMD的现实用法
现实用法:1. 预备一个Dokcerfile[root@qzcsbj-harbor ~]# cd /learn_docker/[root@qzcsbj-harbor learn_docker]# > Dockerfile [root@qzcsbj-harbor learn_docker]# vim Dockerfile FROM centos:7.8.2003RUN rpm --rebuilddb && yum install epel-release -yRUN rpm --rebuilddb && yum install curl -yCMD ["curl","-s","ip.sb"]# 用法如下dokcer run my_centos curl -s ip.sb # curl -s ip.sb获取本机的公网ip地点2. 构建镜像[root@qzcsbj-harbor learn_docker]# docker build .Sending build context to Docker daemon 2.048kBStep 1/4 : FROM centos:7.8.2003 ---> afb6fca791e0Step 2/4 : RUN rpm --rebuilddb && yum install epel-release -y ---> Using cache ---> 81b4e83fb0a5Step 3/4 : RUN rpm --rebuilddb && yum install curl -y ---> Using cache ---> bd0074c78b6cStep 4/4 : CMD ["curl","-s","ip.sb"] ---> Running in 295418f71093Removing intermediate container 295418f71093 ---> c920b743282aSuccessfully built c920b743282a3. 查察效果(出现Successfully代表镜像构建完成)Step 4/4 : CMD ["curl","-s","ip.sb"] ---> Running in 295418f71093Removing intermediate container 295418f71093 ---> c920b743282aSuccessfully built c920b743282a4. 检查镜像[root@qzcsbj-harbor learn_docker]# docker tag c920b743282a centos_curl [root@qzcsbj-harbor learn_docker]# docker images | grep curlcentos_curl latest c920b743282a 3 minutes ago 471MB5. 运行镜像,天生容器记载,没有前台运行,因此立即挂了[root@qzcsbj-harbor learn_docker]# docker run centos_curl139.227.102.1896. 上述运行准确,但是我想再传入一个参数,该怎么办# 发现是无法直接传入参数的,该情势是覆盖镜像中的cmd# 就比如把docker镜像,看成一个情况,去实验背面的下令[root@qzcsbj-harbor learn_docker]# docker run centos_curl pwd/[root@qzcsbj-harbor learn_docker]# [root@qzcsbj-harbor learn_docker]# docker run centos_curl -Idocker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-I": executable file not found in $PATH: unknown.7. 想要准确的给容器传入一个参数该怎么办盼望容器内可以大概准确完备的运作该下令的实验效果[root@qzcsbj-harbor learn_docker]# curl -s ip.sb -I # 获取http报头信息HTTP/1.1 200 OKDate: Wed, 28 Jul 2021 15:16:18 GMT...8. 办理办法方式一:给容器传入新的完备的下令,让背面的下令覆盖镜像中的cmd# 这是谋利取巧的办法,不符合[root@qzcsbj-harbor learn_docker]# docker run centos_curl curl -s ip.sb -IHTTP/1.1 200 OKDate: Wed, 28 Jul 2021 15:18:05 GMTContent-Type: text/plain9. 准确的办理办法[root@qzcsbj-harbor learn_docker]# vim Dockerfile FROM centos:7.8.2003RUN rpm --rebuilddb && yum install epel-release -yRUN rpm --rebuilddb && yum install curl -yENTRYPOINT ["curl","-s","ip.sb"]10. 重新构建镜像# 重新构建镜像速率特殊快,而且我们发现镜像的前三个Step的IMAGE ID是划一的,阐明前三个的IMAGE ID是直接从缓存中拿的。# 只有Step 4/4的IMAGE ID发生了厘革(Dockerfile文件的第四步是更改过的,是重新构建的镜像层),因此更加验证了我们之前所提到的镜像是分层构建的。[root@qzcsbj-harbor learn_docker]# docker build .Sending build context to Docker daemon 2.048kBStep 1/4 : FROM centos:7.8.2003 ---> afb6fca791e0Step 2/4 : RUN rpm --rebuilddb && yum install epel-release -y ---> Using cache ---> 81b4e83fb0a5Step 3/4 : RUN rpm --rebuilddb && yum install curl -y ---> Using cache ---> bd0074c78b6cStep 4/4 : ENTRYPOINT ["curl","-s","ip.sb"] ---> Running in df106e04d533Removing intermediate container df106e04d533 ---> e9479067148cSuccessfully built e9479067148c11. 重新运行该镜像,看效果,以及传入新的参数[root@qzcsbj-harbor learn_docker]# docker tag e9479067148c centos_curl_new# 此时发现,传入的CMD指令,看成了ENTRYPOINT的参数# 着实容器内,实验的完下令是: curl -s ip.sb -I[root@qzcsbj-harbor learn_docker]# docker run centos_curl_new -IHTTP/1.1 200 OKDate: Wed, 28 Jul 2021 15:24:58 GMT...ARG和ENV指令
设置情况变量
dockerfile脚本,shell脚本ENV NAME="nana"ENV AGE=18ENV MYSQL_VERSION=5.6后续全部的操作,通过$NAMME就可以直接获取变量值使用了,维护dockerfile更加方便ARG和ENV一样,都是设置情况变量ENV无论是在镜像构建时,还是容器运行,该变量都可以使用ARG只是用于构建镜像必要设置的变量,容器运行时就消散了VOLUME
容器在运行时,应该包管在存储层不写入任何数据,运行在容器内产生的数据,我们保举是挂载,写入到宿主机上,举行维护。
# mount /mnt VOLUME /data # 将容器内的/data文件夹,在容器运行时,该目次主动挂载为匿名卷,任何向该目次中写入数据的操作,都不会被容器记载,包管的容器存储无状态理念。# Dockerfile[root@qzcsbj-harbor ~]# cd /learn_docker/[root@qzcsbj-harbor learn_docker]# > Dockerfile [root@qzcsbj-harbor learn_docker]# vim Dockerfile FROM centosMAINTAINER nanaVOLUME ["/data1","/data2"]# 该容器运行的时间,这两个目次主动和宿主机的目次做好映射关系docker build .# 运行该镜像docker run 86b4dceba89a# 查察天生的容器信息[root@qzcsbj-harbor nana]# docker ps -a | head -2CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES84014622b3a4 86b4dceba89a "/bin/bash" 2 minutes ago Exited (0) 2 minutes ago sharp_noether# dokcer inspect下令查察[root@qzcsbj-harbor learn_docker]# docker inspect 86b4dceba89a "Volumes": { "/data1": {}, "/data2": {} },1. 容器数据挂载的方式,通过dockerfile,指定VOLUME目次2. 通过docker run -v参数,直接设置必要映射挂载的目次EXPOSE
指定容器运行时对外提供的端口服务。
资助使用该镜像的人,快速明白该容器的一个端口业务docker port 容器dokcer run -p 宿主机端口:容器端口docker run -P # 作用是随机 宿主机端口:容器内端口WORKDIR
用于在dockerfile中,目次的切换,更改工作目次
WORKDIR /optUSER
用于改变情况,用于切换用户
USER rootUSER nanaONBUILD
用于设置镜像触发器,从当前镜像创建子镜像,会触发ONBUILD的实验
注意:ONBUILD指令不会继承
# 创建一个Dockerfile,写入触发器[root@qzcsbj-harbor ~]# mdkir /docker[root@qzcsbj-harbor ~]# vim /docker/Dockerfile FROM centos:7RUN yum -y install curlENTRYPOINT ["curl","-s","https://www.cip.cc/"]ONBUILD RUN echo "==images onbuild=="# 构建镜像(触发器并没有实验)[root@qzcsbj-harbor ~]# cd /docker/[root@qzcsbj-harbor docker]# docker build . -t "nana_ip"Sending build context to Docker daemon 2.048kBStep 1/4 : FROM centos:77: Pulling from library/centos2d473b07cdd5: Pull complete Digest: sha256:0f4ec88e21daf75124b8a9e5ca03c37a5e937e0e108a255d890492430789b60eStatus: Downloaded newer image for centos:7 ---> 8652b9f0cb4c...我们基于构建完成的镜像(nana_ip),创建一个新的Dockerfile[root@qzcsbj-harbor docker]# cd[root@qzcsbj-harbor ~]# vim DockerfileFROM nana_ipRUN yum -y install curlENTRYPOINT ["curl","-s","https://www.cip.cc/"]# 构建子镜像,触发器实验乐成[root@qzcsbj-harbor ~]# docker build . -t "nana_ip02"Sending build context to Docker daemon 17.92kBStep 1/3 : FROM nana_ip# Executing 1 build trigger ---> Running in 70833b9adb69==images onbuild==Removing intermediate container 70833b9adb69 ---> fce1318ec153... |