一. Docker的安装

  1. Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker 。这里我们使用CentOS 7.7.1908
uname
  1. 使用 root 权限登录 CentoS。确保 yum 包更新到最新。
yum update
  1. 卸载旧版本(如果安装过旧版本的话)
yum remove docker  docker-common docker-selinux docker-engine
  1. 安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
yum install
  1. 设置yum源
# 使用官方源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 如果官方yum源获得不了或者下载慢就启用阿里云的源
rm
  1. 安装最新版本的Docker
yum install
  1. 启动Docker并设置开机启动
systemctl start docker
systemctl enable
  1. 验证Docker
docker version
  1. Docker HelloWorld测试;
docker run hello-world

因为本地没有这个镜像,所以从远程官方仓库去拉取。
然后我们再执行一次。

问题及处理:

  • 出现错误
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers).
See 'docker run --help'.
  • 修正DNS的解析结果
yum install -y bind-utils
dig
  • 修改Docker镜像源为阿里云
    登陆网址 https://cr.console.aliyun.com
  • Docker学习笔记-2(业务部署)_docker


  • Docker学习笔记-2(业务部署)_tomcat_02

  • 使用命令 docker info 查看 Registry Mirrors: 是否是你加速后的URL。

二. 将本地镜像推送到阿里云

登陆阿里云开发者平台
​​​ https://cr.console.aliyun.com​Docker学习笔记-2(业务部署)_docker_03
填写必要信息然后
Docker学习笔记-2(业务部署)_docker_04
创建镜像仓库
Docker学习笔记-2(业务部署)_docker_05
通过管理可以在“操作指南中”获得推送镜像的帮助。
登陆认证的口令存放在/root/.docker/config.json,且密文存储。

push完成后在REPOSITORY中会出现一项IMAGE ID相同的registry.cn-chengdu.aliyuncs.com/xxx/yyy。

在这里查看push到阿里云的镜像。

Docker学习笔记-2(业务部署)_tomcat_06

三. 将容器中的目录挂载至宿主机(容器卷)

  • 效果是双向同步。
  • 命令格式
docker run -d -v /宿主机目录1:/容器目录1 -v /宿主机目录2:/容器目录2 镜像ID

注意:宿主机和容器目录不必事先存在。两种目录在不存在的情况下会随着启动容器而由docker自动创建。

如果同步的是多级目录,可能会出现权限不足的提示。这时因为selinux禁用了访问权限。这时需要添加 --privileged=true 来解决目录挂载权限不足问题。

  • 设置容器中的目录只读
docker run -d -v /宿主机目录:/容器目录:ro 镜像ID

四. 私有仓库搭建

  • 第一步:拉取私有仓库镜像 (私有仓库程序本身就是一个镜像)
docker pull registry
  • 第二步:启动私有仓库容器
docker run -d --name=myRegistry -p 5000:5000 registry
  • 第三步:测试
    ​​​ http://ip:5000/v2/_catalog​​ 出现下载_catalog.json的界面说明成功。此时仓库里还没有镜像,所以就是空的。
  • 第四步:/etc/docker/ 中修改daemon.json,让docker信任私有仓库地址。
    注意是json格式,{ }内的多个配置项之间需要用“ ,”分隔。
{
"insecure-registries": ["192.168.74.166:5000"]
}
  • 第五步:修改配置后重启docker;
systemctl restart docker
  • 第六步:标记此镜像为私有仓库的镜像
docker tag tomcat:7 192.168.74.166:5000/mytomcat7
  • 第七步:上传镜像到私有仓库
docker push 192.168.74.166:5000/mytomcat7
或者
docker push 192.168.74.166:5000/mytomcat7:1.0

docker push 192.168.74.166:5000/mytomcat7:latest

此时私有仓库里已经有了这个镜像。
可通过如下命令查看私有仓库镜像:

查看私有仓库
curl -XGET http://ip:端口/v2/_catalog
curl http://192.168.74.166:5000/v2/_catalog
回显json
{"repositories":["mytomcat7"]}

获取某个镜像的标签列表
curl -XGET http://ip:端口/v2/私有仓库镜像名称/tags/list
curl http://192.168.74.166:5000/v2/mytomcat7/tags/list
回显json
{"name":"mytomcat7","tags":["latest"]}

