第10周作业
1.通过dockerfile 制作centos系统镜像然后再制作 nginx编译镜像
dockerfile 制作centos系统镜像
1 在Dockerfile目录下准备编译安装的相关文件
[root@ubuntu1804 ~]#mkdir -r /data/dockerfile/web
[root@ubuntu1804 ~]#cd /data/dockerfile/web
[root@ubuntu1804 web]echo Test nginx-1.6.1 on centos7 >index.html
[root@ubuntu1804 web]#wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@ubuntu1804 web]#tar xf nginx-1.16.1.tar.gz
[root@ubuntu1804 web]#cd nginx-1.16.1/conf
[root@ubuntu1804 conf]#vim nginx.conf
user nginx;
worker_processes 1;
#daemon off;
[root@ubuntu1804 conf]#cp nginx.conf /data/dockerfile/web
2 编写Dockerfile文件
[root@ubuntu1804 web]#pwd
/data/dockerfile/web
[root@ubuntu1804 web]vim Dockerfile
[root@ubuntu1804 web]#cat Dockerfile
#Nginx Dockerfile
FROM centos:centos7.7.1908
MAINTAINER zhang
RUN yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel \
&& useradd -r -s /sbin/nologin nginx \
&& yum clean all
ADD nginx-1.16.1.tar.gz /usr/local/src/
RUN cd /usr/local/src/nginx-1.16.1 \
&& ./configure --prefix=/apps/nginx \
&& make \
&& make install \
&& rm -rf /usr/local/src/nginx*
COPY nginx.conf /apps/nginx/conf/nginx.conf
COPY index.html /apps/nginx/html/
RUN ln -s /apps/nginx/sbin/nginx /usr/sbin/nginx
EXPOSE 80 443
CMD ["nginx","-g","daemon off;"]
3 生成 nginx 镜像
[root@ubuntu1804 web]#vim build.sh
[root@ubuntu1804 web]#cat build.sh
#!/bin/bash
#
docker build -t nginx-centos7:1.6.1-v2 .
[root@ubuntu1804 web]#chmod +x build.sh
[root@ubuntu1804 web]#ls
build.sh Dockerfile index.html nginx-1.16.1.tar.gz nginx.conf
[root@ubuntu1804 web]#./build.sh
[root@ubuntu1804 1.16.1]#docker images
REPOSITORY TAG IMAGE ID CREATED
SIZE
nginx-centos7 1.6.1-v2 1918d29d5f45 17 minutes ago 328MB
4 生成容器测试镜像
[root@ubuntu1804 ~]#docker run -d -p 80:80 nginx-centos7:1.6.1-v2
21c954ad4fb902076832cc9a52dd1502aca43d9bcd2b46a2f164382e4ac7b3f6
[root@ubuntu1804 ~]#docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
21c954ad4fb9 centos7-nginx:1.6.1-v2 "nginx -g 'daemon of…" 6 seconds
ago Up 4 seconds 0.0.0.0:80->80/tcp, 443/tcp inspiring_goldwasser
[root@ubuntu1804 ~]#curl 127.0.0.1
Test nginx-1.6.1 on centos7
2.写出10个常用的dockerfile 脚本参数及使用说明
FROM <repository>[:<tag>] 或 FROM <resisitory>@<digest> // 必须一FROM开头 否则无法识别 <reposotiry> : 指定 base images 的名称 <tag> : base images 的标签,为可选项,默认为latest MAINTANIER (depreacted) // 可选选项 一般用于写作者信息等 MAINTANIER 等同于LABEL 相同作用 LABEL AUTHOR="liuxin <liuxin03311@163.com>" MAINTANIER "maintanier <liuxin03311@163.com>" COPY // 用于从Docker主机复制文件至创建的新印象文件 COPY <src> ... <dest> 或 COPY ["<src>",..."<dest>"] //建议使用这种 兼容路径中空白字符 <src> 要复制的源文件或目录,支持使用通配符 <dest> 目标路径,即正在创建的image的文件路径系统 COPY 指定则以WORKDIR 为其起始路径 注意: 1.<src> 必须是build上下文中的路径,不能是其父目录中的文件。 2.如果<src>是目录,则其内部文件或子目录会被递归复制 ,但 <src>目录目录自身不会被复制 3.如果指定了了多个<src>,或在<src>中使用了通配符 ,则<dest>必须是一个目录 ,且必须以 /结尾 4.如果<dest>事先不存在,它将会被自动创建,这包括其父 目录路径 RUN 在新镜像内部执行的命令,比如安装一些软件、配置一些基础环境,可使用\来换行 在制作镜像的时候使用 示例: 1.RUN echo 'hello docker!' \ > /usr/local/file.txt 2. 也可以使用exec格式RUN ["executable", "param1", "param2"]的命令,如: RUN ["apt-get","install","-y","nginx"] 要注意的是,executable是命令,后面的param是参数 EXPOSE 暴露镜像的端口供主机做映射,启动镜像时,使用-P参数来讲镜像端口与宿主机的随机端口做映射。使用方式(可指定多个): EXPOSE 8080 EXPOSE 8081 EXPOSE 11211/udp 11211/tcp ... WORKDIR 在构建镜像时,指定镜像的工作目录,之后的命令都是基于此工作目录,如果不存在,则会创建目录 WORKDIR /usr/local WORKDIR webservice RUN echo 'hello docker' > text.txt ... ONBUILD 当一个包含ONBUILD命令的镜像被用作其他镜像的基础镜像时(比如用户的镜像需要从某为准备好的位置添加源代码,或者用户需要执行特定于构建镜像的环境的构建脚本),该命令就会执行。 如创建镜像image-A FROM ubuntu ... ONBUILD ADD . /var/www ... 然后创建镜像image-B,指定image-A为基础镜像,如 FROM image-A ... 然后在构建image-B的时候,日志上显示如下: Step 0 : FROM image-A # Execting 1 build triggers Step onbuild-0 : ADD . /var/www ... USER 指定该镜像以什么样的用户去执行,如: USER mongo VOLUME 用来向基于镜像创建的容器添加卷。比如你可以将mongodb镜像中存储数据的data文件指定为主机的某个文件。(容器内部建议不要存储任何数据) 如: VOLUME /data/db /data/configdb 注意:VOLUME 主机目录 容器目录 ADD 将主机的文件复制到镜像中,跟COPY一样,限制条件和使用方式都一样,但是ADD会对压缩文件(tar, gzip, bzip2, etc)做提取和解压操作。 ENV 用于为为镜像定义所需的环境变量 并可被Dockerfile文件中位于其后的其他指令(如ENV、ADD、COPY等)所调用 调用格式为 $variable_name 或 ${variable_name} 语法 ENV <key><value>或 ENV <key>=<value>... 第一种<key>后后所有内容均被视作为其<value>的的组成部分 ,因此,一次只能设置一个变量 第二种格式可用于一次设置多个变量 ,每个变量为一个"<key>=<value>"的键值对,如果 <value>中包含空格 ,可以用反斜杠 (/)进行转义 ,也可通过对<value>加引号进行标识,另外 ,斜线{\}也可用于续行 建议使用第二种 CMD 类似于 RUN 指令,CMD指令也可以用于运行任何命令或应用程序,不过,二者的运行时间点不同 。 * RUN指令运行于映像文件构建过程中 ,而CMD指令运行于基于于Dockerfile构建出的新映像文启动一个容器时 *CMD指令的首要目在于在于启动的 容器指定默认要运行的程序,且 其运行结束后 ,容器也将终止 ;不过,CMD指定的命令指定的命令其可以被docker run de的命令行选项所覆盖 *当有多个CMD的时候,只有最后一个生效。 在制作容器的时候使用 容器启动时需要执行的命令,如: 1.CMD <command> CMD /bin/bash 此方法 进程 PID不为1无法无法接收画画UNIX信号 同样可以使用exec语法,如 2.CMD["<executable>,"<param1>","<param2>"] ["/bin/bash","<param1>","<param2>"] 3.CMD["<param1>","<param2>"] 前两种语法格式的意同 RUN 第三种则用于 ENTRYPOINT指令提供默认参数 ENTRYPOINT 作用和用法和CMD一模一样 CMD和ENTRYPOINT的区别 CMD和ENTRYPOINT同样作为容器启动时执行的命令,区别有以下几点: CMD的命令会被 docker run 的命令覆盖而ENTRYPOINT不会 如使用CMD ["/bin/bash"]或ENTRYPOINT ["/bin/bash"]后,再使用docker run -ti image启动容器,它会自动进入容器内部的交互终端,如同使用 docker run -ti image /bin/bash。 但是如果启动镜像的命令为docker run -ti image /bin/ps,使用CMD后面的命令就会被覆盖转而执行bin/ps命令,而ENTRYPOINT的则不会,而是会把docker run 后面的命令当做ENTRYPOINT执行命令的参数。 HEATHCHECK 用于检查主进程工作与否 1、HEALTHCHECK [options] CMD command 2、HEALTHCHECK NODE 意思是禁止从父镜像继承的HEALTHCHECK生效 参数: --interval:间隔(s秒、m分钟、h小时),从容器运行起来开始计时interval秒(或者分钟小时)进行第一次健康检查,随后每间隔interval秒进行一次健康检查;还有一种特例请看timeout解析。(default:30s) --start-period=DURATION 启动时间, 默认 0s, 如果指定这个参数, 则必须大于 0s ;--start-period 为需要启动的容器提供了初始化的时间段, 在这个时间段内如果检查失败, 则不会记录失败次数。
如果在启动时间内成功执行了健康检查, 则容器将被视为已经启动, 如果在启动时间内再次出现检查失败, 则会记录失败次数。(default:0s) --timeout:执行command需要时间,比如curl 一个地址,如果超过timeout秒则认为超时是错误的状态,此时每次健康检查的时间是timeout+interval秒。(default:30s) --retries:连续检查retries次,如果结果都是失败状态,则认为这个容器是unhealth的.(default:3) 状态码 : 0:success 1:unhealthy 2:reserved For example HEATHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost || exit 1 SHELL Sytnax: SHELL ["exectable","parameters"] STOPSIGNAL 语法: STOPSIGNAL signal STOPSIGNAL命令是的作用是当容器推出时给系统发送什么样的指令 也可以通过 create/run 的参数 --stop-signal 设置。 默认的stop-signal是SIGTERM,在docker stop的时候会给容器内PID为1的进程发送这个signal,通过--stop-signal可以设置自己需要的signal,
主要的目的是为了让容器内的应用程序在接收到signal之后可以先做一些事情,实现容器的平滑退出,如果不做任何处理,容器将在一段时间之后强制退出,会造成业务的强制中断,这个时间默认是10s ARG 语法: ARG <name>[=<default value>] 设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg <varname>=<value>来指定参数 在终端命令行传参:--build-arg <key>=<value> ONBUILD ●用于在Dockerfle中定义一个触发器 ●Dockerfile用于build映像文件,此映像文件亦可作为base image被另一个Dockerfile用作FROM指令的参数,并以之构建新的映像文件 ●在后面的这个Dockerfile中的FROM指令在build过程中被执行时,将会“触发”创建其base image的Dockerfle文件中的ONBUILD指令定义的触发器 ●Syntax ONBUILD <InsTruction> ●尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令 ●使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,例如ruby:2.0-onbuild ●在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程的上下文在缺少指定的源文件时会失败 语法: ONBUILD [INSTRUCTION] 这个命令只对当前镜像的子镜像生效。 比如当前镜像为A,在Dockerfile种添加: ONBUILD RUN ls -al 这个 ls -al 命令不会在A镜像构建或启动的时候执行 此时有一个镜像B是基于A镜像构建的,那么这个ls -al 命令会在B镜像构建的时候被执行。 注意:尽量让Dockerfile层级少 行数代码越多读写层套接也越多 尤其是RUN 等 会多家层级 会让制作的镜像内存很大很大
3.请写出dockerfile的分层原理

