docker快速入门6-dockerfile和registry

网友投稿 220 2022-10-27

docker快速入门6-dockerfile和registry

docker快速入门6-dockerfile和registry

dockerfile是构造Docker images的一行行命令的集合,是一个纯文本文件。

语法格式

# 注释信息

INSTRUCTION 指令,指令不区分大小写,但约定使用大写

非注释行的第一行必须是FROM指令

工作目录

使用Dockerfile制作镜像时需要一个干净的工作目录,该目录结构如下:

Dockerfile文件 可选的 .dockerignore,用于存放要打包进镜像的文件目录中需要排除的文件 文件1,文件2,... 目录1,目录2,...

要打包进镜像的文件或目录都存放在与Dockerfile文件同级。

Dockerfile指令

更多的dockerfile指令相关信息请参考:https://docs.docker.com/engine/reference/builder

FROM

Dockerfile文件开篇的第一个非注释行,用于为镜像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境。

语法 FROM [:]或 FROM @ : 基础镜像名称 : 基础镜像的标签,省略时默认为latest : 可以不指定镜像的名称而使用镜像的唯一识别hash码

LABLE

为Dockerfile提供key,value对的源数据信息,是MAINTAINER的替代指令

LABEL = = = ...

COPY

从Docker主机复制文件至创建的新镜像文件中

有两种方式 COPY [--chown=:] ... COPY [--chown=:] ["",... ""] --chow只适用于类linux系统的镜像 : 要复制的源文件或目录,支持通配符 : 目标路径,即正在创建的image的文件系统路径,使用绝对路径,否则是以WORKDIR为其起始路径 文件复制准则: 必须是Dockerfile文件所在目录中的文件,不能是其父目录中的文件 如果是目录,则其内部的文件或子目录会被递归复制,但目录自身不会被复制 如果指定了多个,或使用了通配符,则必须是一个目录,且以“/”结尾 如果事先不存在,会被递归创建

ADD

类似COPY指令,ADD支持使用tar文件和url路径

两种语法格式 ADD [--chown=:] ... ADD [--chown=:] ["",... ""] --chow只适用于类linux系统的镜像 操作准则 1. 同COPY指令 2. 如果为URL且不以/结尾,则指定的文件将被下载并且直接被创建为;如果以/结尾,则文件名URL指定的文件将被直接下载并保存为/ 3. 如果是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于“tar -x”命令;然而,通过URL获取到的tar文件将不会自动展开; 4. 如果有多个,或其间接或直接使用了通配符,则必须为一个以/结尾的目录路径;如果不以/结尾,其被视为一个普通文件,的内容将被直接写入到

WORKDIR

用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定的工作目录。

语法 WORKDIR /path/to/workdir 在Dockerfile文件中,WORKDIR指令可以出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径。另外,WORKDIR也可调用由ENV指令指定的变量。 如: ENV DIRPATH /path WORKDIR $DIRPATH/

VOLUME

用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷,该卷属于Docker managed volume类型的卷,即宿主机上要挂载的目录由dockerd管理。

语法 VOLUME ["/data"] 如果挂载点目录路径下此前有文件存在,docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中。

EXPOSE

用于为容器打开指定要监听的端口以实现与外部通信

语法 EXPOSE [/...] 用于指定传输层协议,可为tcp或udp二者之一,默认为tcp协议 可一次指定多个端口,如: EXPOSE 80/tcp 8080/udp EXPOSE指令并不会真正把相应的端口暴露到宿主机上,而是说明以该镜像运行的容器具有该种能力,需要在`docker run`命令时使用`-P`(大写的字母p)选项就可把EXPOSE指定的端口进行暴露,宿主机使用的随机端口,也可以使用`-p :`来指定宿主机上使用的端口。

ENV

用于为镜像定义所需要的环境变量,并可被Dockerfile文件中位于其后的其它指令(如ENV、ADD、COPY等)所调用。

语法 ENV ENV = ... 第一种格式中,之后的所有内容均会被视作其的组成部分,因此,一次只能设置一个变量; 第二种格式中可一次设置多个变量,每一个变量为一个“=”键值对,如果有空格,使用反斜线(\)进行转义,可通过对加引号进行标识;另外反斜线也可用于续行; 如: ENV myName="John Doe" myDog=Rex\ The\ Dog \ myCat=fluffy 引用时使用“$myName”或“${myName}” 定义多个变量时,建议使用第二种方式。