私有仓库容器中存放的所有镜像
docker exec -it <registry_container_id> ls
  • 第八步:删除192.168.74.166:5000/mytomcat7本地仓库镜像
docker rmi -f 192.168.74.166:5000/mytomcat7
  • 第九步:从私有仓库拉取192.168.74.166:5000/mytomcat7镜像,并运行;
docker run -d -p 8080:8080 192.168.74.166:5000/mytomcat7
  • 第十步:浏览器运行 http://192.168.74.166:8080测试

五. Docker的迁移与备份

  1. 备份镜像
docker save -o 备份镜像的名称 源镜像名称:Tag版本
docker save -o mytomcat7.1.0.tar bee/tomcat7:1.0

注意不可使用镜像ID,否则镜像名称和版本就恢复不出来了。
成了这个样:
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none>
  1. 恢复镜像:
docker load -i 镜像文件
docker load -i mytomcat7.1.0.tar

六. 生成自定义的镜像

  1. commit方式
    相关命令
# Tomcat
docker cp 容器id:/usr/local/tomcat/conf /home/tomcat/
docker cp 容器id:/usr/local/tomcat/webapps /home/tomcat/

docker run -d --name 容器名称 -p 80:8080 -v /home/tomcat/conf/:/usr/local/tomcat/conf/ -v /home/tomcat/webapps/:/usr/local/tomcat/webapps/ -v /home/tomcat/logs/:/usr/local/tomcat/logs/ 镜像名称

#MySQL5.7
docker cp 容器id:/etc/mysql/conf.d /home/mysql/
docker cp 容器id:/var/log /home/mysql/
docker cp 容器id:/var/lib/mysql /home/mysql/

docker run -p 3306:3306 -d -v /etc/mysql/conf.d/:/home/mysql/conf/ -v /var/log:/home/mysql/log/ -v /var/lib/mysql/:/home/mysql/mysql/ -e MYSQL_ROOT_PASSWORD=123456 镜像ID

查询容器的接口IP地址:IPAddress
docker inspect <容器ID>
  1. Dockerfile方式

常用命令参数:

参数

描述

FROM image_name:tag

定义了使用哪个基础镜像启动构建流程

MAINTAINER user_info

声明镜像维护者信息

LABEL key value

镜像描述元信息(可以写多条)

ENV key value

设置环境变量(可以写多条)

RUN command

构建镜像时需要运行的命令(可以写多条)

WORKDIR path_dir

设置终端默认登录进来的工作目录

EXPOSE port

当前容器对外暴露出的端口

ADD source_dir/file dest_dir/file

将宿主机的文件复制到容器内,如果是一个压缩文件,将会在复制后自动解压

COPY source_dir/file dest_dir/file

和ADD相似,但是如果有压缩文件是不能解压

VOLUME

创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等

CMD

指定容器启动时要运行的命令,假如有多个CMD,最后一个生效

ENTRYPOINT

指定容器启动时要运行的命令

ONBUILD

当构建一个被继承的Dockerfile时运行的命令,父镜像在被子镜像继承后父镜像的onbuild被触发。可以把ONBUID理解为一个触发器。

CMD, ENTRYPOINT 的区别和联系:

CMD, ENTRYPOINT都是容器启动的时候,执行命令(RUN是容器构建的时候执行),都支持exec和shell方式。一般用法,是单独一个CMD,或者先ENTRYPOINT,后CMD结合使用。

假如有多个CMD,启动的时候带命令参数,会覆盖前面的CMD命令,最后一个命令生效,所以我们平时用CMD的时候,有一种情况的就是单独一个CMD命令即可,启动命令也不带参数。可以参考一下Tomcat官方的Dockerfile。

FROM openjdk:13-jdk-oracle

ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME

# let "Tomcat Native" live somewhere isolated
ENV TOMCAT_NATIVE_LIBDIR $CATALINA_HOME/native-jni-lib
ENV LD_LIBRARY_PATH ${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOMCAT_NATIVE_LIBDIR

# see https://www.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR/KEYS
# see also "update.sh" (https://github.com/docker-library/tomcat/blob/master/update.sh)
ENV GPG_KEYS 05AB33110949707C93A279E3D3EFE6B686867BA6 07E48665A34DCAFAE522E5E6266191C37C037D42 47309207D818FFD8DCD3F83F1931D684307A10A5 541FBE7D8F78B25E055DDEE13C370389288584E7 61B832AC2F1C5A90F0F9B00A1C506407564C17A3 713DA88BE50911535FE716F5208B0AB1D63011C7 79F7026C690BAA50B92CD8B66A3AD3F4F22C4FED 9BA44C2621385CB966EBA586F72C284D731FABEE A27677289986DB50844682F8ACB77FC2E86E29AC A9C5DF4D22E99998D9875A5110C01C5A2F6059E7 DCFD35E0BF8CA7344752DE8B6FB21E8933C60243 F3A04C595DB5B6A5F1ECA43E3B7BBB100D811BBE F7DA48BB64BCB84ECBA7EE6935CD23C10D498E23

ENV TOMCAT_MAJOR 8
ENV TOMCAT_VERSION 8.5.50
ENV TOMCAT_SHA512 ffca86027d298ba107c7d01c779318c05b61ba48767cc5967ee6ce5a88271bb6ec8eed60708d45453f30eeedddcaedd1a369d6df1b49eea2cd14fa40832cfb90

RUN set -eux; \
\
# http://yum.baseurl.org/wiki/YumDB.html
if ! command -v yumdb > /dev/null; then \
yum install -y yum-utils; \
yumdb set reason dep yum-utils; \
fi; \
if [ -f /etc/oracle-release ]; then \
# TODO there's an odd bug on Oracle Linux where installing "cpp" (which gets pulled in as a dependency of "gcc") and then marking it as automatically-installed will result in the "filesystem" package being removed during "yum autoremove" (which then fails), so we set it as manually-installed to compensate
yumdb set reason user filesystem; \
fi; \
# a helper function to "yum install" things, but only if they aren't installed (and to set their "reason" to "dep" so "yum autoremove" can purge them for us)
_yum_install_temporary() { ( set -eu +x; \
local pkg todo=''; \
for pkg; do \
if ! rpm --query "$pkg" > /dev/null 2>&1; then \
todo="$todo $pkg"; \
fi; \
done; \
if [ -n "$todo" ]; then \
set -x; \
yum install -y $todo; \
yumdb set reason dep $todo; \
fi; \
) }; \
_yum_install_temporary gzip tar; \
\
ddist() { \
local f="$1"; shift; \
local distFile="$1"; shift; \
local success=; \
local distUrl=; \
for distUrl in \
# https://issues.apache.org/jira/browse/INFRA-8753?focusedCommentId=14735394#comment-14735394
'https://www.apache.org/dyn/closer.cgi?action=download&filename=' \
# if the version is outdated (or we're grabbing the .asc file), we might have to pull from the dist/archive :/
https://www-us.apache.org/dist/ \
https://www.apache.org/dist/ \
https://archive.apache.org/dist/ \
; do \
if curl -fL -o "$f" "$distUrl$distFile" && [ -s "$f" ]; then \
success=1; \
break; \
fi; \
done; \
[ -n "$success" ]; \
}; \
\
ddist 'tomcat.tar.gz' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz"; \
echo "$TOMCAT_SHA512 | sha512sum --strict --check -; \
ddist 'tomcat.tar.gz.asc' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
for key in $GPG_KEYS; do \
gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
done; \
gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz; \
tar -xf tomcat.tar.gz --strip-components=1; \
rm bin/*.bat; \
rm tomcat.tar.gz*; \
command -v gpgconf && gpgconf --kill all || :; \
rm -rf "$GNUPGHOME"; \
\
# https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html#Default_web_applications
mv webapps webapps.dist; \
mkdir webapps; \
# we don't delete them completely because they're frankly a pain to get back for users who do want them, and they're generally tiny (~7MB)
\
nativeBuildDir="$(mktemp -d)"; \
tar -xf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1; \
_yum_install_temporary \
apr-devel \
gcc \
make \
openssl-devel \
; \
( \
export CATALINA_HOME="$PWD"; \
cd "$nativeBuildDir/native"; \
aprConfig="$(command -v apr-1-config)"; \
./configure \
--libdir="$TOMCAT_NATIVE_LIBDIR" \
--prefix="$CATALINA_HOME" \
--with-apr="$aprConfig" \
--with-java-home="$JAVA_HOME" \
--with-ssl=yes; \
make -j "$(nproc)"; \
make install; \
); \
rm -rf "$nativeBuildDir"; \
rm bin/tomcat-native.tar.gz; \
\
# mark any explicit dependencies as manually installed
deps="$( \
find "$TOMCAT_NATIVE_LIBDIR" -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ && $(NF-1)=>" { print $(NF-1); \
[ -z "$deps" ] || yumdb set reason user $deps; \
\
# clean up anything added temporarily and not later marked as necessary
yum autoremove -y; \
yum clean all; \
rm -rf /var/cache/yum; \
\
# sh removes env vars it doesn't support (ones with periods)
# https://github.com/docker-library/tomcat/issues/77
find ./bin/ -name '*.sh' -exec sed -ri 's|^#!/bin/sh$|#!/usr/bin/env bash|' '{}' +; \
\
# fix permissions (especially for running as non-root)
# https://github.com/docker-library/tomcat/issues/35
chmod -R +rX .; \
chmod 777 logs temp work

# verify Tomcat Native is working properly
RUN set -e \
&& nativeLines="$(catalina.sh configtest 2>&1)" \
&& nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')" \
&& nativeLines="$(echo "$nativeLines" | sort -u)" \
&& if ! echo "$nativeLines" | grep 'INFO: Loaded APR based Apache Tomcat Native library' >&2; then \
echo >&2 "$nativeLines"; \
exit 1; \
fi

EXPOSE 8080
CMD ["catalina.sh", "run"]

如果在命令行中加上参数,比如 /bin/bash 或者 ls -l,
那就会覆盖dockerfile中的CMD [“catalina.sh”,“run”]。执行的是启动时docker run 携带的参数。

其他可以参考 https://github.com/docker-library/{software}
这里的software是指软件名称,比如tomcat,redis,mysql等。
这里再参考一下redis的Dockerfile。

FROM debian:buster-slim

# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r -g 999 redis && useradd -r -g redis -u 999 redis

# grab gosu for easy step-down from root
# https://github.com/tianon/gosu/releases
ENV GOSU_VERSION 1.11
RUN set -eux; \
# save list of currently installed packages for later so we can clean up
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates \
dirmngr \
gnupg \
wget \
; \
rm -rf /var/lib/apt/lists/*; \
\
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF)"; \
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
\
# verify the signature
export GNUPGHOME="$(mktemp -d)"; \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
\
# clean up fetch dependencies
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
chmod +x /usr/local/bin/gosu; \
# verify that the binary works
gosu --version; \
gosu nobody true

ENV REDIS_VERSION 5.0.7
ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-5.0.7.tar.gz
ENV REDIS_DOWNLOAD_SHA 61db74eabf6801f057fd24b590232f2f337d422280fd19486eca03be87d3a82b

RUN set -eux; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates \
wget \
\
gcc \
libc6-dev \
make \
; \
rm -rf /var/lib/apt/lists/*; \
\
wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL"; \
echo "$REDIS_DOWNLOAD_SHA | sha256sum -c -; \
mkdir -p /usr/src/redis; \
tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1; \
rm redis.tar.gz; \
\
# disable Redis protected mode [1] as it is unnecessary in context of Docker
# (ports are not automatically exposed when running inside Docker, but rather explicitly by specifying -p / -P)
# [1]: https://github.com/antirez/redis/commit/edd4d555df57dc84265fdfb4ef59a4678832f6da
grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 1$' /usr/src/redis/src/server.h; \
sed -ri 's!^(#define CONFIG_DEFAULT_PROTECTED_MODE) 1$!\1 0!' /usr/src/redis/src/server.h; \
grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 0$' /usr/src/redis/src/server.h; \
# for future reference, we modify this directly in the source instead of just supplying a default configuration flag because apparently "if you specify any argument to redis-server, [it assumes] you are going to specify everything"
# see also https://github.com/docker-library/redis/issues/4#issuecomment-50780840
# (more exactly, this makes sure the default behavior of "save on SIGTERM" stays functional by default)
\
make -C /usr/src/redis -j "$(nproc)" all; \
make -C /usr/src/redis install; \
\
# TODO https://github.com/antirez/redis/pull/3494 (deduplicate "redis-server" copies)
serverMd5="$(md5sum /usr/local/bin/redis-server | cut -d' ' -f1)"; export serverMd5; \
find /usr/local/bin/redis* -maxdepth 0 \
-type f -not -name redis-server \
-exec sh -eux -c ' \
md5="$(md5sum "$1" | cut -d" " -f1)"; \
test "$md5" = "$serverMd5"; \
' -- '{}' ';' \
-exec ln -svfT 'redis-server' '{}' ';' \
; \
\
rm -r /usr/src/redis; \
\
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
find /usr/local -type f -executable -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
\
redis-cli --version; \
redis-server --version

RUN mkdir /data && chown redis:redis /data
VOLUME /data
WORKDIR /data

COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 6379
CMD ["redis-server"]

可以使用ENTRYPOINT 执行命令,然后使用CMD来拼接具体的执行参数。最终执行的 是 docker-entrypoint.sh redis-server。经过上面两个案例,相信大家对CMD, ENTRYPOINT 会有一定的了解。

我们再看看详细语法。

CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)
第一种用法:运行一个可执行的文件并提供参数。
第二种用法:为ENTRYPOINT指定参数。
第三种用法(shell form):是以“ /bin/sh -c ”的方法执行的命令。

ENTRYPOINT 语法。

ENTRYPOINT [“executable”, “param1”, “param2”] (exec 格式, 推荐)
ENTRYPOINT command param1 param2 (shell 格式)

下面我们通过一些简单实例,来具体看下CMD, ENTRYPOINT 的实际用法。

FROM centos
CMD echo "abc"
#CMD ["/bin/echo", "defg"]
---------------------------------------------------
docker run <container_id> echo "hello"
FROM centos
ENTRYPOINT ["ls"]
CMD ["-l"]

七. Dockerfile项目实例

  1. 第一个例子
    Dockerfile:
FROM centos
MAINTAINER bee<bee@niubi.com>

LABEL name="bee CentOS Image" \
build-date="20200210"

ENV WORKPATH /home/
WORKDIR $WORKPATH

RUN yum -y install net-tools
RUN yum -y install

构建并运行

# 仓库镜像名称(repository name)必须小写(bee/mycentos)
docker build -f MyDockerFile -t bee/mycentos:1.0 .
docker run -it --name test01 <container_id>

查看构建历史

docker history bee/mycentos7:1.0
docker history <image_id>
  1. 构建自己的Tomcat
    Dockerfile
FROM 0702/centos7
MAINTAINER bee<bee@163.com>

LABEL name="bee Tomcat Image" \
build-date="20200210"

COPY copyright.txt /home/copyright.txt
ADD server-jre-8u151-linux-x64.tar.gz /home/
ADD apache-tomcat-8.5.37.tar.gz /home/

ENV WORKPATH /home/apache-tomcat-8.5.37/
WORKDIR $WORKPATH

ENV JAVA_HOME /home/jdk1.8.0_151
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /home/apache-tomcat-8.5.37/
ENV CATALINA_BASE /home/apache-tomcat-8.5.37/
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin

EXPOSE 8080
CMD ["/home/apache-tomcat-8.5.37/bin/catalina.sh","run"]
  1. 构建容器卷

Dockerfile

FROM centos
VOLUME ["/home/v1","/home/v2"]

可以使用

docker inspect <container_id>

查看宿主机的对应目录(Mounts部分)。注意宿主机的对应目录是以随机字符串来命名的——以便于移植。

  1. ONBUILD的使用

当构建一个被继承的Dockerfile时运行的命令。父镜像在被子镜像继承后父镜像的ONBUID被触发。可以把ONBUID理解为一个触发器。

编写Dockerfile的时候,其他命令都是为了自身镜像服务的,只有ONBUILD是为了父镜像服务。

父镜像Dockerfile:

FROM centos
ONBUILD RUN yum -y install vim # 在父镜像中不安装,在子镜像中安装。

子镜像Dockerfile:

FROM parent

当构建子镜像的时候,父镜像的ONBUILD会触发,子镜像直接安装vim。

实际应用:一般是ONBUILD里执行的是一些父镜像暂时无法执行的东西,比如COPY,ADD,等命令。父镜像当做模板,仅仅提供基础支持,然后具体实现是子镜像操作(在docker build时)。