公司中的所有镜像都是要上传到harbor仓库上,一层一层的打镜像,在打的同时将镜像上传到harbor上
#第一层原始系统层(ubantu/debain/centos):
这个目录结构一定要提前设计好,我先将官方的原始系统镜像pull下来,在这层的基础之上我们会加一些常用命令
#第二层常用命令层:
否则后期还要在镜像中安装命令太过于麻烦,我们将这个安装常用命令的镜像称为公司的基础镜像叫做baseimgae,后期我们在打镜像的时候就不再调用官方的了,而是直接调用baseimgae。我们会在baseimgae这个镜像中不仅要安装命令,而且还要将我们的常用用户创建好,这个镜像创建好了之后再往下就会分叉了,
#第三层业务层(nginx、PHP、JDK、tomcat、mysql等业务):
因为公司有很多业务,这一层就包括了各种服务镜像如jdk(java环境使用的镜像)、安装PHP的镜像、安装NGINX的镜像等等服务。然后这一层再提交为一层业务镜像,并在JDK的镜像层往下再打一层tomcat的业务层,在tomcet这层之后再打一层代码层。用来存放代码的APP1、APP2这一层只是编译安装了各个服务而已他们上面是没有任何代码和web页面数据的。
第四层代码层(静态服务前端代码和tomcat的jsp代码等):
然后再将这一层打出来的镜像就可以往公司的 Harbor 仓库进行上传了。
#宿主机:
打完了这几层镜像之后,下面就是运行这些镜像的各个node节点也就是所谓的宿主机,要保证我们的宿主机能够在公司的harbor上去拉取镜像,当宿主机拉取完了镜像之后,我们就让该宿主机运行一个容器。然后再将所有nginx容器的数据都存放到NAS存储上,以实现数据同步。而NAS存储是先挂载在宿主机上,然后是宿主机将这个存储给各个容器去使用。由java容器往NAS存储上写数据,再由nginx容器来读NAS存储上的数据,所以他们实际上是看到的同一份数据
#总结:
我们从镜像分层上,我们不会像docker官方那样一步打成我们的业务镜像,因为像官方那样一次性操作的步骤太多了,不利于后期dockerfile文件以及没做一个容器就要从新打一次镜像,不能实现dockerfile文件多次复用。
所以我们会将每个步骤才分开,每个步骤都是一层镜像,这样后期某个业务想用某个环境的镜像直接就基于不同层的dockerfile文件进行调用

浙公网安备 33010602011771号