Dockerfile制作镜像
文章目录
- Dockerfile制作镜像
- Dockerfile的指令
- 镜像生成的途径
- Dockerfile制作
- 基于容器制作(直接在容器中制作)
文章图片
- Dockerfile只是构建Docker映像的源代码
- Docker可以通过读取Dockerfile中的指令来自动构建图像
- Dockerfile是一个文本文档,包含用户可以在命令行上调用的所有命令来组装一个图像
- 使用docker构建用户可以创建一个自动构建,该构建可以连续执行多个命令行指令
文章图片
- Dockerfile的文件格式
- 格式(Format)
# Comment
以#
开头的为注释信息INSTRUCTION arguments
指令和参数
- Dockerfile的指令不区分大小写
- 通常都会将指令写成大写,以便于区分指令和参数。
- Docker按顺序在Dockerfile中运行指令
- 第一个指令必须是“FROM”,以便指定要从中构建的基本映像
- 格式(Format)
- 环境替代(Environment replacement)
- Environment变量(使用ENV语句声明)也可以在某些指令中用作Dockerfile要解释的变量
- Dockerfile中使用
$variable_name
或${variable_name}
标注环境变量 ${variable_name)
语法还支持一些标准的bash修饰符${variable:-word}
如果variable有值,那么使用variable的值,如果没有就使用word字符串作为值${variable:+word}
如果variable有值,那么使用word字符串作为值,如果没有设置就是variable值,即空值。
- FROM 指令
- FROM指令是最重要的一个且必须为Dockerfile文件开篇的第一个非注释行,用于为映像文件构建过程指定基准镜像,后续的指令运行与此基准镜像所提供的运行环境
- 实践中,基准镜像可以是任何可用镜像文件,默认情况下,
docker build
会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件- 如果找不到指定的镜像文件,docker build会返回一个错误信息
- 语法:
FROM
或[: ] @
:指定作为base image的名称
:buse image的标签,省略时默认为latest;
buse image镜像的哈希码
# 在任意目录中创建Dockerfile文件 [root@gdy img1]# vim Dockerfile
- MAINTANIER 指令(depreacted,作者信息)
- 用于让Dockerfile制作者提供本人的详细信息
- Dockerfile 并不限制MAINTAINER指令可能出现的位置,但推荐将其放置于FROM指令之后
- 语法:
MAINTAINER
可以是任何文本信息,单通常会使用作者名称及邮件地址
- 示例:
MAINTAINER "xdd
"
- 示例:
- LABEL 指令(docker1.7后的语法)指定元数据
- 语法:
LABEL
= = = ...
- 语法:
- COPY 指令
- 用于从Docker主机复制文件至创建的新映像文件
- 语法
COPY...
或COPY ["",..."
"]
:要复制的源文件或目录,支持使用通配符
:目标路径,即正在创建的image的文件系统路径; 建议为
使用绝对路径,否则,COPY指定则以WORKDIR
为其实路径;
- 文件复制准则
必须是build上下文中的路径,不能是其父目录中的文件
- 如果
是目录,则其内部文件或子目录会被递归复制,但
目录自身不会被复制
- 如果指定了多个
,或在
中使用了通配符,则
必须是一个目录,且必须以/
结尾 - 如果
事先不存在,它将会被自动创建,这包括其父目录路径
- 测试dockerfile文件内容为:
# Description: test image FROM busybox:latest MAINTAINER "xdd
" # LABEL maintainer="xdd "# 指定环境路径 # WORKDIR=/data/ # 复制单个文件 COPY index.html /data/web/html/ # 复制目录下的所有文件 COPY yum.repos.d /etc/yum.repos.d/
docker build -t tinyhttpd:v0.1-1 ./
#更具当前目录下的dockerfile文件制作镜像docker run --name t1 --rm tinyhttpd:v0.1-1 cat /data/web/html/index.html
#可以测试镜像中文件是否已经存在
- 用于从Docker主机复制文件至创建的新映像文件
- ADD 命令
- ADD命令类似于COPY命令,ADD支持使用TAR文件和URL路径
- 语法:
ADD...
或ADD ["",..."
"] - 操作准则
- 同COPY指令
- 如果
为URL且不以
/
结尾,则指定的文件将被下载并直接创建为
; 如果
以/
结尾,则文件名URL指定的文件将被直接下载并保存为/ - 如果
是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于
tar -x
命令;然而,通过URL获取到的tar文件将不会自动展开; - 如果
有多个,或其间接或直接使用了通配符,则
必须是一个以/
结尾的目录路径;如果
不以/
结尾,则其被视作一个普通文件,的内容将被直接写入到
;
- VOLUME 命令(指定卷)
- 用于在image中创建一个挂载点目录,以挂载Docker host上的卷或其它容器上的卷
- 语法:
VOLUME
或VOLUME ["
"] - 如果挂载点目录路径下此前有文件存在,docker run 命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中
- EXPOSE 命令
- 用于为容器打开指定要监听的端口以实现与外部通信
- 指定暴露出的端口会绑定宿主机的随机端口
- 语法:
EXPOSE [/] [[/] ...]
用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议
- EXPOSE指令可一次指定多个端口,例如
EXPOSE 11211/udp 11211/tcp
- 指定暴露端口后的容器可以使用
-P
选项暴露端口docker run --name t2 --rm -P tinyhttpd:v0.1-7 /bin/httpd -f -h /data/web/html
docker port t2
可以查看t2暴露的端口信息
- 指定暴露端口后的容器可以使用
- ENV 命令
- 用于为镜像定义所需要的环境变量,并可被Dockerfile文件中位于其后的其它指定(如ENV、ADD、COPY等)所调用
- 调用格式为
$variable_name
或${variable_name}
- 语法:
ENV
或ENV
= ... - 第一种格式中,
之后的所有内容均被视作其
的组成部分,因此,一次只能设置一个变量; - 第二种格式可用一次设置多个变量,每个变量为一个
的键值对,如果=
中包含空格,可以以反斜线(\)
进行转义,也可通过对
加引号进行标识;另外,反斜线也可用于续行; - 定义多个变量时,建议使用第二种方式,以便在同一层中完成所有功能
- RUN 命令
- 用于指定docker build过程中运行的程序,其可以是任何命令
- 语法:
RUN
或RUN ["
","",""]
- 第一种格式中,
通常是一个shell命令,且以"/bin/sh -c"来运行它,这意味着此进程在容器中的PID不为1,不能接收Unix信号,因此,当时用docker stop
命令停止容器时,此进程接收不到SIGTERM信号;
- 第二种语法格式中的参数是一个JSON格式的数组,其中
为要运行的命令,后面的为传递给命令的选项或参数;然而,此种格式指定的命令不会以"/bin/sh -c"来发起,因此常见的shell操作如变量替换以及通配符
(?.*等)
替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。
RUN ["/bin/bash","-c","
",""]
- 注意:如果要在shell中使程序获取主进程,可以使用
exec COMMAND
来执行命令。
- Json数组中,要使用双引号
- 简单示例,在dockerfile文件中使用:
# Description: test image FROM busybox:latest MAINTAINER "xdd
" # LABEL maintainer="xdd "ENV DOC_ROOT=/data/web/html/ \ WEB_SERVER_PACKAGE="nginx-1.15.2.tar.gz"# 指定环境路径 #WORKDIR=/ #LABEL IMGDIR="/data/web/html/"COPY index.html ${DOC_ROOT:-/data/web/html/} COPY yum.repos.d /etc/yum.repos.d/ ADD http://nginx.org/download/${WEB_SERVER_PACKAGE} /usr/local/src/ #ADD ${WEB_SERVER_PACKAGE} /usr/local/src/ # 设定容器的工作目录 WORKERDIR /usr/local/RUN cd /usr/local/src && \ tar -xf ${WEB_SERVER_PACKAGE} && \ mv nginx-1.15.2 webserver# 绑定本地文件,使用docker托管的目录挂载到镜像下的/data/mysql/目录中 VOLUME /data/mysql/# 运行容器时使用-P会暴露的端口 EXPOSE 80/tcp
- 用于指定docker build过程中运行的程序,其可以是任何命令
- CMD 命令
- 类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同
- RUN指定运行与映像文件构建的过程中,而CMD指令运行与基于Dockerfile构建出的新映像文件启动一个容器时
- CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过,CMD指定的命令其可以被docker run的命令行选项所覆盖
- 在Dockerfile中可以存在多个CMD指令,但仅最后一个会生效
- 语法:
CMD
或- 会自动运行成shell的子进程,进程id不是1,然后在做进程切换转换为id为1的进程
CMD ["
或","",""] - 会直接启动一个id为1的进程,即超管进程。并不会是shell的子进程,即不支持shell环境变量。除非启动shell执行
CMD ["",""]
- 前两种语法 格式的意义同RUN
- 第三种则用于为ENTRYPOINT指令提供默认参数
- 类似于RUN指令,CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同
- ENTRYPOINT 命令
- 类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序
- 与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序
- 不过,
docker run
命令的--entrypoint
选项的参数可覆盖ENTRYPOINT指令指定的程序
- 不过,
- 语法
ENTRYPOINT
或ENTRYPOINT ["
","",""]
- docker run命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用
- Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一条会生效。
- 示例Dockerifle文件如下:
FROM busybox LABEL maintainer="xdd
" app="httpd"ENV WEB_DOC_ROOT="/data/web/html/"RUN mkdir -p $WEB_DOC_ROOT && \ echo "HEllo word xdd" > ${WEB_DOC_ROOT}/index.html#CMD ["/bin/httpd","-f","-h","${WEB_DOC_ROOT}"] # CMD/bin/httpd -f -h ${WEB_DOC_ROOT} # CMD ["/bin/sh","-c","/bin/httpd","-f","-h /data/web/html/"] CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"] ENTRYPOINT ["/bin/sh","-c"] #ENTRYPOINT /bin/sh -c
- 注意:启用时,ENTYPOINT会接受最后一个CMD命令中定义的参数,如果启动时指定命令,会默认替换掉文件中的CMD命令。例如:
docker run --name tinyweb2 -it -P tinyhttpd:v0.2-7 ls /data
- 综合示例:配置
- Dockerfile文件内容
FROM nginx:1.14-alpine LABEL maintainer="xdd
"ENV NGX_DOC_ROOT="/data/web/html/" ENV HOSTNAME="gdy" ENV PORT="8080"ADD index.html ${NGX_DOC_ROOT} ADD entrypoint.sh /bin/EXPOSE 8080CMD ["/usr/sbin/nginx","-g","daemon off; "]ENTRYPOINT ["/bin/entrypoint.sh"]
- entrypoint.sh文件内容
#!/bin/sh #cat > /etc/nginx/conf.d/www.conf << EOF server { server_name ${HOSTNAME}; listen ${IP:-0.0.0.0}:${PORT:-80}; root ${NGX_DOC_ROOT:-/usr/share/nginx/html}; } EOF# 运行传递给脚本的所有参数 exec "$@"
- index.html文件内容
nginx web
- 相关命令
- 制作镜像:
docker build -t myweb:v0.3-8 ./
- 启动镜像:
docker run --name myweb1 --rm -P myweb:v0.3-8
- 查看镜像暴露出的端口:
docker port myweb1
- 制作镜像:
- Dockerfile文件内容
- 类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序
- USER 命令
- 用于指定运行image时的或运行Dockerfile中任何RUN、CMD或者ENTRYPOINT指令指定的程序时的用户名或UID
- 默认情况下,container的运行身份为root用户
- 语法:
USER
| - 需要注意的是、
可以为任意数字,但实践中其必须为/etc/passwd中某用户的有效UID,否则,docker run命令将运行失败
- 需要注意的是、
- HEALTHCHECK 命令
- 监控容器是否还在运行。
- 这可以检测一些情况,比如web服务器陷入无限循环,无法处理新的连接,服务器进程仍然运行
- 语法:
HEALTHCHECK [options] CMD command
#通过运行一个命令检查容器健康。容器内HEALTHCHECK NONE
#禁用从基本映像继承的任何healthcheck
- 详细语法:
- 在CMD命令之前的选项有:
--interval=DURATION
#每隔多长时间执行一次,默认30s。--timeout=DURATION
#响应超时时间,默认30s--start-period=DURATION
#等待主进程启动时间(第一次执行时),默认0s--retries=N
#每次检查多少次,默认3次
- 检查请求发出时的状态:
0:success
#该容器是健康的,可以使用1:unhealthy
#容器不能正常工作2:reserved
#未使用,保留
- 例子:
HEATHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
- 修改之前一个命令例子如下:
FROM nginx:1.14-alpine LABEL maintainer="xdd
"ENV NGX_DOC_ROOT="/data/web/html/" ENV HOSTNAME="gdy" ENV PORT="8080"ADD index.html ${NGX_DOC_ROOT} ADD entrypoint.sh /bin/EXPOSE 8080/tcp 80/tcp#3秒后开启动检查,2秒后执行一条命令,即启动后移动等待5秒 HEALTHCHECK --start-period=3s --interval=2s CMD wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/CMD ["/usr/sbin/nginx","-g","daemon off; "]ENTRYPOINT ["/bin/entrypoint.sh"]
- 在CMD命令之前的选项有:
- SHELL 命令
- SHELL指令允许覆盖命令的SHELL形式所使用的默认SHELL。
- 当前默认shell在linux上是
["/bin/sh","-c"]
在windows上是["cmd","/S","/C"]
- SHELL指令必须在Dockerfile中以JSON格式编写。
- 语法:
SHELL["可执行文件","参数"]
- 语法:
- SHELL指令可以出现多次。
- 每个SHELL指令覆盖所有以前的SHELL指令,并影响所有后续指令。
- STOPSIGNAL 命令
- 发送给系统的停止信号指令
- 例如,这个信号可以是一个有效的无符号数字,它匹配内核syscall表中的某个位置。例如:9或者格式为SIGNAME的信号名,为SIGKILL
- 语法:
STOPSIGNAL signal
- ARG 命令
- ARG可以指定变量,可以在用户使用dockerfile文件制作镜像时使用
--build-arg
为将要生成的镜像重新指定变量值。有点类似于EVN命令。= - 如果用户指定了Dockerfile中没有定义的生成参数,则生成一个警告
- 语法:
ARG
=[= ] - Dockerfile可以插入一个或多个ARG指令。
- 一个ARG指令可以选择包含一个默认值:
ARG version=1.14
ARG user=xdd
- ARG可以指定变量,可以在用户使用dockerfile文件制作镜像时使用
- 【Dockerfile制作镜像】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指令中使用ADD或COPY命令应该格外小心,因为新构建过程的上下文在缺少指定的源文件时会失败。
推荐阅读
- pem pfx 是什么文件
- linux时间管理
- linux运维|GraphicsMagick命令行使用示例
- linux运维|网站框架演变
- 初识 etcd
- 创建一个Pod背后etcd的故事
- Pod 的QoS服务质量
- Ansible 运维自动化
- OpenSSL 自签证书详解
- Systemd 进程管理