RUN

用于指定docker build过程中运行的程序,其可以是任何命令

语法 RUN RUN ["executable", "param1", "param2", ...] 第一种格式中,通常是一个shell命令,且以“/bin/sh -c”来运行它,这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当使用“docker stop ”命令停止容器时,此进程接收不到SIGTERM信息; 第二种格式中的参数是一个JSON格式的数组,其中为要运行的命令,后面的为传递给命令的选项或参数;然而,此种格式指定的命令不会以“/bin/sh -c”来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;不过,如果要运行的命令依赖此shell特性话,可以将其替换为类似下面的格式。 RUN ["/bin/bash", "-c", "", "param1"] JSON数组中一定要使用双引号

CMD

类似RUN指令,CMD指令也可用于运行任何命令或程序,不过二者的运行时间点不同。

RUN指令运行于镜像文件构建过程中,而CMD指令运行于基于Dockerfile构建出的新镜像文件启动一个容器时;CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD指定的命令可以被“docker run”的命令行选项所覆盖;

在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效。

语法 CMD ["executable","param1","param2"] (exec的形式, 首选使用这种) CMD ["param1","param2"] (为ENTRYPOINT指代默认参数) CMD command param1 param2 (同RUN一样)

ENTRYPOINT

类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序。与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定的程序。不过,docker run命令的--entrypoint选项的参数可以覆盖ENTRYPOINT指令指定的程序。

语法 ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2 docker run命令传入的命令参数会覆盖CMD指令的内容,并且附加到ENTRYPOINT命令最后做为其参数使用,如果docker run命令行未传入命令参数,那ENTRYPOINT会以CMD指令中的内容作为其默认参数 Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效

USER

用于指定运行image时的或运行Dockerfile中任何RUN、CMD或ENTRYPOINT指令指定的程序时的用户名或UID

默认情况下,container的运行身份为root用户

语法 USER [:] USER [:] UDI,GID必须为镜像系统中有效用户的UID,GID,否则,docker run命令将运行失败。

HEALTHCHECK

用于Docker如何测试容器是否仍在正常工作。

语法 HEALTHCHECK [OPTIONS] CMD command (通过在容器内部运行命令来检查容器的运行状况) HEALTHCHECK NONE (禁用从基本映像继承的任何运行状况检查) [OPTIONS]: --interval=DURATION(默认值:30s) 表示检查间隔时间 --timeout=DURATION(默认值:30s) 表示检查超时时间 --start-period=DURATION(默认值:0s) 表示container运行后等待主进程起动程序,开始健康检查前的等待时长 --retries=N(默认值:3) 当检查失败时,需要连续检查多少次才判定该服务处于不健康状态 检查命令的退出状态,可能的值为: 0:成功-容器健康且可以使用 1:不健康-容器无法正常工作 2:保留-请勿使用此退出代码 事例 HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f || exit 1

SHELL

用于覆盖RUN,CMD,ENTRYPOINT等指令运行的默认shell。

语法 SHELL ["executable", "parameters"] linux默认使用["/bin/sh", "-c"],windows默认使用["cmd", "/S", "/C"]

STOPSIGNAL

向容器发送退出的信号

语法 STOPSIGNAL signal signal为系统合法的无符号的信号数字,如9

ARG

用于给docker build时传递变量

语法 ARG [=] 在“docker build”时使用“--build-arg =”传递参数 如: FROM busybox ARG user USER ${user:-some_user} USER $user 在build时使用 $ docker build --build-arg user=what_user ./

ONBUILD

用于在Dockerfile中定义一个触发器

Dockerfile用于build映像文件,此映像文件亦可作为base image被另一个Dockerfile用作FROM指令的参数,并以之构建新的映像文件,在后面的这个Dockerfile中的FROM指令在build过程中被执行时,将会“触发”创建其base image的Dockerfile文件中的ONBUILD指令定义的触发器。

语法 ONBUILD 尽管任何指令都可注册为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令。 使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,如 ruby:2.0-onbuild,来告诉用户会触发ONBUILD 在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程的上下文在缺少指定的源文件时会失败

Dockerfile事例

