09-Docker镜像构建¶
Dockerfile简单介绍¶
一张图就能学会Dockerfile你知道吗?
Dockerfile是非常容易学的,和SHELL相比那简单的太多了。
Dockerfile是为快速构建docker image而设计的,当你使用docker build 命令的时候,docker 会读取当前目录下的命名为Dockerfile(首字母大写)的纯文本文件并执行里面的指令构建出一个docker image。这比SaltStack的配置管理要简单的多,不过还是要掌握一些简单的指令。
Dockerfile 由一行行命令语句组成,并且支持以#开头的注释行。指令是不区分大小写的,但是通常我们都大写。
Dockerfile的四大部分¶
基础镜像信息
维护者信息
镜像操作指令
容器启动时执行指令
Dockerfile图表理解¶
类型 | 解释 |
---|---|
FROM | 基础镜像来自于 |
MAINTAINER | 作者信息 |
RUN | 你先让他干啥(把命令前面加上RUN) |
ADD | 往他肚子里放点文件(COPY文件,会自动解压) |
WORKDIR | 我的cd,(当前工作目录) |
VOLUME | 给我一个存放行李的地方(目录挂载) |
EXPOSE | 我要打开的门是啥(端口) |
RUN | 奔跑吧,兄弟!(进程要一直运行下去) |
C | 镜像启动时需要执行的 |
简单构建Dockerfile¶
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。 基于 Dockerfile 构建镜像可以使用 docker build 命令。docker build 命令中使用-f 可以指定具体的dockerfile 文件
mkdir /root/dockerfile -p
cd /root/dockerfile/
echo "hello world" >index.html
[root@linux-bkce-node21 dockerfile]# vi Dockerfile
FROM centos:7.9.2009
MAINTAINER chris
RUN yum -y install epel-release
RUN yum -y install nginx wget
COPY index.html /usr/share/nginx/html/
EXPOSE 80
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]
docker build -t mynginx:v1 ./
dockerfile 构建过程:
1.从基础镜像运行一个容器
2.执行一条指令,对容器做出修改
3.执行类似 docker commit 的操作,提交一个新的镜像层
4.再基于刚提交的镜像运行一个新的容器
5.执行 dockerfile 中的下一条指令,直至所有指令执行完毕
构建完毕之后,我们就可以Run起来。
docker run --name nginx01 -d -p8080:80 mynginx:v1
环境清理
docker rm -f nginx01
docker rmi -f mynginx:v1
Dockerfile指令详解¶
下面我们来分别介绍下上面使用到的命令:
FROM¶
格式:FROM
解释:FROM是Dockerfile里的第一条指令(必须是),后面跟有效的镜像名(如果该镜像你的本地仓库没有则会从远程仓库Pull取)。然后后面的其它指令FROM的镜像中执行。
例子:
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM nginx
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -d -p8080:80 mydemo:v1
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
MAINTAINER¶
格式:MAINTAINER
解释:指定维护者信息。 例子:
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM nginx
MAINTAINER chris
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -d -p8080:80 mydemo:v1
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
RUN¶
格式:RUN
解释:运行命令,命令较长使可以使用\来换行。推荐使用上面数组的格式
例子:
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
RUN yum -y install wget
RUN ["/bin/bash","-c","echo hello"]
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -it mydemo:v1 /bin/bash
rpm -qa|grep wget
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
COPY¶
COPY
格式:
COPY [--chown=
例子:
cd /root/dockerfile/
echo "This is dockerfile COPY demo" >index.html
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
COPY index.html /usr/share/nginx/html/
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -it mydemo:v1 /bin/bash
[root@f2d42048dc97 /]# cat /usr/share/nginx/html/index.html
This is dockerfile COPY demo
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
ADD¶
格式:
ADD
ADD ["
解释:将指定的
所有拷贝到container中的文件和文件夹权限为0755,uid和gid为0
如果文件是可识别的压缩格式,则docker会帮忙解压缩
ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下, 会自动复制并解压到 <目标路径>。 ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像 构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
例子:
cd /root/dockerfile/
echo "This is dockerfile ADD demo" >index.html
tar zcf index.html.tar.gz index.html
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
ADD index.html.tar.gz /usr/share/nginx/html/
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -it mydemo:v1 /bin/bash
[root@c52f02bac63f /]# ls -l /usr/share/nginx/html/
total 4
-rw-r--r-- 1 root root 28 Apr 12 02:12 index.html
[root@c52f02bac63f /]# cat /usr/share/nginx/html/index.html
This is dockerfile ADD demo
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
rm -f /root/dockerfile/index.html.tar.gz
CMD¶
格式:
CMD ["executable","param1","param2"] 使用 exec 执行,推荐方式;
CMD command param1 param2 在 /bin/sh 中执行,提供给需要交互的应用;
CMD ["param1","param2"] 提供给ENTRYPOINT的默认参数;
解释:
CMD指定容器启动时执行的命令,每个Dockerfile只能有一条CMD命令, 如果指定了多条,只有最后一条会被执行。 如果你在启动容器的时候也指定的命令,那么会覆盖Dockerfile构建的镜像里面的CMD命令。
类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
1、CMD 在 docker run 时运行。 2、RUN 是在 docker build 构建镜像时运行的
例子:
cd /root/dockerfile/
echo "This is dockerfile CMD demo" >index.html
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
RUN yum -y install epel-release
RUN yum -y install nginx wget
COPY index.html /usr/share/nginx/html/
CMD echo "demo" >/tmp/demo.txt
CMD ["/usr/sbin/nginx","-g","daemon off;"]
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -d -p8080:80 mydemo:v1
[root@linux-bkce-node21 ~]# sh /root/in01.sh demo01
[root@8e012b8b5d9c ~]# ps -ef|grep nginx|grep sbin
root 56769 56747 0 10:25 ? 00:00:00 nginx: master process /usr/sbin/nginx -g daemon off;
[root@linux-bkce-node21 ~]# sh /root/in02.sh demo01
[root@8e012b8b5d9c /]# ls /tmp/
ks-script-DrRL8A yum.log
[root@8e012b8b5d9c /]# ls -l /tmp/
total 4
-rwx------ 1 root root 836 Nov 13 2020 ks-script-DrRL8A
-rw------- 1 root root 0 Nov 13 2020 yum.log
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
EXPOSE¶
格式:EXPOSE
解释:设置Docker容器内部暴露的端口号,如果需要外部访问,还需要启动容器时增加-p或者-P参数进行分配。
EXPOSE 的用途:
1、在Dockerfile中声明了那些端口是将要开放的。
2、在构建容器时通过 -P (大写的P)可以随机映射端口。(如果EXPOSE没有指定端口,那么使用 -P 参数无效)
准确来说 Dockerfile 中的 EXPOSE用处不大!原因:
1、真正的暴露端口是在创建容器 run 的时候指定的 -p 或者 -P 参数,先来说说 -p 参数后面跟的是【主机端口:容器端口】,那么问题就来了既然在运行的时候还需要指定端口那么 EXPOSE还要什么用呢!
2、当我们创建容器 run 的时候指定参数是 -P,那么在运行之后 会把 EXPOSE 的端口随机映射到主机的不同端口,这时问题又来了既然映射到不同的端口那么容器的端口就是是随机的不确定的,那就要在运行之后才能知道端口,这样使用起来是极其不便的。
本着存在即合理的想法来解释一下EXPOSE的真正用途:
EXPOSE可以不用但是不能没有,因为 Dockerfile 不一定是一个人维护的,或者说当下一个运维人员接手项目之后能够通过 Dockerfile 里面的参数掌握整体的逻辑,一切还是为了规范。
例子:
cd /root/dockerfile/
echo "This is dockerfile EXPOSE demo" >index.html
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
RUN yum -y install epel-release
RUN yum -y install nginx wget
COPY index.html /usr/share/nginx/html/
EXPOSE 80
CMD ["/usr/sbin/nginx","-g","daemon off;"]
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -d -p 8080:80 mydemo:v1
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
ENTRYPOINT¶
格式:
ENTRYPOINT ["executable", "param1","param2"]
ENTRYPOINT command param1 param2(shell中执行)。
类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。 但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 entrypoint 指令指定的程序。 优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。 注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
ENTRYPOINT ["/usr/bin/rethinkdb"]
CMD ["--help"]
列子:
现在我们开始做一个nginx镜像
cd /root/dockerfile/
echo "This is dockerfile ENTRYPOINT demo" >index.html
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
RUN yum -y install epel-release
RUN yum -y install nginx wget
COPY index.html /usr/share/nginx/html/
ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -d -p 8080:80 mydemo:v1
[root@linux-bkce-node21 dockerfile]# curl 192.168.1.21:8080
This is dockerfile ENTRYPOINT demo
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
USER¶
格式:USER daemon
解释:指定运行容器时的用户名和UID,后续的RUN指令也会使用这里指定的用户。
用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
列子:
现在我们开始做一个centos镜像
cd /root/dockerfile/
echo "This is dockerfile USER demo" >index.html
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
RUN ls -l /root
RUN whoami
RUN useradd docker01 ; echo "123456"|passwd --stdin docker01
USER docker01
RUN whoami
EOF
docker build -t mydemo:v1 ./
ENV¶
格式:ENV
ENV
解释:设置环境变量,可以在RUN之前使用,然后RUN命令时调用,容器启动时这些环境变量都会被指定
列子:
现在我们开始做一个centos镜像
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
ENV VERSION=1.0.0
ENV VERSION01=1.0.1
ENV VERSION02=1.0.2
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -it mydemo:v1 /bin/bash
[root@cd8eee5f0f80 /]# env|grep VERSION
VERSION=1.0.1
[root@3ad7642b58da /]# echo $VERSION02
1.0.2
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
ARG¶
https://www.cnblogs.com/poloyy/p/15476476.html
格式:ARG
解释:ARG指定了一个变量在docker build的时候使用,可以使用--build-arg
详解 在执行 docker build 时,可以通过 --build-arg <参数名>=<值> 来为声明的变量赋值 当镜像编译成功后,ARG 指定的变量将不再存在(ENV指定的变量将在镜像中保留) Docker内置了一些镜像创建变量,用户可以直接使用而无须声明,包括(不区分大小写)HTTP_PROXY、HTTPS_PROXY、FTP_PROXY、NO_PROXY
ARG 和 ENV 的区别 ARG 定义的变量只会存在于镜像构建过程,启动容器后并不保留这些变量 ENV 定义的变量在启动容器后仍然保留
注意 不要通过 ARG 保存密码之类的信息,因为 docker history 还是可以看到所有值的
构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
列子:
如果在 FROM 指令之前指定,那么只能用于 FROM 指令中
cd /root/dockerfile
cat >Dockerfile<<\EOF
FROM centos:7.9.2009
ARG DOCKER_USERNAME=ubuntu
RUN set -x ; echo ${DOCKER_USERNAME}
RUN cat /etc/redhat-release
EOF
docker build -t mydemo:v1 --build-arg DOCKER_USERNAME=test .
docker history mydemo:v1
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
VOLUME¶
格式:VOLUME ["/data"]
解释:可以将本地文件夹或者其他container的文件夹挂载到container中。
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。 作用: 1、避免重要的数据,因容器重启而丢失,这是非常致命的。 2、避免容器不断变大。
格式: VOLUME ["<路径 1>", "<路径 2>"...] VOLUME <路径> 在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。
相信大部分人对docker run -v这个参数都比较熟悉,无非就是把宿主机目录和容器目录做映射,以便于容器中的某些文件可以直接保存在宿主机上,实现容器被删除之后数据还在,比如我们把mysql装在容器中,肯定不能说容器被删mysql所有的数据也都不在了。第二个作用是也可以用来实现多容器共享同一份文件。
volume和run -v的区别,什么时候需要使用volume
容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
那么Dockerfile中的VOLUME指令实际使用中是不是就是跟docker run中的-v参数一样是将宿主机的一个目录绑定到容器中的目录以达到共享目录的作用呢? 并不然,其实VOLUME指令只是起到了声明了容器中的目录作为匿名卷,但是并没有将匿名卷绑定到宿主机指定目录的功能。 当我们生成镜像的Dockerfile中以Volume声明了匿名卷,并且我们以这个镜像run了一个容器的时候,docker会在安装目录下的指定目录下面生成一个目录来绑定容器的匿名卷(这个指定目录不同版本的docker会有所不同),我当前的目录为:/var/lib/docker/volumes/{容器ID}。
总结: volume只是指定了一个目录,用以在用户忘记启动时指定-v参数也可以保证容器的正常运行。比如mysql,你不能说用户启动时没有指定-v,然后删了容器,就把mysql的数据文件都删了,那样生产上是会出大事故的,所以mysql的dockerfile里面就需要配置volume,这样即使用户没有指定-v,容器被删后也不会导致数据文件都不在了。还是可以恢复的。
volume指定的位置在容器被删除以后数据文件会被删除吗
volume与-v指令一样,容器被删除以后映射在主机上的文件不会被删除。
如果-v和volume指定了不同的位置,会发生什么事呢?
会以-v
设定的目录为准,其实volume
指令的设定的目的就是为了避免用户忘记指定-v
的时候导致的数据丢失,那么如果用户指定了-v
,自然而然就不需要volume指定的位置了。
总结:
其实一般的dockfile如果不是数据库类的这种需要持久化数据到磁盘上的应用,都是无需指定volume的。指定volume只是为了避免用户忘记指定-v时导致的数据全部在容器中,这样的话容器一旦被删除所有的数据都丢失了。 那么为什么dockerfile中不提供一个能够映射为主机目录:容器目录这样的指令呢?其实这样的设计是有道理的,如果在dockerfile中指定了主机目录,这样dockerfile就不具备了可移植性了,毕竟每个人所需要映射的目录可能是不同的,那么最好的办法就是把这个权利交给每个运行这个dockerfile的人,所以才会有 run -v 主机目录:容器目录 这样的指令。
例子:
创建测试目录:
mkdir -p /data
echo "This is VOLUME demo" >/data/volume.txt
现在我们开始做一个centos镜像
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
VOLUME ["/data"]
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -d -it mydemo:v1 /bin/bash
[root@linux-bkce-node21 dockerfile]# docker ps |grep demo01
5f0ae025f02a mydemo:v1 "/bin/bash" 33 seconds ago Up 31 seconds demo01
[root@linux-bkce-node21 dockerfile]# docker inspect 5f0ae025f02a|grep -A 5 Mounts
"Mounts": [
{
"Type": "volume",
"Name": "bb37ada0a46572707eeacf161295cf14d9c1cbc075ea574e107202dc1d561436",
"Source": "/var/lib/docker/volumes/bb37ada0a46572707eeacf161295cf14d9c1cbc075ea574e107202dc1d561436/_data",
"Destination": "/data",
docker run --name demo02 -it -v /data:/opt mydemo:v1 /bin/bash
[root@45bf28b24396 /]# ls -l /opt/
total 8
-rw-r--r-- 1 root root 28 Apr 6 15:14 myvolume.txt
-rw-r--r-- 1 root root 20 Apr 12 04:37 volume.txt
[root@45bf28b24396 /]# cat /opt/volume.txt
This is VOLUME demo
环境清理
docker rm -f demo01
docker rm -f demo02
docker rmi -f mydemo:v1
WORKDIR¶
格式:WORKDIR/path/to/workdir
解释:切换目录,为后续的RUN、CMD、ENTRYPOINT 指令配置工作目录。
可以多次切换(相当于cd命令),
也可以使用多个WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
则最终路径为 /a/b/c。
现在我们开始做一个centos镜像
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
RUN mkdir /a/b/c -p
WORKDIR /a
RUN pwd
WORKDIR b
RUN pwd
WORKDIR c
RUN pwd
EOF
docker build -t mydemo:v1 ./
环境清理
docker rmi -f mydemo:v1
LABEL¶
LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:
LABEL
现在我们开始做一个centos镜像
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
EOF
docker build -t mydemo:v1 ./
检查镜像属性
docker image inspect --format='' mydemo:v1
HEALTHCHECK¶
Dockerfile-HEALTHCHECK指令 https://www.cnblogs.com/weiyiming007/p/10186087.html
用于指定某个程序或者指令来监控 docker 容器服务的运行状态。 格式: HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令 HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令 HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
下面我们主要介绍第一种形式的应用: options的可设定参数:
interval:间隔(s秒、m分钟、h小时),从容器运行起来开始计时interval秒(或者分钟小时)进行第一次健康检查,随后每间隔interval秒进行一次健康检查;还有一种特例请看timeout解析。
--start-period=DURATION 启动时间, 默认 0s, 如果指定这个参数, 则必须大于 0s ;--start-period 为需要启动的容器提供了初始化的时间段, 在这个时间段内如果检查失败, 则不会记录失败次数。 如果在启动时间内成功执行了健康检查, 则容器将被视为已经启动, 如果在启动时间内再次出现检查失败, 则会记录失败次数。
timeout:执行command需要时间,比如curl 一个地址,如果超过timeout秒则认为超时是错误的状态,此时每次健康检查的时间是timeout+interval秒。 retries:连续检查retries次,如果结果都是失败状态,则认为这个容器是unhealth的
CMD关键字后面可以跟执行shell脚本的命令或者exec数组。CMD后面的命令执行完的返回值代表容器的运行状况,可能的值:
0 health状态,1 unhealth状态,2 reserved状态,这个没细研究,用的也很少。 注意:在Dockerfile中只能有一个HEALTHCHECK指令。如果您列出多个,则只有最后一个HEALTHCHECK将生效。
现在我们开始做一个nginx镜像
cat >test.sh<<\EOF
nginx_count=$(ps -ef|grep nginx|wc -l)
if [ $nginx_count != 1 ];then
echo 0
exit 0
else
echo 1
exit 1
fi
EOF
cd /root/dockerfile/
echo "This is dockerfile HEALTHCHECK demo" >index.html
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM centos:7.9.2009
MAINTAINER chris
RUN yum -y install epel-release
RUN yum -y install nginx wget
COPY index.html /usr/share/nginx/html/
EXPOSE 80
CMD ["/usr/sbin/nginx","-g","daemon off;"]
ADD test.sh /opt/
HEALTHCHECK --interval=10s --timeout=5s --retries=3 CMD sh /opt/test.sh
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -it -d -p 8080:80 mydemo:v1 /bin/bash
sh /root/in01.sh demo01
环境清理
docker rm -f demo01
docker rmi -f mydemo:v1
ONBUILD¶
用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜 像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
ONBUILD 指定的命令在构建镜像时并不执行,而是在它的子镜像中执行
为镜像添加触发器 当一个镜像被其他镜像作为基础镜像时需要写上 OBNBUILD 会在构建时插入触发器指令
例子01:
现在我们开始做一个nginx01镜像
cd /root/dockerfile/
echo "This is dockerfile ONBUILD demo" >index.html
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM nginx
MAINTAINER chris
ONBUILD COPY index.html /usr/share/nginx/html/
EXPOSE 80
EOF
docker build -t mydemo:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -d -p 8081:80 mydemo:v1
curl 192.168.1.21:8081
例子02:
现在我们开始做一个nginx02镜像
cd /root/dockerfile/
echo "This is dockerfile ONBUILD demo" >index.html
cd /root/dockerfile
cat >Dockerfile<<EOF
FROM mydemo:v1
MAINTAINER chris
EXPOSE 80
EOF
docker build -t mydemo:v2 ./
构建完毕之后,我们就可以Run起来。
docker run --name demo02 -d -p 8082:80 mydemo:v2
sleep 3
curl 192.168.1.21:8082
环境清理
docker rm -f demo01
docker rm -f demo02
docker rmi -f mydemo:v1
docker rmi -f mydemo:v2
生产环境如何构建镜像¶
系统层==》运行环境层==〉应用服务层
生产环境实战准备¶
(1)创建好目录
[root@linux-node1 ~]# mkdir /opt/docker
[root@linux-node1 ~]# cd /opt/docker
[root@linux-node1 docker]# mkdir app/{xxx-admin,xxx-api} -p
[root@linux-node1 docker]# mkdir runtime/{java,php,python} -p
[root@linux-node1 docker]# mkdir system/{centos,centos-ssh,ubuntu} -p
下面为创建的结构图
[root@linux-node1 docker]# cd /opt/docker
[root@linux-node1 docker]# yum -y install unzip
提前下载好centos7.6的基础镜像
docker pull centos:7.6.1810
docker pull centos:7.9.2009
docker pull registry.cn-beijing.aliyuncs.com/chris-demo/centos:latest
构建基础centos-init镜像容器¶
创建基础centos镜像容器专属目录
mkdir /root/dockerfile/centos -p
配置sshd自动启动
cd /root/dockerfile/centos
cat >>supervisord.conf<<\EOF
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
EOF
下载yum文件
curl -o /root/dockerfile/centos/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /root/dockerfile/centos/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
编写centos的基本镜像的文件
cat >Dockerfile<<\EOF
# Docker for CentOS
#Base image
FROM registry.cn-beijing.aliyuncs.com/chris-demo/centos:7.9.2009
#Who
MAINTAINER Jason.admin admin@gmail.com
#EPEL
ADD epel.repo /etc/yum.repos.d/
ADD CentOS-Base.repo /etc/yum.repos.d/
#Base pkg
RUN echo "nameserver 223.5.5.5" > /etc/resolv.conf ; cat /etc/resolv.conf ; ping -c 4 223.5.5.5
RUN echo "nameserver 223.6.6.6" >> /etc/resolv.conf ; cat /etc/resolv.conf ; ping -c 4 223.6.6.6
RUN yum clean all && yum repolist
RUN yum -y install openssh-clients openssl-devel openssh-server wget mysql-devel supervisor git redis tree net-tools sudo psmisc ansible initscripts net-tools vim tmux supervisor ; yum clean all
RUN yum group -y install "Minimal Install" ; yum clean all
RUN yum -y install wget redis git tree net-tools ansible tmux vim supervisor
## For SSHD
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN echo "root:123456" | chpasswd
#set supervisor
RUN mkdir -p /var/log/supervisor
ADD supervisord.conf /etc/supervisord.conf
# start run supervisor
EXPOSE 22
ENTRYPOINT /usr/bin/supervisord -u root -c /etc/supervisord.conf
EOF
(2)下面是生成基本系统镜像的文件,
[root@harbor01 centos]# ls -l /root/dockerfile/centos/
total 16
-rw-r--r-- 1 root root 2523 Apr 12 15:13 CentOS-Base.repo
-rw-r--r-- 1 root root 1027 Apr 12 15:09 Dockerfile
-rw-r--r-- 1 root root 664 Apr 12 15:13 epel.repo
-rw-r--r-- 1 root root 71 Apr 12 15:12 supervisord.conf
(3)现在开始构建镜像
cd /root/dockerfile/centos
docker build -t centos:init-2025-06-30 .
(4)查看构建的镜像
docker images|grep centos|grep init
运行一个容器
docker run --name demo01 -d -it -p 22222:22 centos:init-2025-06-30 /bin/bash
进入容器
docker exec -it demo01 /bin/bash
ss -ltnp
rpm -qa|wc -l
cat /etc/redhat-release
ip addr
lsblk
ping -c 4 www.baidu.com
exit 0
清理容器
docker rm -f demo01
构建基础centos-mini镜像容器¶
创建基础centos镜像容器专属目录
mkdir /root/dockerfile/centos -p
配置sshd自动启动
cd /root/dockerfile/centos
cat >>supervisord.conf<<\EOF
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
EOF
下载yum文件
curl -o /root/dockerfile/centos/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /root/dockerfile/centos/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
编写centos的基本镜像的文件
cat >Dockerfile<<\EOF
# Docker for CentOS
#Base image
FROM registry.cn-beijing.aliyuncs.com/chris-demo/centos:7.9.2009
#Who
MAINTAINER Jason.admin admin@gmail.com
#EPEL
ADD epel.repo /etc/yum.repos.d/
ADD CentOS-Base.repo /etc/yum.repos.d/
#Base pkg
RUN echo "nameserver 223.5.5.5" > /etc/resolv.conf ; cat /etc/resolv.conf ; ping -c 4 223.5.5.5
RUN echo "nameserver 223.6.6.6" >> /etc/resolv.conf ; cat /etc/resolv.conf ; ping -c 4 223.6.6.6
RUN yum clean all && yum repolist
RUN yum group -y install "Minimal Install" ; yum clean all
RUN yum -y install openssh-clients openssl-devel openssh-server supervisor
## For SSHD
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN echo "root:123456" | chpasswd
#set supervisor
RUN mkdir -p /var/log/supervisor
ADD supervisord.conf /etc/supervisord.conf
#run supervisor
CMD /usr/bin/supervisord -u root -c /etc/supervisord.conf
# start run supervisor
EXPOSE 22
ENTRYPOINT /usr/bin/supervisord -u root -c /etc/supervisord.conf
EOF
(2)下面是生成基本系统镜像的文件,
[root@harbor01 centos]# ls -l /root/dockerfile/centos/
total 16
-rw-r--r-- 1 root root 2523 Apr 12 15:13 CentOS-Base.repo
-rw-r--r-- 1 root root 1027 Apr 12 15:09 Dockerfile
-rw-r--r-- 1 root root 664 Apr 12 15:13 epel.repo
-rw-r--r-- 1 root root 71 Apr 12 15:12 supervisord.conf
(3)现在开始构建镜像
cd /root/dockerfile/centos
docker build -t centos:mini-2025-06-30 .
(4)查看构建的镜像
docker images|grep centos|grep mini
运行一个容器
docker run --name demo01 -d -it -p 22222:22 centos:mini-2025-06-30 /bin/bash
进入容器
docker exec -it demo01 /bin/bash
ss -ltnp
rpm -qa|wc -l
cat /etc/redhat-release
ip addr
lsblk
ping -c 4 www.baidu.com
exit 0
清理容器
docker rm -f demo01
构建基础centos-tiny镜像容器¶
创建基础centos镜像容器专属目录
mkdir /root/dockerfile/centos -p
配置sshd自动启动
cd /root/dockerfile/centos
cat >>supervisord.conf<<\EOF
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
EOF
下载yum文件
curl -o /root/dockerfile/centos/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /root/dockerfile/centos/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
编写centos的基本镜像的文件
cat >Dockerfile<<\EOF
# Docker for CentOS
#Base image
FROM registry.cn-beijing.aliyuncs.com/chris-demo/centos:7.9.2009
#Who
MAINTAINER Jason.admin admin@gmail.com
#EPEL
ADD epel.repo /etc/yum.repos.d/
ADD CentOS-Base.repo /etc/yum.repos.d/
#Base pkg
RUN echo "nameserver 223.5.5.5" > /etc/resolv.conf ; cat /etc/resolv.conf ; ping -c 4 223.5.5.5
RUN echo "nameserver 223.6.6.6" >> /etc/resolv.conf ; cat /etc/resolv.conf ; ping -c 4 223.6.6.6
RUN yum clean all && yum repolist
RUN yum -y install openssh-clients openssl-devel openssh-server wget mysql-devel supervisor tree net-tools sudo psmisc initscripts net-tools vim tmux supervisor ; yum clean all
## For SSHD
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN echo "root:123456" | chpasswd
#set supervisor
RUN mkdir -p /var/log/supervisor
ADD supervisord.conf /etc/supervisord.conf
EXPOSE 22
ENTRYPOINT /usr/bin/supervisord -u root -c /etc/supervisord.conf
EOF
(2)下面是生成基本系统镜像的文件,
[root@harbor01 centos]# ls -l /root/dockerfile/centos/
total 16
-rw-r--r-- 1 root root 2523 Apr 12 15:13 CentOS-Base.repo
-rw-r--r-- 1 root root 1027 Apr 12 15:09 Dockerfile
-rw-r--r-- 1 root root 664 Apr 12 15:13 epel.repo
-rw-r--r-- 1 root root 71 Apr 12 15:12 supervisord.conf
(3)现在开始构建镜像
cd /root/dockerfile/centos
docker build -t centos:tiny-2025-06-30 .
(4)查看构建的镜像
docker images|grep centos|grep tiny
运行一个容器
docker run --name demo01 -d -it -p 22222:22 centos:tiny-2025-06-30 /bin/bash
进入容器
docker exec -it demo01 /bin/bash
ss -ltnp
rpm -qa|wc -l
cat /etc/redhat-release
ip addr
lsblk
ping -c 4 www.baidu.com
exit 0
清理容器
docker rm -f demo01
验证基础容器¶
下载容器镜像
docker pull registry.cn-beijing.aliyuncs.com/chris-demo/centos:tiny-2025-06-30
docker pull registry.cn-beijing.aliyuncs.com/chris-demo/centos:mini-2025-06-30
docker pull registry.cn-beijing.aliyuncs.com/chris-demo/centos:init-2025-06-30
构建完毕之后,我们就可以Run起来。
docker run --name demo01 -d -it -p 22223:22 registry.cn-beijing.aliyuncs.com/chris-demo/centos:tiny-2025-06-30 /bin/bash
docker run --name demo02 -d -it -p 22224:22 registry.cn-beijing.aliyuncs.com/chris-demo/centos:mini-2025-06-30 /bin/bash
docker run --name demo03 -d -it -p 22225:22 registry.cn-beijing.aliyuncs.com/chris-demo/centos:init-2025-06-30 /bin/bash
进入容器
docker exec -it demo01 /bin/bash
ss -ltnp
rpm -qa|wc -l
cat /etc/redhat-release
exit 0
docker exec -it demo02 /bin/bash
ss -ltnp
rpm -qa|wc -l
cat /etc/redhat-release
exit 0
docker exec -it demo03 /bin/bash
ss -ltnp
rpm -qa|wc -l
cat /etc/redhat-release
exit 0
查看容器资源
docker stats
环境清理
docker rm -f demo01
docker rm -f demo02
docker rm -f demo03
基于基础容器构建nginx容器¶
例子:
配置sshd 自动启动
mkdir -p /root/dockerfile/nginx
cd /root/dockerfile/nginx
cat >>supervisord.conf<<\EOF
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd -D
[program:nginx]
command=/usr/sbin/nginx -c /etc/nginx/nginx.conf
EOF
配置dockerfile
mkdir -p /root/dockerfile/nginx
cd /root/dockerfile/nginx
echo "This is centos base nginx demo" >index.html
cd /root/dockerfile/nginx
cat >Dockerfile<<\EOF
FROM centos:base
MAINTAINER chris
RUN yum -y install nginx wget
COPY index.html /usr/share/nginx/html/
ADD supervisord.conf /etc/supervisord.conf
EXPOSE 80
ENTRYPOINT /usr/bin/supervisord -u root -c /etc/supervisord.conf
EOF
docker build -t mynginx:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name nginx01 -d -it -p 8080:80 -p 2222:22 mynginx:v1 /bin/bash
curl 192.168.1.21:8080
ssh 192.168.1.21 -p2222
环境清理
docker rm -f nginx01
docker rmi -f mynginx:v1
基于基础容器构建tomcat容器¶
例子:
mkdir -p /root/dockerfile/tomcat
cd /root/dockerfile/tomcat
cat >Dockerfile<<\EOF
FROM centos:base
MAINTAINER chris
#RUN yum install wget -y
ADD jdk-8u45-linux-x64.rpm /usr/local/
ADD apache-tomcat-8.0.26.tar.gz /usr/local/
RUN cd /usr/local && rpm -ivh jdk-8u45-linux-x64.rpm
RUN mv /usr/local/apache-tomcat-8.0.26 /usr/local/tomcat8
ENTRYPOINT /usr/local/tomcat8/bin/startup.sh && tail -F /usr/local/tomcat8/logs/catalina.out
EXPOSE 8080
EOF
docker build -t mytomcat:v1 ./
构建完毕之后,我们就可以Run起来。
docker run --name tomcat01 -d -p 8080:8080 mytomcat:v1
打开浏览器访问:http://192.168.1.21:8080/
环境清理
docker rm -f tomcat01
docker rmi -f mytomcat:v1