Dockerfile指令详解下
VOLUME 定义匿名卷
VOLUME指令的格式为:
- VOLUME [<路径1>,<路径2>...]
- VOLUME<路径>
之前我们说过,容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据.
VOLUMN /data
这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。当然,运行时可以覆盖这个挂载设置。比如:
docker run -d -v mydata:/data xxxx
在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了Dockerfile 中定义的匿名卷的挂载配置
EXPOSE 声明端口
格式为 EXPOSE <端口1> [<端口2>...] 。
EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声
明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端。
要将 EXPOSE 和在运行时使用 -p <宿主端口>:<容器端口> 区分开来。 -p ,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
WORKDIR 指定工作目录
格式为 WORKDIR <工作目录路径>
使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改
为指定的目录,如该目录不存在, WORKDIR 会帮你建立目录。
下面的写法把Dockerfile按照Shell脚本来写,可能导致下面的错误
RUN cd /app
RUN echo "hello" > world.txt
如果将这个 Dockerfile 进行构建镜像运行后,会发现找不到 /app/world.txt 文件,或者其内容不是 hello 。原因其实很简单,在 Shell 中,连续两行是同一个进程执行环境,因此前一个命令修改的内存状态,会直接影响后一个命令;而在 Dockerfile 中,这两行 RUN 命令的执行环境根本不同,是两个完全不同的容器。这就是对 Dockerfile 构建分层存储的概念不了解所导致的错误。之前说过每一个 RUN 都是启动一个容器、执行命令、然后提交存储层文件变更。第一层 RUN cd /app 的执行仅仅是当前进程的工作目录变更,一个内存上的变化而已,其结果不会造成任何文件变更。而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能继承前一层构建过程中的内存变化。
因此如果需要改变以后各层的工作目录的位置,那么应该使用 WORKDIR 指令。
USER 指定当前用户
格式: USER <用户名>
USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层。 WORKDIR 是改变工作目录, USER 则是改变之后层的执行 RUN , CMD 以及 ENTRYPOINT 这类命令的身份。
当然,和 WORKDIR 一样, USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立
好的,否则无法切换。
如果以 root 执行的脚本,在执行期间希望改变身份,比如希望以某个已经建立好的用户来运行某个服务进程,不要使用 su 或者 sudo ,这些都需要比较麻烦的配置,而且在 TTY 缺失的环境下经常出错。建议使用 gosu
# 建立 redis 用户,并使用 gosu 换另一个用户执行命令
RUN groupadd -r redis && useradd -r -g redis redis
# 下载 gosu
RUN wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.7/
gosu-amd64" \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true
# 设置 CMD,并以另外的用户执行
CMD [ "exec", "gosu", "redis", "redis-server" ]
HEALTHCHECK 健康检查
HEALTHCHECK 指令是告诉 Docker 应该如何进行判断容器的状态是否正常,这是 Docker 1.12
引入的新指,通过该指令指定一行命令,用这行命令来判断容器主进程的服务状态是否还正常,从而比较真实的反应容器实际状态。格式:
- HEALTHCHECK [选项] CMD <命令> :设置检查容器健康状况的命令
- HEALTHCHECK NONE :如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
当在一个镜像指定了 HEALTHCHECK 指令后,用其启动容器,初始状态会为 starting ,在HEALTHCHECK 指令检查成功后变为 healthy ,如果连续一定次数失败,则会变为unhealthy
HEALTHCHECK 支持下列选项:
- --interval=<间隔> :两次健康检查的间隔,默认为 30 秒
- --timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被
视为失败,默认 30 秒 - --retries=<次数> :当连续失败指定次数后,则将容器状态视为 unhealthy ,默认 3次
和 CMD , ENTRYPOINT 一样, HEALTHCHECK 只可以出现一次,如果写了多个,只有最后一个生效。
在 HEALTHCHECK [选项] CMD 后面的命令,格式和 ENTRYPOINT 一样,分为 shell 格式,和exec 格式。命令的返回值决定了该次健康检查的成功与否: 0 :成功; 1 :失败; 2 :保留,不要使用这个值。
假设我们有个镜像是个最简单的 Web 服务,我们希望增加健康检查来判断其 Web 服务是否在正常工作,我们可以用 curl 来帮助判断,其 Dockerfile 的 HEALTHCHECK 可以这么写:
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
这里我们设置了每 5 秒检查一次(这里为了试验所以间隔非常短,实际应该相对较长),如果健康检查命令超过 3 秒没响应就视为失败,并且使用 curl -fs http://localhost/ || exit1 作为健康检查命令。
使用 docker build 来构建这个镜像:
docker build -t myweb:v1 .
构建好了后,我们启动一个容器:
docker run -d --name web -p 80:80 myweb:v1
当运行该镜像后,可以通过 docker ps 看到最初的状态为 (health: starting) ,在等待几秒钟后,再次 docker ps ,就会看到健康状态变化为了 (healthy) 。如果健康检查连续失败超过了重试次数,状态就会变为 (unhealthy)。
为了帮助排障,健康检查命令的输出(包括 stdout 以及 stderr )都会被存储于健康状态里,可以用 docker inspect 来查看
ONBUILD 为他人做嫁衣裳
格式: ONBUILD <其它指令>
ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN , COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。Dockerfile 中的其它指令都是为了定制当前镜像而准备的,唯有 ONBUILD 是为了帮助别人定制自己而准备的
Dockerfile指令详解下的更多相关文章
- Dockerfile 指令详解
GitHub Page:https://blog.cloudli.top/posts/Dockerfile-指令详解/ FROM FROM 命令指定基础镜像.在构建镜像时,基础镜像必须指定,因此在 D ...
- Dockerfile指令详解
Dockerfile中包括FROM.MAINTAINER.RUN.CMD.EXPOSE.ENV.ADD.COPY.ENTRYPOINT.VOLUME.USER.WORKDIR.ONBUILD等13个指 ...
- Dockerfile指令详解上
COPY复制文件指令 和RUN命令一样,COPY命令也有两种格式,一种类似与命令行,一种类似与函数调用,命令格式如下: COPY ... COPY ["",...] COPY将构建 ...
- Docker Dockerfile 指令详解与实战案例
Dockerfile介绍及常用指令,包括FROM,RUN,还提及了 COPY,ADD,EXPOSE,WORKDIR等,其实 Dockerfile 功能很强大,它提供了十多个指令. Dockerfile ...
- 6 Dockerfile指令详解 && ENTRYPOINT 指令
ENTRYPOINT 的格式和 RUN 指令格式一样,分为 exec 格式和 shell 格式. ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数. ENTRYPOINT 在 ...
- 3 Dockerfile指令详解-FROM&MAINTAINER&RUN
1.FROM指令 FROM centos #指定centos为基础镜像 2.MAINTAINER 指令 MAINTAINER @QQ.COM #指定维护人等信息,方便维护 3.RUN 命令 #新建 ...
- Dockerfile指令详解--VOLUME 指令
Alpine Linux是一个轻型Linux发行版,它不同于通常的Linux发行版,Alpine采用了musl libc 和 BusyBox以减少系统的体积和运行时的资源消耗.Alpine Linux ...
- 7 Dockerfile指令详解 && VOLUME 指令
格式为: VOLUME ["<路径1>", "<路径2>"...] VOLUME <路径> 之前我们说过,容器运行时应该尽量 ...
- 5 Dockerfile指令详解 && CMD 指令
CMD 指令的格式和 RUN 相似,也是两种格式: shell 格式: CMD <命令> exec 格式: CMD ["可执行文件", "参数1", ...
随机推荐
- How Autofs Works
How Autofs Works Autofs is a client-side service that automatically mounts the appropriate file syst ...
- Tomcat的杂七杂八
localhost_access_log.2016-01-15.txt 原来这里面有访问记录. /logs/catalina.2016-01-22.log 这里有显示失败的信息 2016-01-23 ...
- java bulid path 和 WEB-INF/lib 下jar 包区别
用Java Build Path导入包和把包复制到lib下是有区别的,它俩其实不会冲突,也没有什么关系的, Java Build Path是我们编译需要的包, 导入到lib下是程序运行时需要的包 , ...
- oracle常用函数速记
1.截断中文字符串 CREATE OR REPLACE function cn_cutstr(v_str varchar2,v_len number) return varchar2 IS v_i n ...
- 开始Java之旅
从今天起,cgg将给大家讲讲Java这种神奇的东西. 至于配置环境变量,大家可以看看我的博客:环境变量上面有详细解释. 下面先给大家一个公式: public class [文件名]{ ...
- KBMMW 4.81.00 发布
这次更新的速度非常快. 4.81.00 May 9 2015 Important notes (changes that may break existing code) ============== ...
- 2018.06.29 NOIP模拟 Gcd(容斥原理)
Gcd 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出n个正整数,放入数组 a 里. 问有多少组方案,使得我从 n 个数里取出一个子集,这个子集的 gcd 不为 1 ,然后我再从 ...
- C语言之计算字符串最后一个单词的长度,单词以空格隔开
//计算字符串最后一个单词的长度,单词以空格隔开. #include<stdio.h> #include<string.h> #include<windows.h> ...
- EditPlus常用快捷键[私人]
EditPlus快捷键大全网上一搜一大把, 本文档只记录自己常用的快捷键, 随时更新: 必用: ctrl + c 复制 ctrl + x 剪切 ctrl + v 粘贴 ctrl + z 回滚 ctrl ...
- 批量远程执行shell命令工具
使用示例(使用了默认用户root,和默认端口号22): ./mooon_ssh --h=192.168.4.1,192.168.4.2 -P=password -c='cat /etc/hosts' ...