root@node01:~/img01# pwd /root/img01 root@node01:~/img01# ls -al total 20 drwxr-xr-x 2 root root 4096 Jul 20 09:58 . drwx------ 5 root root 4096 Jul 20 09:58 .. -rw-r--r-- 1 root root 513 Jul 20 09:32 Dockerfile -rwxr-xr-x 1 root root 195 Jul 20 09:58 entrypoint.sh -rw-r--r-- 1 root root 35 Jul 20 09:22 index.html root@node01:~/img01# cat Dockerfile FROM nginx:1.14-alpine # ARG定义的变量可以在build时通过--build-arg 传递参数替换 ARG author="Jack " LABEL maintainer="${author}" ENV NGX_DOC_ROOT="/data/web/html/" ADD index.html ${NGX_DOC_ROOT} ADD entrypoint.sh /bin/ EXPOSE 80/TCP 8080/TCP # 健康检查 HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/ # 触发器 ONBUILD RUN echo "Hello Word!" > /tmp/readme.txt CMD ["/usr/sbin/nginx","-g","daemon off;"] ENTRYPOINT ["/bin/entrypoint.sh"] root@node01:~/img01# cat entrypoint.sh #!/bin/sh cat > /etc/nginx/conf.d/conf << EOF server { server_name ${HOSTNAME}; listen ${IP:-0.0.0.0}:${PORT:-10080}; root ${NGX_DOC_ROOT:-/usr/share/nginx/html}; } EOF exec "$@" root@node01:~/img01# cat index.html This is a nginx test page

entrypoint.sh文件中末尾的exec "$@"尤为重要,由于Dockerfile中同时定义了ENTRYPOINT和CMD指令,所以容器运行时执行的程序为/bin/entrypoint.sh "/usr/sbin/nginx" "-g" "daemon off;" 而后边的参数都会entrypoint.sh脚本末尾的“$@”收集,即成了exec "/usr/sbin/nginx" "-g" "daemon off;",因使用了exec来执行,所以启动nginx的进程ID会替代运行/bin/entrypoint.sh脚本时的sh进程的ID。

build生成镜像

root@node01:~/img01# docker build --build-arg 'author="Tom "' -t mynginx:v0.1-1 ./ Sending build context to Docker daemon 4.608kB Step 1/11 : FROM nginx:1.14-alpine ---> 8a2fb25a19f5 Step 2/11 : ARG author="Jack " ---> Running in ffe97dc263b2 Removing intermediate container ffe97dc263b2 ---> 48cccb2b3ac2 Step 3/11 : LABEL maintainer="${author}" ---> Running in e31958e5d9eb Removing intermediate container e31958e5d9eb ---> b2c494b442d5 Step 4/11 : ENV NGX_DOC_ROOT="/data/web/html/" ---> Running in 1aabf04d1295 Removing intermediate container 1aabf04d1295 ---> 4fdb24fa67f2 Step 5/11 : ADD index.html ${NGX_DOC_ROOT} ---> e334aa452daa Step 6/11 : ADD entrypoint.sh /bin/ ---> ad5488c7c47c Step 7/11 : EXPOSE 80/TCP 8080/TCP ---> Running in 773ae947ecd7 Removing intermediate container 773ae947ecd7 ---> 23c16ae625fe Step 8/11 : HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/ ---> Running in 7be92e4c77a7 Removing intermediate container 7be92e4c77a7 ---> 544097889172 Step 9/11 : ONBUILD RUN echo "Hello Word!" > /tmp/readme.txt ---> Running in 3f121c8e23d0 Removing intermediate container 3f121c8e23d0 ---> 6d80a88f95ee Step 10/11 : CMD ["/usr/sbin/nginx","-g","daemon off;"] ---> Running in b5dbfb4a6c46 Removing intermediate container b5dbfb4a6c46 ---> 7eaa7434d331 Step 11/11 : ENTRYPOINT ["/bin/entrypoint.sh"] ---> Running in f3d78245e25a Removing intermediate container f3d78245e25a ---> 3a250eefa3a7 Successfully built 3a250eefa3a7 Successfully tagged mynginx:v0.1-1

查看镜像详细信息

