Docke--Dockerfile指令介绍
Dockerfile 构建镜像常用指令
Dockerfile 是一个文本文件,其内包含了一条条的指定(Instruction),每一条指令构建一层,因此每一条指定的内容,就是描述该层应当如何构建。
通过使用build 命令,根据Dockerfile的描述来构建镜像
通过源代码的方式
通过标准输入流的方式
通过源代码的路径:
Dockerfile需要放置在项目的跟目录位置
在构建的时候,Dockerfile client会把整个context打包发送到Docker Server端,然后由server端负责build镜像,在构建成功后,会删除context目录
docker build -t {镜像名字} {项目的路径可以是相对路径}
通过标准输入流:
通过标准输入流的方式获取Dockerfile的内容
client不会打包上传context目录,因此对于一些ADD、COPY等涉及host本地文件复制的操作不能够支持
docker build -t {镜像名字} - < Dockerfile路径
已nginx 示例:
[root@server ~]# mkdir myNginx #创建一个存放Dockerfile的目录
[root@server ~]# cd myNginx
[root@server myNginx]# vim Dockerfile #编辑Dockerfile
FROM nginx
RUN echo '<h1>Hello, My Dockerfile Nginx!</h1>' > /usr/share/nginx/html/index.html
这个Dockerfile很简单,就两行。涉及到两条指令,FROM 和RUN。
FROM 指定基础镜像
所谓的定制镜像,必须是以一个镜像为基础,在其上进行定制。一个 Dockerfile 中的 FROM 是必备的指定,并且必须是第一条指令。
FROM {bash镜像}
RUN 执行命令
RUN 指令是用来执行命令行命令的,一个Dockerfile可以包含多个 RUN,按照定义顺序执行。
RUN 支持两种运行格式:
- shell 格式:RUN <cmd>,这个会当做/bin/sh -c “cmd” 运行,就像直接在命令行中输入的命令一样。比如上面的:
RUN echo '<h1>Hello, My Dockerfile Nginx!</h1>' > /usr/share/nginx/html/index.html
exec 格式:RUN ["可执行文件", "参数1", "参数2", ...],Docker 把它当做json的顺序来解析,必须使用双引号,且可执行文件必须是完整路径。
RUN 就像Shell脚本一样可以执行命令,但是也不建议一个命令对应一个RUN,像下面这样的写法
FROM centos
RUN yum install -y gcc make cmake
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz"
RUN mkdir -p /usr/src/redis
RUN tar xf redis.tar.gz -C /usr/src/redis --stript-components=
RUN cd /usr/src/redis
RUN make
RUN make install
因为Dockerfile 中的每一个指令都会建立一层,RUN 也不例外,每一个RUN 的行为,就和我们手工创建景象的过程一样,新建一层,上面的这种写法创建了7层,这样会产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也容易出错。上面的Dockerfile正确写法应该如下:
FROM centos
RUN yum install -y gcc make cmake \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redi s-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar xf redis.tar.gz -C /usr/src/redis --stript-components= \
&& cd /usr/src/redis \
&& make \
&& make install
首先,之前所有的命令只有一个目的,就是编译、安装redis 可执行文件。因此没有必要建立很多层,这只是一层的事情。因此 只需要使用一个RUN 指令,使用&& 将各个所需命令串联起来。将前面的7层简化为1层。
COPY 复制文件
格式:
- COPY <源路径> ... <目标路径>
- COPY ["<源路径1>", ... "<目标路径>"]
和 RUN 指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用。
COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。例如:
[root@server ~]# mkdir myCentos #创建一个文件夹
[root@server ~]# cd myCentos/
[root@server myCentos]# echo "hello world" >> file.txt #准备测试文件
[root@server myCentos]# mkdir dir #准备测试目录
[root@server myCentos]# touch dir/test{..}.txt #准备测试目录里面的文件
[root@server myCentos]# vim Dockerfile #编辑Dockerfile
FROM centos
COPY file.txt /mydir/
COPY dir /mydir/
[root@server myCentos]# ls #查看宿主主机的当前的测试文件
dir Dockerfile file.txt
[root@server myCentos]# ls dir/ #查看宿主机的当前的测试文件
test1.txt test2.txt test3.txt test4.txt test5.txt
[root@server myCentos]# docker build -t mycentos:v1 . #构建一个叫mycentos,标签为v1的镜像
Sending build context to Docker daemon .144kB
Step / : FROM centos
---> 1e1148e4cc2c
Step / : COPY file.txt /mydir/
---> 16250be2483b
Step / : COPY dir /mydir/dir
---> 2296f62ff0b3
Successfully built 2296f62ff0b3
Successfully tagged mycentos:v1
[root@server myCentos]# docker run -it --rm --name myC mycentos:v1 /bin/bash #启动一个容器,使用上面创建的镜像,进去并执行shell命令
[root@cc87d839493f /]# ls mydir/ #查看容器内的mydir文件夹
dir file.txt
[root@cc87d839493f /]# ls mydir/dir/ #查看容器内mydir文件夹下面的dir文件夹的文件
test1.txt test2.txt test3.txt test4.txt test5.txt
从上面示例可以看出, <目标路径> 可以是容器内的相对路径,如果该路径不存在,会自动在复制文件前创建缺失目录,且<目标路径>也可以是相对路径(工作目录可以用WORKDIR 指令来指定)
如果是拷贝目录, 那么在 目标地址 也必须写上 拷贝的目录的名称 。否则是将该目录下的所文件拷贝到目标路径
还需注意一点,使用COPY指令,源文件的各种元数据都会保留,比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建相关的文件都在使用Git进行管理的时候。
ADD 更高级的复制文件
ADD 指令和COPY 的格式和性质基本一致。但是在 COPY 基础上增加了一些功能。
比如 <源路径> 可能是一个 URL,这种情况下,会自动去下载这个链接的文件到 <目标路径>里,下载完成的文件权限自动设置为 600,如果不是想要的权限,那么可以通过 RUN 进行权限调整。
如果 <源路径> 为一个 tar 压缩文件的话,或者压缩格式为 gzip,bzip以及xz 的情况下,ADD 指令会自动解压缩这个压缩文件到 <目标路径>去。
示例
[root@server ~]# mkdir myCentos1 && cd myCentos1 #创建构建编写Dockerfile的目录并进入
[root@server myCentos1]# wget http://nginx.org/download/nginx-1.14.2.tar.gz #方便测试,先准备一个nginx1.14-2版本的
[root@server myCentos1]# vim Dockerfile #编写Dockerfile
FROM centos
ADD http://nginx.org/download/nginx-1.12.2.tar.gz /nginx/
ADD nginx-1.14.2.tar.gz /nginx/
[root@server myCentos1]# ls #编写完成查看当前目录下的文件
Dockerfile nginx-1.14..tar.gz [root@server myCentos1]# docker build -t mycentos:v2 . #开始构建一个名字叫mycentos:v2的镜像
Sending build context to Docker daemon .018MB
Step / : FROM centos
---> 1e1148e4cc2c
Step / : ADD http://nginx.org/download/nginx-1.12.2.tar.gz /nginx/
Downloading [==================================================>] .7kB/.7kB
---> a1c9717e9a03
Step / : ADD nginx-1.14..tar.gz /nginx/
---> 068c9e89ae0e
Successfully built 068c9e89ae0e
Successfully tagged mycentos:v2
[root@server myCentos1]# docker run -it --rm --name myC mycentos:v2 /bin/bash #进入容器,并执行/bin/bash命令
[root@197da52295fa /]# ls /nginx/ #查看nginx目录
nginx-1.12..tar.gz nginx-1.14.
从上面示例可以看出,ADD指令,如果我们跟的是一个URL的文件,那么会自动下载并放到 <目标路径>,如果跟的是一个压缩文件,那么会自动解压到 <目标路径>
注意:如果我们只是单纯的想复制一个文件或者一个压缩包,那么建议还是使用COPY,如果需要像上面这样用到下载,或解压缩,采用ADD
CMD 容器启动命令
容器不是虚拟机,容器就是进程,既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD 指令就是用于指定容器默认的主进程启动命令的。
CMD 指令有三种格式:
- shell 格式: CMD <命令>
- exec 格式:CMD ["可执行文件","参数1","参数2", ...]
- 参数列表格式:CMD ["参数1","参数2",...] , 这个时候CMD作为 ENTRYPOINT的参数。
在指令格式上,一般推荐使用exec 格式,这类格式在解析时会被解析为JSON数组,因此一定要使用双引号 “” ,而不要使用单引号。
如果使用shell 格式的话,实际的命令会被包装为 sh -c 的参数的形式进行执行。比如:
CMD echo $HOME
在实际执行中,会将其变更为:
CMD ["sh", "-c", "echo $HOME"]
在运行时可以指定新的命令来替代镜像设置中的这个默认命令,比如,centos镜像默认的 CMD 是 /bin/bash, 如果我们直接 docker run -it centos 的时候,会直接进入 bash。我们也可以在运行时指定别的命令,如 docker run -it centos cat /etc/passwd 。这就是用 cat /etc/passwd命令替换了默认的 /bin/bash 命令了。
前台执行和后台执行的问题:
Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 start / systemctl 去启动后台服务,容器内没有后台服务的概念。
比如:如果我们将CMD 写成这样:
CMD service nginx start
然后会发现容器执行后就立刻退出了,甚至在容器内使用systemctl 命令结果却发现根本执行不了。这就是因为没有搞明白前台、后台的概念,没有区分容器和虚拟机的差异,依旧在以传统虚拟机的角度去理解容器
对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。
而使用 service nginx start 命令,则是希望 start来已后台守护进程形式启动nginx服务。而 CMD service nginx start 会被理解为 CMD ["sh", "-c", "service nginx start"],因此主进程实际上是sh, 那么当service nginx start 命令结束后,sh 也就结束了, sh 作为主进程退出了,自然就会令容器退出。
正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式。如:
CMD ["nginx", "-g"," daemon off;"]
理解前台执行和后台执行
ENTRYPOINT 入口点
ENTRYPOINT 的格式和 RUN 指令格式一样,分为 exec 格式 和shell格式。
ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比CMD要繁琐,需要通过 docker run 的参数 --entrypoint 来指定。
当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:
ENTRYPOINT "<CMD>"
那么问题来了? 有了CMD ,为什么还要有ENTRYPOINT呢? 这种 ENTRYPOINT "<CMD>" 有什么好处呢?
场景一:让镜像变成命令一样使用
假设我们需要一个得知自己当前公网IP的镜像,那么可以使用CMD来实现:
[root@server myCentos2]# cat Dockerfile #查看Dockerfile文件内容
FROM centos
CMD ["curl", "-s", "https://ip.cn"]
[root@server myCentos2]# docker build -t mycentos:v3 . #创建一个镜像
[root@server myCentos2]# docker run mycentos:v3 #启动一个容器
当前 IP: 116.24.66.227 来自: 广东省深圳市 电信
这样看起来是可以当做命令来使用,不过命令一般有参数,CMD 中实质的命令是 curl, 如果希望显示HTTP头信息,就需要加上 -i 参数。
[root@server myCentos2]# docker run mycentos:v3 -i
docker: Error response from daemon: OCI runtime create failed: container_linux.go:: starting container process caused "exec: \"-i\": executable file not found in $PATH": unknown.
这里可以看到可执行文件找不到的报错, executable file not found。上面说过,跟在镜像名后面的是 command, 运行时会替换 CMD 的默认值,因此这里的 -i 替换了原来的 CMD,而不是添加在原来的 curl -s https://ip.cn 后面,而 -i 根本不是命令,所以找不到。
那么如果我们希望加入 -i 参数,我们就必须重新完整的输入这个命令:
[root@server myCentos2]# docker run mycentos:v3 curl -i https://ip.cn
显然这不是好的解决办法,而是用 ENTRYPOINT 就可以解决这个问题:
[root@server myCentos2]# cat Dockerfile #查看修改后的Dockerfile
FROM centos
ENTRYPOINT ["curl", "-s", "https://ip.cn"]
[root@server myCentos2]# docker build -t mycentos:v4 . #再次生成一个新的镜像
[root@server myCentos2]# docker run mycentos:v4 #测试不加参数启动镜像
当前 IP: 116.24.66.227 来自: 广东省深圳市 电信
[root@server myCentos2]# docker run mycentos:v4 -i #测试加上参数启动镜像
HTTP/1.1 OK
Date: Wed, Jan :: GMT
Content-Type: text/html; charset=UTF-
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: __cfduid=d67dbccf782da9ec6788bf87a78993a701547040189; expires=Thu, -Jan- :: GMT; path=/; domain=.ip.cn; HttpOnly
Expect-CT: max-age=, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: cloudflare
CF-RAY: 49673780decb961f-SJC 当前 IP: 116.24.66.227 来自: 广东省深圳市 电信
从上面可以看出,不加-i 参数可以运行成功, 加上-i参数也可以运行成功,且达到了curl -i 的效果。这是因为当存在 ENTRYPOINT 后,CMD 的内容将会作为参数传递给 ENTRYPOINT ,而这里 -i 就是新的CMD,因此会作为参数传递给curl,从而达到了我们预期的效果。
场景二:应用运行前的准备工作
启动容器就是启动主进程,但有些时候,启动主进程前,需要一些准备工作。比如 mysql 类的数据库,可能需要一些数据库配置、初始化的工作,这些工作要在最终的mysql 服务器运行之前解决。此外,可能希望避免使用root 用户去启动服务器, 从而提高安全性,而在启动还需要以 root 身份执行一些必要的准备工作,最后切换到服务用户启动服务等。或者除了服务外,其它命令依旧可以使用 root 身份执行,方便调试等。
这些准备工作是和容器 CMD 无关的,无论CMD 是什么,都需要事先进行一个预处理的工作。这种情况下,可以写一个脚本,然后放入 ENTRYPOINT 中去执行,而这个脚本会接到的参数 (也就是CMD)作为指令,在脚本最后执行。比如官方的redis 中就是这样做的:
FROM alpine:3.4
...
RUN addgroup -S redis && adduser -S -G redis redis
...
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE
CMD ["redis-server"]
可以看到其中为了 redis 服务创建了redis 用户,并在最后指定了 ENTRYPOINT 为 docker-entrypoint.sh 脚本。
#!/bin/bash
...
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '' ]; then
chown -R redis .
exec su-exec redis "$0" "$@"
fi exec "$@"
该脚本的内容就是根据 CMD 的内容来判断,如果是 redis-server 的话,则切换到 redis用户身份启动服务,否则依旧使用 root 身份执行。比如:
# docker run -it redis id
uid=(root) gid=(root) groups=(root)
ENV 设置环境变量
格式:
- ENV <key><value>
- ENV<key1>=<value1> <key2>=<value2>
这个指令很简单,就是设置环境变量,无论是后面的其它指令,如RUN,还是运行时的应用,都可以直接使用这里定义的环境变量。
[root@server myCentos3]# cat Dockerfile #查看编辑好的Dockerfile文件内容
FROM centos
ENV name1 xiaobai
ENV name2=zhazha name3=cainiao
[root@server myCentos3]# docker build -t mycentos:v5 . #构建镜像
[root@server myCentos3]# docker run --rm -it --name test mycentos:v5 #启动一个容器,并以交互式启动
[root@b55929b2c63f /]# echo $name1 #进入容器后调用环境变量name1
xiaobai
[root@b55929b2c63f /]# echo $name2 $name3 #调用环境变量name2,name3
zhazha cainiao
定义了环境变量,可以在后续的指令中直接使用环境变量
FROM centos
ENV URL="https://nginx.org/download/"
ADD $URLnginx.1.12..tar.gz /usr/local/
ARG 构建参数
格式:
- ARG <参数名>[=<默认值>]
构建参数和 ENV的效果一样,都是设置环境变量。所不同的是,ARG 所设置的构建环境和环境变量,在将来容器运行时是不会存在这些环境变量的。但是不要因此就使用 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值的。
Dockerfile 中的ARG指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build 中用 --build-arg <参数名>=<值> 来覆盖。
VOLUME 定义匿名卷
格式:
- VOLUME ["<路径1>","<路径2>"...]
- VOLUME <路径>
容器运行时应该尽量保持容器存储层不会发生写操作,对于数据库类需要保存动态数据的应用,其数据文件应该保存在数据卷中,为了防止运行时忘记将动态文件所保存目录挂载为卷,在Dockerfile中,可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
[root@server myCentos4]# cat Dockerfile #编写Dockerfile文件,内容如下
FROM nginx
VOLUME /usr/share/nginx/html/
[root@server myCentos4]# docker build -t mynginx:v1 . #创建一个mynginx:v1的镜像
[root@server myCentos4]# docker run -it --rm --name nginx mynginx:v1 /bin/bash #利用mynginx:v1镜像启动一个名字叫做nginx的容器
root@eaa3ffb6dda7:/# ls /usr/share/nginx/html/ #查看nginx网站目录的文件
50x.html index.html # 此时打开第二个终端,第一个终端不要关闭
[root@server ~]# docker inspect nginx #在第二个终端查看启动的nginx 容器挂载信息,会发现在宿主机上面自动挂载到了一个目录
"Mounts": [
...
"Source": "/var/lib/docker/volumes/47794aa178f1aa829d8e778f319a6bb678349926a8107f459fcb10d3b00ff8b5/_data",
...
],
[root@server ~]# ls /var/lib/docker/volumes/47794aa178f1aa829d8e778f319a6bb678349926a8107f459fcb10d3b00ff8b5/_data #查看挂载的目录,和容器中的目录一样,有同样的文件
50x.html index.html
[root@server ~]# echo "<h1>hello docker</h1>" >> /var/lib/docker/volumes/47794aa178f1aa829d8e778f319a6bb678349926a8107f459fcb10d3b00ff8b5/_data/test.html #在该目录添加文件 # 此时回到nginx容器启动的第一个终端
root@eaa3ffb6dda7:/# ls /usr/share/nginx/html/ #再次查看该目录会发现也有上面新添加的文件
50x.html index.html test.html
root@eaa3ffb6dda7:/# cat /usr/share/nginx/html/test.html #并且查看文件内容
<h1>hello docker</h1>
从上面可以看出,实际Dockerfile中只做了一件事,那就是将nginx网站目录挂载到了一个宿主机的一个匿名目录,且通过 docker inspect可以找到该目录,这样就实现了动态的更改网站数据目录的内容了。从而提高了灵活性。
同样还可以在运行容器的时候指定挂载:
[root@server myCentos4]# docker run -it --rm -v mydata:/usr/share/nginx/html/ --name nginx mynginx:v1 /bin/bash #指定挂载的目录启动容器
root@f5c496cc9846:/# # 打开第二个终端查看挂载目录
[root@server ~]# docker inspect nginx #查看挂载信息
"Mounts": [
...
"Source": "/var/lib/docker/volumes/mydata/_data",
"Destination": "/usr/share/nginx/html",
...
],
这样 使用了 mydata 这个命令卷挂载到了/usr/share/nginx/html 这个位置,替代了Dockerfile 中定义的匿名卷的挂载配置
EXPOSE 声明端口
格式:
- EXPOSE <端口1> [<端口2>...]
EXPOSE 指令是声明运行容器时提供的服务端口,这只是一个声明,在运行时并不会因为这个声明就会开启这个端口的服务。在Dockerfile中写入这样的声明有两个好处,一个是帮助使用镜像者理解这个镜像服务的守护端口,以方便配置映射;另一个用处则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射EXPOSE的端口。
WORKDIR 指定工作目录
格式:
- WORKDIR <工作目录路径>
使用 WORKDIR 指令可以来制定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,则会自动创建。
可以为RUN、CMD、ENTRYPOINT指令配置工作目录,可以使用多个WORKDIR指令,后续参数如果是相对路径,则会基于之前的命令指定的路径。如:WORKDIR /home WORKDIR test。最终路径为/home/test。path路径也可以是环境变量,比如有环境变量HOME=/home, WORKDIR $HOME/test也就是/home/test
[root@server myCentos5]# cat Dockerfile #查看编辑好的Dockerfile文件
FROM centos
WORKDIR /home/testdir
[root@server myCentos5]# docker build -t mycentos:v6 . #创建一个名字叫做mycentos:v6的镜像
[root@server myCentos5]# docker run --rm -it mycentos:v6 #使用上面创建的镜像启动一个容器
[root@4f7ae938d471 testdir]# pwd #进入容器后查看当前工作目录
/home/testdir
USER 指定当前用户
格式:
- USER <用户名>
USER 和WORKDIR 相似,都是改变环境状态并影响以后的层。WORKDIR是改变工作目录,USER 则是指定运行容器时的用户名或UID,后续的RUN、CMD、ENTRYPOINT 也会已该用户身份去运行命令。
当然,USER 只是能够切换到指定用户而已,这个用户必须事先建立好,否则无法切换。
RUN groupadd -r redis && useradd -r -g redis redis
USER redis
RUN ["redis-server"]
HEALTHCHECK 健康检查
格式:
- HEALTHCHECK [选项] CMD <命令>:设置检查容器健康的命令
- HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK 指令是告诉Docker 应该如何进行判断容器的状态是否正常
当在一个镜像指定了 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可以这样写:
[root@server myNginx1]# cat Dockerfile
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
[root@server myNginx1]# docker build -t mynginx:v2 .
[root@server myNginx1]# docker run -d --name web -p 80:80 mynginx:v2
这里设置了每5秒检查一次(这里为了测试所以间隔非常短,实际应该相对较长),如果健康检查命令超过3秒没响应就视为失败,并且使用 curl -fs http://localhost/ || exit 1 作为健康检查命令。
当运行改镜像启动的容器后,可以通过 docker ps 看到最初的状态为(health:starting):
[root@server myNginx1]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fb9c72f7a6de mynginx:v2 "nginx -g 'daemon of…" seconds ago Up seconds (health: starting) 0.0.0.0:->/tcp web
再等待几秒钟后,再次 docker ps,就会看到健康检查状态变成了 (healthy):
[root@server myNginx1]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fb9c72f7a6de mynginx:v2 "nginx -g 'daemon of…" seconds ago Up seconds (healthy) 0.0.0.0:->/tcp web
如果健康检查连续失败超过了重试次数,状态就会变为 (unhealthy)。
Docke--Dockerfile指令介绍的更多相关文章
- Docker学习(三): Dockerfile指令介绍
特别声明: 博文主要是学习过程中的知识整理,以便之后的查阅回顾.部分内容来源于网络(如有摘录未标注请指出).内容如有差错,也欢迎指正! =============系列文章============= 1 ...
- docker之Dockerfile指令介绍
Docker通过对于在Dockerfile中的一系列指令的顺序解析实现自动的image的构建 通过使用build命令,根据Dockerfiel的描述来构建镜像 通过源代码路径的方式 通过标准输入流的方 ...
- Dockerfile指令介绍
FROM:指定基础镜像 在Dockerfile中FROM是必备的指令,用于指定基础的镜像. FROM centos:latest LABEL:指定镜像标签 LABEL指令用来指定镜像的标签. 格式: ...
- docker(8)Dockerfile指令介绍
前言 Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明. Dockerfile简介 Dockerfile是用来构建Docker镜像的构建文件,是由一系列 ...
- docker学习笔记17:Dockerfile 指令 ONBUILD介绍
ONBUILD指令可以为镜像添加触发器.其参数是任意一个Dockerfile 指令. 当我们在一个Dockerfile文件中加上ONBUILD指令,该指令对利用该Dockerfile构建镜像(比如为A ...
- Docker(二):Dockerfile 使用介绍
上一篇文章Docker(一):Docker入门教程介绍了 Docker 基本概念,其中镜像.容器和 Dockerfile .我们使用 Dockerfile 定义镜像,依赖镜像来运行容器,因此 Dock ...
- Docker(二):Dockerfile使用介绍
上一篇文章Docker(一):Docker入门教程介绍了 Docker 基本概念,其中镜像.容器和 Dockerfile .我们使用 Dockerfile 定义镜像,依赖镜像来运行容器,因此 Dock ...
- Docker应用三:Dockerfile使用介绍(以安装redis为例)
Dockerfile使用介绍 一.Dockerfile介绍 Dockerfile用于自定义创建docker镜像,是由一行行命令组成的文件. Docker file中的命令根据作用分为四类: 1.1.指 ...
- C#中的预编译指令介绍
原文:C#中的预编译指令介绍 1.#define和#undef 用法: #define DEBUG #undef DEBUG #define告诉编译器,我定义了一个DEBUG的一个符号,他类似一个变量 ...
- corosync+pacemaker的crmsh的常用指令介绍
配置crmsh的yum仓库,此仓库的RPM包有openSUSE提供,将这个network:ha-clustering:Stable.repo文件直接下载到本地并且命名为crmsh.repo wget ...
随机推荐
- 前后端分离密码登陆加密RSA方案(java后端)
前言:密码加密有很多种方案,这里不做过多讨论,本篇文章是基于RSA加密实现. 首先在前端工程中需要引入加密js: "jsencrypt": "2.3.1",(注 ...
- 折腾Java设计模式之中介者模式
博文原址:折腾Java设计模式之中介者模式 中介者模式 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性.这种模式提供了一个中介类,该类通常处理不同类之间的通信,并 ...
- HeadFirst设计模式读书笔记之策略模式
1. 例子 1. 做一个鸭子模拟器,里面有很多不同的鸭子,有的可以游泳,有的可以睡觉,有的可以呱呱叫,一般套路是定义一个鸭子的超类,在 超类里定义睡觉,游泳,呱呱叫的方法,再让不同的鸭子子类继承这个超 ...
- Dotnetcore 开发速记
1.System.InvalidOperationException:"Internal connection fatal error." 全球固定模式,坑爹 https://gi ...
- Openlayers系列(一)关于地图投影相关错误的解决方案
背景 近期开发以MongoDB为基础的分布式地理数据管理平台系统,被要求做一个简单的demo给客户进行演示.于是笔者便打算向数据库中存储一部分瓦片数据,写一个简单的存取服务器,使用Openlayers ...
- 教你一步永久激活WebStorm2018
工欲善其事必先利其器,我们在开发过程中,编辑器是我们提高开发效率及生产必备的工具,如何发现一个高效好用的编辑器是程序员必备的技能之一. 前端开发有众多编辑器 sublime.vscode.webstr ...
- python类的继承、封装和多态
摘自https://www.cnblogs.com/evablogs/p/6724477.html 继承 1 2 3 4 5 6 7 8 class Person(object): def _ ...
- Oracle 安装步骤、安装中错误处理、完整卸载
/*************************************************以下ORACLE服务端安装************************************* ...
- AI-2048 注释
针对2048游戏,有人实现了一个AI程序,可以以较大概率(高于90%)赢得游戏,并且作者在 stackoverflow上简要介绍了AI的算法框架和实现思路. 有博客介绍了其中涉及的算法,讲的很好 其中 ...
- HTML基础-------HTML标签(1)
HTML标签(1) h系列(容器级双标签) h系列标签分为六个等级(h1,h2,h3,h4,h5,h6) 语义:给文本添加一个标题 标题重要程度逐级递减,一个页面只能有一个h1级的标签,并且大多数时候 ...