目录
总结之前学习docker的笔记,如有描述不当的地方,欢迎评论区留言~
docker镜像
docker镜像采用分层构建机制,最底层为bootfs,其之为rootfs
bootfs:用于系统引导的文件系统,包括bootloader,kernel,容器启动完成后会被卸载以节约内存资源;
rootfs:位于bootfs之上,表现为docker容器的根文件系统
docker中,rootfs由内核挂载为“readonly”模式,而后通过“联合挂载”技术额外挂载一个“可写层”
传统模式中,系统启动时,内核挂载rootfs时会首先将其挂载为“readonly”模式,完整性自检完成后将其重新挂载为读写模式
最底层的称为基础镜像,位于下层的镜像称为父镜像。最上层为“可读写”层,其下的均为“只读”层。当删除容器时,会同时删除wriable层。
Aufs即advanced multi--layered unification filesystem:高级多层统一文件系统
用于为Linux文件系统实现“联合挂载”
aufs是之前的UnionFS的重新实现,2006年由Junjiro Okajima开发;
Docker最初使用aufs作为容器文件系统层,它目前仍作为存储后端之一来支持;
aufs的竞争产品是overlayfs,后者自从3.18版本开始被合并到Linux内核;
dockert的分层镜像,除了aufs,dockeri还支持btrs,devicemapper和vs等
在Ubuntu系统下,docker)默认Ubuntu的aufs;而在CentOS7上,用的是devicemapper;
docker镜像的获取:
$docker pull <register>[:<port>]/[<namespace>/]<name>:<tag>
$docker pull quay.io/coreos/flannel:v0.15.1-amd64
docker镜像的制作方法:
1、Docker file
2、Docker commit,基于容器制作
3、Automated builds第三种还是基于dockerfile的
基于容器制作镜像:
$docker run --name b1 -it busybox
与busybox联合,创建b1,在容器内创建新文件,然后生成镜像
-->
/ # ls
bin dev etc home proc root run sys tmp usr var
/ # mkdir -p /data/html
/ # vi /data/html/index.html
制作镜像
$docker commit -a "lisjob <123@qq.com>" -c 'CMD ["/bin/httpd","-f","-h" "/data/html"]' -p b1 lwj/httpd:v0.1-1
-p制作镜像时要先将容器停止
-a作者信息等
-c修改默认的编辑
tag:lwj/httpd:v0.1-1
如果创建镜像时忘记打标签,可以先提交镜像再打标签
$docker commit -p b1
$docker image ls 查看ID
$docker tag ID lwj/httpd:v0.1-1
利用制作的镜像创建容器 t1 ,可以看到之前创建镜像时创建的文件,在t1内也能使用
$docker run --name t1 -it lwj/httpd:v0.1-1
/ # ls
bin data dev etc home proc root run sys tmp usr var
/ # ls /data
html
/ # cat /data/html/index.html
<h1>hello busybox</h1>
上传镜像
登录账号(docker官方账号)
$docker login -u lisrepo
Input your password
确保harbor内有仓库目录,提前新建一个,我这里建了一个httpd的目录
推镜像:
$docker push lisrepo/httpd
The push refers to a repository [docker.io/lisrepo/httpd]
f5d380d90e81: Layer already exists
d94c78be1352: Layer already exists
v0.1-1: digest: sha256:44422f812589dbecc05e2633f84f6b99a6b9c82cdef822ec97bf8529470ba4bd size: 734
也可以上传至阿里云仓库,登录阿里云账号,还是要确保已经创建了httpd目录,步骤如下所示:
使用官方给定的命令,即可完成镜像上传
如果已经在服务器S1端制作了镜像,需要打包发给S2,这样另一个服务器在使用镜像时就不用再去仓库pull了,并且S1端也无需上传,采用如下操作:
S1端:
$docker save -o PACKAGES.gz image1 image2
$scp PACKAGES.gz S2:/root
S2端:
$docker load -i PACKAGES.gz
$docker images
可以看到image1 image2
基于docker file制作:
格式:
Format
#Comment
INSTRUCTION arguments
顺序执行,大小写一般不区分,大写最好。第一个非注释行必须是FORM,类似于(#!/bin/bash)但是FROM不必须位于第一行。每条指令都会创建一个新的镜像层并对镜像进行提交,docker
大体上按照以下流程执行dockerfile内的指令:
- docker从基础镜像运行一个容器
- 执行一条指令,就生成一个新镜像,对容器作出修改
- docker再基于刚提交的镜像运行一个新容器
- 执行dcokerfile的下一条指令,直至文件结束
dcokerfile内环境变量:
$variable_name 或者${variable_name }
${variable:-word}表示variable可能不存在,表示变量为空或者未设置时,引用时使用word;若变量自己有值,则使用变量自身的值。
${variable:+word}表示variable有值时显示word;若变量自己没有值,则不执行。
dockerfile instructions:
FROM:
FROM是最重要的一个并且必须为Dockerfile文件开篇的第一个非注释行,用于为映像文件构建过程指定基准镜像(base image),实践中,基准镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件docker。如果找不到指定的镜像文件,docker build会返回一个错误信息..如果在同一个dockfile内创建多个镜像时,可以使用多个FROM指令(一个镜像一次)。
·Syntax
·FROM<repository>:[<tag>]或
·FROM<resository>@<digest>
·<reposotiry>:指定作为base image的名称;
·<tag>:base image的标签,为可选项,省略时默认为latest;
MAINTAINER:
镜像作者,联系方式
COPY:
用于从docker主机复制文件至创建的新映像文件,不支持文件提取和压缩
syntax:
COPY<src>...<dest>或者
COPY["<src>"..."<dest>"]
<src>:要复制的源文件或者目录,支持使用通配符
<dest>:目标路径,即正在创建的image的文件系统路径;建议为<dest>使用绝对路径,否则COPY指定则以WORKDIR为其起始路径;
文件复制准则
<src>必须是build上下文中的路径,不可是父目录 中的文件
若<src>为目录,则其内部文件或者子目录会被递归复制,但<src>目录自身不会被复制
若指定多个<src>,或者<src>中使用了通配符,则<dest>必须为一个目录,且必须以/结尾
若<dest>事先不存在,它将会被自动创建,这包括其父目录路径
WORKDIR:
为dockerfile内所有的RUN,CMD,ENTRYPOINT,COPY,ADD指定,设定工作目录
syntax:
WORKDIR<dirpath>
在dockerfile文件中,WORKDIR指令可出现多次,其路径也可以为相对路径,不过,其是相对此前一个WORKDIR指令指定的路径;另外,WORKDIR也可以由ENV指定定义的变量
例如:
WORKDIR /var/log
WORKDIR $STATEPATH
ADD:
ADD指令和COPY很像,支持使用TAR文件和URL路径
syntax:
ADD <src>...<dest>或者ADD ["<src>"..."<dest>"]
操作准则:
同COPY指令
如果<src>是一个本地系统的压缩格式的tar(gzip,bzip2,xz)文件,它将被展开为一个目录,其行为类似于“tar -x”命令,但是,通过URL获取到的tar文件将不会被自动展开(本地的会展开,通过URL获取的不会展开)
如果<src>有多个,或者其间接或者直接的使用了通配符,则<dest>必须是一个以/结尾的目录路径;若<dest>不以/结尾,则其被视为一个普通文件,<src>的内容将被直接写入到<dest>
若<src>为URL且<dest>不以/结尾,则<src>指定的文件将被下载并直接创建为<dest>;如果<dest>以/结尾,则文件名URL指定的文件将被直接下载并保存为<dest>/<filename>,如果目的位置不存在,docker会自动创建此目录,包括路径内的任何目录(mkdir -p),权限为0755,UID,GID均为0
例如:
ADD software.lic /opt/application/software.lic
将 构建目录下的 software.lic 文件复制到镜像中的/opt/application/software.lic
VOLUME:
用于向基于镜像创建的容器添加卷,一个卷是可以存在于一个或者多个容器内特定的目录,这个目录可以绕过联合文件系统,并提供共享数据和对数据持久化的功能。
卷功能能让我们将数据,比如源代码,数据库或者其他的内容添加到镜像中而不是将这些内容提交到镜像中,并运行我们在多个容器间共享这些内容,我们可以利用此功能来测试容器和内部的应用程序代码,管理日志,或者处理容器内部的数据库。
syntax:
VOLUME <mountpoint>或者VOLUME ["<mountpoint>"]
如果挂载点目录路径下此前在文件存在,Docker run命令会在卷挂载完成后将此前的所有文件复制到新挂载的卷中。镜像中定义存储卷,当基于镜像启动容器时会自动拥有这个存储卷
如
VOLUME ["/opt/project"]
为基于此镜像创建的容器创建一个名为/opt/project的挂载点,也可以通过指定数组的方式来指定多个卷.
ONBUILD:
此指令可以为docker设置触发器,当一个镜像被用作是其他镜像的基础镜像时,该镜像内的触发器会被执行;触发器会在构建过程中创建新指令,可以认为这些指令是紧跟在FROM之后指定的,触发器可以是任何构建指令,例如:
ONBUILD ADD ./app/src
ONBUILD RUN cd /app/src && make
此代码会在创建的镜像中加入ONBUILD触发器,ONBUILD指令可以在镜像上运行docker inspect命令来查看。 并且需要注意的是,ONBUILD触发器只能被继承一次,也就是说,只能在子镜像中执行,而不会在孙镜像执行。
实验一:ONBUILD触发器示例
构建一个镜像,名为tinyhttpd:v0.1-6,其dockerfile中用到了ONBUILD,内容如下
#Description:test image
FROM busybox:latest
LABEL maintainer="1638083879@qq.com"
ENV DOC_ROOT=/data/web/html/ \
WEB_SERVER_PACKAGE="nginx-1.16.1"
COPY index.html ${DOC_ROOT:-/data/web/html/}
COPY yum.repos.d /etc/yum.repos.d/
WORKDIR /usr/local/
ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/
#ADD http://nginx.org/download/nginx-1.16.1.tar.gz /usr/local/src/
VOLUME /data/httpd/
ONBUILD ADD . /var/www/
EXPOSE 80/tcp
~
~
构建tinyhttpd:v0.1-6 镜像
docker build -t tinyhttpd:v0.1-6 ./
在镜像构建完毕后,可以通过inspect查看镜像中的ONBUILD
docker inspect
...
"OnBuild": [
"ADD . /var/www/"
],
...
...
基于此tinyhttpd:v0.1-6 镜像构建一个新的镜像tinyhttpd:v0.1-7 ,其dockefile文件如下
FROM tinyhttpd:v0.1-6
LABEL maintainer="1638083879@qq.com"
构建镜像
[root@node01 ~/img2]#docker build -t tinyhttpd:v0.1-7 ./
Sending build context to Docker daemon 35.84kB
Step 1/2 : FROM tinyhttpd:v0.1-6
# Executing 1 build trigger
---> 2b41556c9a0e
Step 2/2 : LABEL maintainer="1638083879@qq.com"
---> Running in 00b3d12dad10
Removing intermediate container 00b3d12dad10
---> fd7ebd7d89e7
Successfully built fd7ebd7d89e7
Successfully tagged tinyhttpd:v0.1-7
可以看到在FROM之后,Docker插入了一条ADD指令,这条ADD指令就是在ONBUILD触发器中指定的,执行完此ADD指令后,Docker才会继续执行构建文件中的后续指令。
EXPOSE:
用于为容器打开指定要监听的端口以实现与外部通信
syntax:
EXPOSE <port>[/<protocol>] <port>][/<protocol>]...]
<protocol>用于指定传输层协议,tcp,udp二者之一,默认是tcp
EXOPSE指令可以一次指定多个端口,例如
EXPOSE 11211/udp 11211/tcp
注意:镜像中指定的端口,在docker run 时加上-P选项,才会暴露
ENV:
用于为镜像定义所需的环境变量,并可被dockerfile文件中位于其后的其他指令(如ENV,ADD,COPY,等)所调用。也可以在docker run命令行时使用-e选项指定临时的环境变量,这些变量只会在执行命令时有效。
调用格式:$variabele_name ${variable_name}
syntax:
ENV <key> <value>或
ENV <key>=<value> ...
第一种格式,<key>之后的所有内容都会被视为<value>的组成部分,因此,一次只可以设置一个变量
第二种格式,可一次设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<value>中含空格,可以以 反斜线 \ 进行转义,也可以通过对<value>加引号进行标识,其次,反斜线也可以用于续行
定义多个变量时,建议使用格式二
实验二、制作镜像步骤示例:
1.创建工作目录:
$mkdir img1
$cd img1
2.工作目录内存放制作镜像所需要的文件
$cp -r /etc/yum.repos.d/ ./
$wget http://nginx.org/download/nginx-1.16.1.tar.gz
3.制作Dockerfile文件,D一定要大写
#Description:test image
FROM busybox:latest
LABEL maintainer="1638083879@qq.com"
ENV DOC_ROOT=/data/web/html/ \
WEB_SERVER_PACKAGE="nginx-1.16.1"
COPY index.html ${DOC_ROOT:-/data/web/html/}
COPY yum.repos.d /etc/yum.repos.d/
WORKDIR /usr/local/
ADD ${WEB_SERVER_PACKAGE}.tar.gz ./src/
#ADD http://nginx.org/download/nginx-1.16.1.tar.gz /usr/local/src/
VOLUME /data/httpd/
EXPOSE 80/tcp
~
4.编译镜像文件:
$cd img1
$docker build -t tinyhttpd:v0.1-1 ./
5.使用镜像文件创建容器
$docker run -P --rm --name tiny1 tinytest:v0.1-1
RUN:
在当前镜像中运行指定的命令,每条RUN指令都会创建一个新的镜像层,如果该指令执行成功,则会将此镜像层提交,之后执行dockerfile的下一条指令。
syntax:
RUN <command> 或者RUN ["<executable>","[param1]","<param2>"]
第一种格式中,<command>一般是一个shell命令,且以“/bin/sh -c”来运行它,这意味着此进程的pid不为1,不可以接收unix信号,因此,当使用docker stop <container>命令停止容器时,此进程接收不到SIGTERM信号(pid=1的是init,内核完成之后启动的第一个进程,然后init根据/etc/inittab的内容再去启动其它进程)
第二种语法格式中,参数是一个JSON格式的数组,其中,<excutable>为要运行的命令,后面的<paramN>为传递给命令的选项或者参数;此种格式指定的命令不会由“/bin/sh -c”来发起,因此常见的shell操作如变量替换以及通配符(?.*等)替换将不会进行;不过,如果要运行的命令依赖于此shell特性的话,可以将其替换为类似于下面的格式:
RUN ["/bin/bash","-c","<excutable>","<param1>"]
例如
RUN ["apt-get","install","-y","nginx"]
COMMAND:
类似于RUN指令,CMD也可以用于运行任何命令或者应用程序,不过,二者运行的时间点不一样。
RUN指令运行在镜像文件的构建过程中,CMD运行在基于Dockfile构建出的新映像文件启动一个容器时
在Dockfile里可以存在多个CMD指令,但仅有最后一个生效
CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止,不过,CMD指定的命令可以被docker run的命令行选项所覆盖
syntax:
CMD <command>或者
CMD ["<execuable>","<param1>","<param2>"]或者
CMD ["<param1>","<param2>"]
前两种语法格式意义同RUN,第三种则用于为ENTRYPOINT指令提供默认参数
RUN和COMMAND的区别:
RUN的第三种格式与ENTRYPOINT结合的例子:
ENTRYPOINT ["/usr/sbin/nginx"]
CMD ["-h"]
此时当我们启动该容器时,命令行指定的参数都会被传给nginx守护进程,此时,比如指定-g "daemon off";这个参数让nginx守护进程以前台方式运行。如果启动时不加任何参数,则在CMD指令的-h参数会被传递给nginx进程,即nginx会以/usr/sbin/nginx -h的方式启动,该命令来显示nginx的帮助信息。
所以CMD与ENTRYPOINT结合的这种命令,可用来实现构建一个镜像,此镜像既可以运行默认的命令,也支持通过docker run的命令行为该命令指定可覆盖的选项或者标志。
ENTRYPOINT:
类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序
与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定的程序
但是通过docker run命令得--entrypoint选项可以覆盖ENTRYPOINT指令指定的程序
syntax:
ENTRYPOINT <command>
ENTRYPOINT ["<executable>","<param1>","<param2>"]
docker run 命令传入的命令参数会覆盖CMD指令的参数并且附加到ENTRYPOINT命令最后作为其参数使用
在Dockfile里可以存在多个ENTRYPOINT指令,但仅有最后一个生效
即就是: 定义多个CMD,最后一个生效,多个ENTRYPOINT,最后一个生效,CMD和ENTRYPOINT同时存在,CMD的命令会被当做参数传给ENTRYPPOINT;容器接收参数是靠环境变量。
USER:
指定运行images时或运行dockerfile中任何RUN,CMD,ENTRYOPINT指令指定的程序时的用户名或者UID以及组或者GID,或者是两者组合。也可以在docker run命令行通过-u 来覆盖指令指定的值。
如果不通过USRE指令指定用户,默认情况下,container运行身份为root用户
syntax:
USER <UID> | <UserName>
<UID>可以是任意数字,但是实践中必须为/etc/passwd中某用户有效的UID,否则,Docker run命令会失效。
实验三、分别使用了CMD的两种语法格式
第一种语法格式,自动启动Shell的子进程,因此支持Shell语法
$vim Dockerfile
FROM busybox
LABEL maintainer="lucy <123@qq.com>" app="httpd"
ENV WEB_DOC_ROOT="/data/web/html/"
RUN mkdir -p $WEB_DOC_ROOT && \
echo '<h1>Busybox httpd server.</h1>' > ${WEB_DOC_ROOT}/index.html
CMD /bin/httpd -f -h ${WEB_DOC_ROOT} #CMD命令运行时间点是基于新镜像启动一个容器时
$docker build -t tinyhttpd:v0.2-1 ./
$docker image inspect tinyhttpd:v0.2-1
"Cmd": [
"/bin/sh", #/bin/sh来运行程序
"-c",
"/bin/httpd -f -h ${WEB_DOC_ROOT}"
],
$docker run --name tinyweb1 -it --rm -P tinyhttpd:v0.2-1
由于Dockerfile文件里默认用bash命令启动httpd服务,httpd服务是没有交互式的,因此重新启动终端进入容器内
$docker exec -it tinyweb1 /bin/sh
/ # ps -a
PID USER TIME COMMAND
1 root 0:00 /bin/httpd -f -h /data/web/html/ #使用exec command来使命令运行在SHELL内,为了不违背SHELL为进程1的原则,这里HTTPD为进程1(其实仍为bin/sh的子进程),当使用docker stop/kill就会停止容器
6 root 0:00 /bin/sh
11 root 0:00 ps -a
/ # printenv 环境变量
WEB_DOC_ROOT=/data/web/html/
HOSTNAME=933287cb09fc
SHLVL=1
HOME=/root
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
CMD的第二种语法格式
$vim Dockfile
FROM busybox
LABEL maintainer="lucy <123@qq.com>" app="httpd"
ENV WEB_DOC_ROOT="/data/web/html/"
#自动启动Shell的子进程,因此支持Shell语法
RUN mkdir -p $WEB_DOC_ROOT && \
echo '<h1>Busybox httpd server.</h1>' > ${WEB_DOC_ROOT}/index.html
#json数组格式,默认不会以shell环境执行,因此内核不会把${WEB_DOC_ROOT}识别为环境变量,而是由-h将${WEB_DOC_ROOT}识别为一个路径。"/bin/sh" -c可以手动使其运行shell环境
CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
#CMD ["/bin/sh","-c","/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
查看环境变量和1进程方法同上。
编译容器:
$docker build -t tinyhttpd:v0.2-2 ./
$docker image inspect tinyhttpd:v0.2-2
"Cmd": [
"/bin/httpd", #不以shell环境执行
"-f",
"-h ${WEB_DOC_ROOT}"
],
启动容器会报找不到文件错误:
[root@centos7 ~/img2]#docker run --name tinyweb2 -it --rm -P tinyhttpd:v0.2-2
httpd: can't change directory to ' ${WEB_DOC_ROOT}': No such file or directory
手动改为shell子进程
$Vim Dockerfile
CMD ["/bin/sh","-c","/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
再次编译容器:
$docker build -t tinyhttpd:v0.2-3 ./
$docker inspect image tinyhttpd:0.2-3
"Cmd": [
"/bin/sh",
"-c",
"/bin/httpd",
"-f",
"-h ${WEB_DOC_ROOT}"
],
注意:定义多个CMD,最后一个生效
根据entrypoint文件编译镜像:
$vim entrypont.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 "$@"
~
~
~
需要的html文件
$vim index.html
<h1>New Doc Root for nginx</h1>
创建文件夹
$mkdir img3
$cd img3
根据entrypoint.sh文件创建dockerfile
$vim Dockerfile
FROM nginx:1.14-alpine
LABEL maintainer="lucy <123@qq.com>"
ENV NGX_DOC_ROOT='/data/web/html/'
ADD index.html ${NGX_DOC_ROOT}
ADD entrypoint.sh /bin/
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
接着就是老一套~编译镜像,创建容器~
$docker build -t tinyhttpd:v0.3-1 ./
$docker run --name myweb1 --rm -P -it tinyhttpd:v0.3-1
在另一终端上进入容器可以看到html的内容
$docker exec -it myweb1 /bin/sh
/ # cat //etc/nginx/conf.d/www.conf
server {
server_name 9ff998aa757b;
listen 0.0.0.0:80;
root /data/web/html/;
}
/ # wget -O - -q 9ff998aa757b
<h1>New Doc Root for nginx</h1>
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
/ # 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
9 root 0:00 /bin/sh
17 root 0:00 ps
容器健康状况检测:
容器健康状况检测是用来测试一个容器是否在工作
syntax:
HEALTHCHECK [OPTIONS] CMD command (check container health by running a command inside the container)
OPTIONS:
--interval=DURATION 默认30s
--timeout=DURATION默认30s
--start-period=DURATION 默认0s
--retries=N 默认3次
存在状态值反映了勇气的健康状态,有以下几种:
0:容器时健康的
1:不健康
2:预留值,无意义
例子:
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
实验四、给dockerfile内加入健康检查
$vim Dockerfile
FROM nginx:1.14-alpine
LABEL maintainer="lucy <123@qq.com>"
ENV NGX_DOC_ROOT='/data/web/html/'
ADD index.html ${NGX_DOC_ROOT}
ADD entrypoint.sh /bin/
EXPOSE 80/tcp
HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
当给以上的dockerfile内加入健康检查再编译时,出现了以下错误
Step 7/9 : HEALTHCHECK --start-period=3s CMD wget -O - -q http://${IP:-0.0.0.0}:${PORT:-80}/
Unknown flag: start-period
出错原因:docker版本太老,需要docker-ce 至少为17.05 ;
查看版本
$docker -v
升级版本,升级版本后docker的配置文件会存在daemon.json daemon.json.rpmsave
重命名即可:
$mv /etc/docker/daemon.json{.rpmsave,}
重启docker,再进行编译即可
$systemctl start docker
[root@centos7 ~/img3]#docker -v
Docker version 20.10.11, build dea9396
根据镜像启动容器,我们这里用-e替换暴露的端口为8080,可以看到30s会发一个GET请求
进入容器内,查看其暴露的端口正是设置的8080