root@node01:~/img01# docker image inspect mynginx:v0.1-1 ... "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "NGINX_VERSION=1.14.2", "NGX_DOC_ROOT=/data/web/html/" ], "Cmd": [ "/usr/sbin/nginx", "-g", "daemon off;" ], "Healthcheck": { "Test": [ "CMD-SHELL", "wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/" ], "StartPeriod": 3000000000 }, "Image": "sha256:7eaa7434d331cfc56db82b03ee9472eca1dd4ee3411252fb0155d86debb5fa78", "Volumes": null, "WorkingDir": "", "Entrypoint": [ "/bin/entrypoint.sh" ], "OnBuild": [ "RUN echo \"Hello Word!\" > /tmp/readme.txt" ], "Labels": { "maintainer": "\"Tom \"" }, ...

其中Labels中的maintainer是docker build使用--build-arg传递的值Tom <tom@163.com>,不再是Docerfile中定义的值Jack <jack@qq.com>。

基于镜像mynginx:v0.1-1运行一个容器

root@node01:~# docker container run --rm --name nginx01 -e "PORT=8080" mynginx:v0.1-1 127.0.0.1 - - [20/Jul/2020:14:43:44 +0000] "GET / HTTP/1.1" 200 35 "-" "Wget" "-" 127.0.0.1 - - [20/Jul/2020:14:44:14 +0000] "GET / HTTP/1.1" 200 35 "-" "Wget" "-" ......

因配置了HEALTHCHECK,在容器运行后,运行进程运行3秒后每隔30秒都会检查nginx的主页。

另起终端连接到容器中

root@node01:~# docker container exec -i -t nginx01 /bin/sh / # cat /etc/nginx/conf.d/conf server { server_name eaf2cfb1eece; listen 0.0.0.0:8080; root /data/web/html/; } / # netstat -tanl Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:8080 127.0.0.1:33032 TIME_WAIT tcp 0 0 127.0.0.1:8080 127.0.0.1:33030 TIME_WAIT / # ps PID USER TIME COMMAND 1 root 0:00 nginx: master process /usr/sbin/nginx -g daemon off; 8 nginx 0:00 nginx: worker process 44 root 0:00 /bin/sh 66 root 0:00 ps / # ls /tmp/ / #

生成了配置文件,监听8080端口是docker run命令行传递的PORT变量的值。

再来测试一下ONBUILD指令,以生成的新镜像mynginx:v0.1-1为基础镜像再来制作一个镜像

root@node01:~/img02# pwd /root/img02 root@node01:~/img02# ls Dockerfile root@node01:~/img02# cat Dockerfile FROM mynginx:v0.1-1 RUN /bin/touch /tmp/1.txt root@node01:~/img02# docker build -t test:v0.1-1 ./ Sending build context to Docker daemon 2.048kB Step 1/2 : FROM mynginx:v0.1-1 # Executing 1 build trigger ---> Using cache ---> 8fd69355802f Step 2/2 : RUN /bin/touch /tmp/1.txt ---> Running in 2e123d9c7683 Removing intermediate container 2e123d9c7683 ---> cce488581509 Successfully built cce488581509 Successfully tagged test:v0.1-1

以此镜像运行一个容器

root@node01:~# docker container run -i -t --rm --name test01 test:v0.1-1 /bin/sh / # ls /tmp/ 1.txt readme.txt / # cat /tmp/readme.txt Hello Word! / #

/tmp/readme.txt生成了,说明基础镜像里定义的ONBUILD指令被触发了。

docker官方在github在还有许多Dockerfile事例,可以参考:Registry

Registry用于保存docker镜像,包括镜像的层次结构和元数据。用户可以自建Registry,也可以使用官方的Docker Hub。

分类:

Sponsor Registry: 第三方的registry,供客户和Docker社区使用 Mirror Registry: 第三方的registry,只让客户使用 Vendor Registry: 由发布Docker镜像的供应商提供的Registry Private Registry: 通过设有防火墙和额外的安全层的私有实体提供的registry

私有registry搭建

官方提供了docker-distribution软件包来搭建一个Private Registry,也提供了一个名为registry的镜像,只需要pull该镜像,启动容器就可以搭建起来,如果要提供["192.168.101.41/myreposition"]

此key表示访问192.168.101.41/myreposition这个Private Registry可以使用http协议。

官方提供的registry过于简陋,vmware对该软件进行了二次开发,名为Harbor为其增加了许多特性,还提供了一个web界面,详细信息请参考:https://github.com/goharbor/harbor

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:DS8007 多协议双智能卡接口
下一篇:springmvc直接不经过controller访问WEB
相关文章

 发表评论

暂时没有评论,来抢沙发吧~