【Docker 学习十】DockerFile

体验一下

创建dockerfile01文件

先创建一个dockerfile文件,名字可以随便命令,但建议就用dockerfile

1
vi /home/dockerfile_01

通过这脚本可以生成镜像,
镜像就是一层一层的,脚本一个个命令,每个命令都是一层

编写dockerfile01

1
2
3
4
5
6
7
8
9
# 文件中的内容指令(都是大写)参数
# ubuntu镜像
FROM centos
# 匿名挂载,容器内部的路径
VOLUME ["volume01","volume02"]

CMD echo "---------end-------"
CMD /bin/bash
# 这里的每个命令都是镜像的一层

构建镜像:docker build命令:

用法

1
docker build -f Dockerfile文件所在位置 -t 镜像名称:tag【可以说自定义版本号】 当前路径

docker build命令

1
2
docker build -f /home/dockerfile_01 -t yulium/centos:1.0 .
# 略

命令行后面要加. 否则报错了
注意:这里的.表示在当前路径
实际上.指的是在指定上下文目录,docker build 命令会将该目录下的内容打包交给docker引擎以帮助构建镜像

启动自己写的容器

用法
1
docker run -it 镜像ID /bin/bash
运行容器
1
2
docker run -it yulium/centos:1.0 /bin/bash
# [root@70c4952c9d31 /]#

查看数据卷

1
2
[root@70c4952c9d31 /]#ls
# ...... volume01 volume02

说明:这个目录就是我们生成镜像的时候自动挂载了,数据卷目录

退出容器并查看Mounts

1
docker inspect 70c49
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[
{
"Type": "volume",
"Name": "6de9a85175c3b9ece98df6251de50d80d2cc8ca96cfd4105bc0ab3d8f5bcac41",
"Source": "/var/lib/docker/volumes/6de9a85175c3b9ece98df6251de50d80d2cc8ca96cfd4105bc0ab3d8f5bcac41/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "a419b8273b50f0e80de80de170dc372063ef6fa2be1e1ce18906bdb9150d97c2",
"Source": "/var/lib/docker/volumes/a419b8273b50f0e80de80de170dc372063ef6fa2be1e1ce18906bdb9150d97c2/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]

这个卷和宿主机都有一个同步的目录!匿名挂载一般都是放在宿主机里面docker目录路径下

测试一下:宿主机和容器的文件是否同步了

首先,在自己的容器volume01目录下创建文件

创建container.txt文件

1
[root@0e5c1292b3af /]# touch volume01/container.txt

查看宿主机volume01目录路径

1
2
3
# 退出容器之后,查看有没有同步了
# 如果不知道此路径,可以通过命令docker inspect 容器ID查看Mounts内容
cd /var/lib/docker/volumes/fb5c70144ee9a27bfbb67e589ae9e7f95e8a013bbea03ac887bda69395f23665/_data

切换路径后用ls查看

1
2
ls
# container.txt

说明,文件同步了
这种方式以后使用太多了,因为我们通常会构建自己的镜像!
假如构建镜像时候没有挂载卷,要手动镜像挂载-v 卷名:容器内路径

初识Dockerfile

命令脚本 -> 构建镜像 -> 启动容器 -> 查看
Dockerfile就是用来构建docker镜像的构建文件命令脚本,它就是一个命令脚本的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

基于Dockerfile构建镜像可以使用docker build命令。docker build命令中使用 -f 可以指定具体的dockerfile文件

默认情况下使用Dockerfile(D大写),docker build命令中不用指定就可以构建

构建步骤:

  1. 编写一个dockerfile文件
    1
    docker build -f /home/docker-test-volume/dockerfile1  -t yulium/centos .
  2. docker build 构建成为一个镜像
    1
    docker run -it --name docker01 yulium/centos
  3. docker run 运行镜像
  4. docker push发布镜像(DockerHub、阿里云镜像仓库)

很多官方镜像都像是基础包,很多功能都不具备,我们通常会自己搭建自己的镜像!

官方既然可以制作镜像,我们也一样可以做!

Dockerfile构建过程

基础知识

  1. 每个保留关键字(指令)都是必须大写字母

  2. 执行从上到下顺序执行

  3. #表示注释

  4. 每个指令都会创建提交一个新的镜像层,并提交

DockerFile面向开发的,我们以后要发布项目,做镜像,就需要编写dockefile文件这个文件十分简单

Docker镜像逐渐成为企业的交互标准,必须要掌握!

步骤:开发,部署, 运维… 缺一不可!

DockerFile:构建文件,定义了一切的步骤,源代码

DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品!

docker build -f /dockerfile文件路径 -t 名称标签

Docker容器:容器就是镜像运行起来提供服务器

dockerfile指令

以前的话我们就是使用别人的,现在我们知道了这些指令之后,我们可以来练习自己写一个镜像

参数 含义
FROM 基础镜像,一切从这里开始构建
MAINTAINER 镜像是谁写的,姓名+邮箱
LABEL 添加镜像的元数据,使用键值对的形式。
RUN 镜像构建的时候需要运行的命令
CMD 指定这个容器启动时运行的命令 例:CMD echo,只有最后一个会生效,可被替代(可以被覆盖)
ENTRYPOINT 指定这个容器启动的时候要运行的命令,可以追加命令(不可被覆盖)
EXPOSE 暴露的端口
ENV 构建的时候设置环境变量
ADD 将文件、目录或远程URL复制到镜像中
COPY 类似ADD,将我们的文件拷贝到镜像中
VOLUME 挂载的目录
WORKDIR 镜像的工作目录
USER 指定后续指令的用户上下文
ARG 定义在构建过程中传递给构建器的变量,可使用 “docker build” 命令设置
ONBUILD 当构建一个被继承的dockerfile的时候就会运行ONBUILD的指令。触发指令(了解即可)
STOPSIGNAL 设置发送给容器以退出的系统调用信号
HEALTHCHECK 定义周期性检查容器健康状态的命令
SHELL 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令

FROM

基础镜像,必须是可以下载下来的,定制的镜像都是基于FROM的镜像,

比如用于centos就是定制需要的基础镜像。
后续的操作都是基于centos镜像

1
2
3
4
5
6
格式:
FROM <image>
FROM <image>:<tag>
示例:
FROM nginx 默认版本号都是最新的
FROM nginx:1.25.1 指定版本号

MAINTAINER

用于指定镜像的维护者信息

1
2
3
4
5
格式:
MAINTAINER <name>
示例:
MAINTAINER yulium
MAINTAINER xxx@qq.com

LABEL

用于向镜像添加元数据metadata

指令用来给镜像添加一些元数据(metadata),

这些标签可以包含关于镜像的信息,如作者、版本、描述、维护者等

LABEL指令是可选

但它在构建镜像时为镜像添加了有用的描述性信息,有助于更好地管理和组织镜像库

1
2
3
4
5
6
7
8
以键值对的形式,格式:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例:
LABEL version="1.0",
LABEL "description"="This text"
LABEL "multi.label1"="value1" \
"multi.label2"="value2"
LABEL "other"="value3"

如果要查看镜像的labels,可以使用docker inspect命令

1
2
3
4
5
6
7
"Labels": {
"version": "1.0",
"description": "This text",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
},

使用LABEL指令有更广泛的用途,可以用来添加更多类型的元数据信息,
MAINTAINER指令仅限于指定维护者信息
因此,如果你正在编写新的Dockerfile,建议使用LABEL指令来添加元数据信息,而避免使用过时的MAINTAINER指令

RUN

指定在构建正在创建的映像,比如安装软件,下载文件等
包含两种模式Shellexec

1
2
3
4
格式:
RUN <command> (shell模式,这个是最常用的,需要记住)
示例:
RUN yum update && yum install python3

RUN指令在Dockerfile中可以出现多次,并且每个RUN指令都会创建一个新的镜像层
为了减少镜像的层数,可以将多个命令合并为一行
例如使用&&连接多个命令,这样在构建镜像时只会生成一个新的层

CMD

用于docker run执行docker镜像构建容器时使用
RUN不同,它不会为Image创建新层,而只是运行命令,每个Dockerfile/Image只能有一个CMD

  • 一个Dockerfile中只能包含一个CMD指令
  • 如果有多个CMD,则只有最后一个CMD指令会生效

    CMD [“a”,”b”] 格式:该格式是为ENTRYPOINT提供使用,此时ENTRYPOINT就必须使用exec格式,否则不生效

    1
    2
    3
    4
    5
    格式:
    CMD <command>
    示例:
    CMD /bin/bash -c ls
    CMD python ./app.py
命令

此命令会在容器启动且docker run没有指定其他命令时运行。下面是一个例子:

1
CMD echo "Hello world"

运行容器 docker run -it [image] 将输出:

1
Hello world

但当后面加上一个命令,比如 docker run -it [image] /bin/bashCMD 会被忽略掉,命令bash 将被执行:

1
root@10a32dc7d3d3:/#

类似于RUN指令,用于运行程序,但二者运行的时间点不同:

  • CMDdocker run时运行
  • RUN是在docker build构建镜像时运行的

作用:
为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束
CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖.

使用CMD指令可以为镜像定义一个默认的启动命令

当使用docker run命令启动容器时,如果没有指定其他命令,就会执行CMD中定义的命令

这使得在创建容器时无需手动指定要运行的命令,从而使容器的使用更加简便。

如果在docker run命令中指定了其他命令,则会覆盖CMD指令中的默认命令

例如,如果在启动容器时执行以下命令,就会覆盖CMD中定义的默认启动命令:

1
2
# dockerfile文件里面其中 CMD ["python", "app.py"]
docker run my_image python app_01.py

在上面的例子中,容器会运行python app_01.py命令,而不是默认的CMD指令中定义的命令

ENTRYPOINT

ENTRYPOINTDockerfile中的一个重要指令,用于配置容器启动时的默认执行命令。
它类似于CMD指令,但有一些关键的区别

ENTRYPOINT指令的格式与CMD指令类似,可以使用Shell格式数组格式,但在使用时,需要注意以下几点:

  • ENTRYPOINT指令的命令会在容器启动时始终执行,无论在docker run命令中是否指定了其他命令。它不会被覆盖,而是作为容器的主要执行命令
  • 如果在docker run命令中指定了其他命令,这些命令将作为ENTRYPOINT指令的参数进行传递.也就是说,ENTRYPOINT指令中的命令将成为执行时的前缀

注意:如果Dockerfile 中如果存在多个ENTRYPOINT 指令,仅最后一个生效

下面是一个使用ENTRYPOINT指令的简单示例:

1
2
3
FROM centos:latest

ENTRYPOINT ["echo", "Hello"]

如果我们构建该镜像并运行容器,不提供其他参数,那么容器启动后将输出"Hello"

1
2
3
$ docker build -t my_image .
$ docker run my_image
Hello

如果我们在运行容器时提供了其他参数,那么这些参数将作为ENTRYPOINT指令中命令的参数:

1
2
$ docker run my_image "World"
Hello World

将Dockerfile修改为:

1
2
ENTRYPOINT ["/bin/echo", "Hello"]  
CMD ["world"]

当容器通过docker run -it [image] 启动时,输出为:

1
Hello world

而如果通过docker run -it [image] yuliums 启动,输出依旧为:

1
Hello yuliums

ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器启动时动态替换掉。
ENTRYPOINTCMD 可以联合使用,ENTRYPOINT 设置执行的命令,CMD传递参数

DockerfileRUNCMDENTRYPOINT都能够用于执行命令,下面是三者的主要用途:

  • RUN命令执行命令并创建新的镜像层,通常用于安装软件包
  • CMD命令设置容器启动后默认执行的命令及其参数,但CMD设置的命令能够被docker run命令后面的命令行参数替换
  • ENTRYPOINT配置容器启动时的执行命令(不会被忽略,一定会被执行,即使运行 docker run时指定了其他命令)

实际应用中,可以使用ENTRYPOINT指令来定义一个可执行的程序或脚本,
然后在容器启动时运行这个程序,并将Docker容器作为可执行应用来使用.
这样可以确保容器在运行时的行为是可预期的
而且可以将容器配置和执行逻辑完全封装在镜像内部,使得容器的使用更加方便和易于管理

EXPOSE

用于声明容器在运行时监听的网络端口
作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射
  • 在运行时使用随机端口映射时,也就是docker run -p时,会自动随机映射EXPOSE的端口
  • 可以是一个或者多个端口,也可以指定多个EXPOSE
    1
    2
    3
    4
    格式:
    EXPOSE <端口1> [<端口2>/<protocol>...]
    示例:
    EXPOSE 80
    上面的例子中,我们声明了容器将监听80端口,而[<port>/<protocol>…]则表示可选的协议类型,例如TCP或UDP
    但是需要注意的是,EXPOSE并不会实际上打开该端口,也不会进行端口映射,
    在使用docker run命令启动容器时,如果需要通过主机访问容器的80端口,还需要使用-p选项来进行端口映射。
    例子:
    1
    $ docker run -p 8080:80 my_image

    上述命令将容器的80端口映射到主机的8080端口,这样就可以通过访问主机的8080端口来访问容器的服务

ENV

用于设置环境变量

它允许在镜像构建过程中设置环境变量,这些环境变量将在容器运行时可用

1
2
3
4
5
格式:
ENV key=value 其中key是环境变量的名称,value是环境变量的值
ENV key value
示例:
ENV MY_NAME John Doe

实例:可以使用多个ENV指令来设置多个环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM centos

# 设置环境变量
ENV MY_NAME John Doe
ENV APP_HOME /app

# 创建目录并设置工作目录
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

# 复制应用程序到镜像中
COPY . .

# 在运行时输出环境变量
CMD echo "Hello, $MY_NAME"

我们使用了两个ENV指令来设置两个环境变量:MY_NAMEAPP_HOME
在镜像构建过程中,这些环境变量会被设置为指定的值
然后,在容器启动时,CMD指令中的命令将使用$MY_NAME环境变量的值输出问候语
在运行容器时,你可以通过docker run命令的-e选项来覆盖环境变量的值

1
$ docker run -e MY_NAME="Alice" my_image

上述命令将覆盖默认的MY_NAME环境变量值,容器将输出"Hello, Alice"

ADD

用于将文件、目录或远程URL复制到镜像中

它类似于COPY指令,但在功能上更强大

1
2
3
4
5
格式:
ADD source destination source是要复制的源文件、目录或URL destination是复制后的目标路径

示例:
ADD app.py /app/

除了复制文件和目录,ADD指令还支持自动解压缩
如果source是一个压缩文件(例如.tar.tar.gz.tgz.zip等)
那么ADD指令会自动解压缩该文件到destination指定的目录

实例:
复制本地文件到镜像中

1
ADD app.py /app/

复制本地目录到镜像中

1
ADD src/ /app/

从远程URL下载文件并复制到镜像中

1
ADD https://example.com/file.tar.gz /tmp/

解压缩压缩文件并复制到镜像中

1
ADD app.tar.gz /app/

COPY

COPY用于将本地文件或目录复制到镜像中
不支持自动解压缩功能,与ADD指令相比,功能更简单明确

1
2
3
4
5
格式:
COPY source destination source是要复制的源文件、目录 destination是复制后的目标路径

示例:
COPY app.py /app/

复制本地文件到镜像中

1
COPY app.py /app/

复制本地目录到镜像中

1
ADD src/ /app/

COPY指令会将本地文件或目录复制到镜像中的指定位置

在构建镜像时,Docker将会在镜像的文件系统层中添加复制的文件或目录

这使得镜像的构建过程更加明确,不会产生自动解压缩的不确定行为

相对于ADD指令COPY指令更为推荐,特别是在只需要简单复制本地文件或目录的情况下

COPY指令功能简单,不容易引起不必要的意外行为

对于大多数复制文件的场景,建议使用COPY指令

VOLUME

用于声明容器中的挂载点(数据卷)

在启动容器docker run的时候,我们可以通过-v参数修改挂载点。

可以在一个Dockerfile中使用多个VOLUME指令来声明多个挂载点

1
2
3
4
5
格式:
VOLUME ["<路径1>", "<路径2>" ...]
VOLUME ["<路径1>"] 其中<路径1>是挂载点的路径
示例:
VOLUME ["/app/data", "/app/logs"] 声明两个挂载点

在运行容器时,可以使用-v选项或--mount选项来将主机的目录或数据卷映射到容器的挂载点。
例如:

1
$ docker run -v /host/data:/app/data -v /host/logs:/app/logs my_image

上述命令将主机的/host/data/host/logs目录分别映射到容器中的/app/data/app/logs挂载点,实现了主机和容器之间的数据共享

WORKDIR

用于设置工作目录,也称为当前工作目录

在容器启动时,进程的当前工作目录将被设置为WORKDIR指令所指定的目录必须是提前创建好的

1
2
3
4
格式:
WORKDIR <工作目录路径>
示例:
WORKDIR /app

当容器启动时,进程的当前工作目录将自动设置为/app
这样在执行CMD指令时,不需要使用绝对路径来运行python app.py

USER

用于指定在容器中运行镜像时要使用的普通用户

这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)

1
2
3
4
5
格式:
USER <用户名>[:<用户组>]
示例:
USER myuser
USER user:group

默认情况下,Docker容器在启动时以root用户身份运行,这意味着容器内的进程具有最高权限.

然而,为了加强安全性,避免潜在的安全风险,最好以非特权用户的身份运行容器中的应用程序
实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
FROM centos

# 创建一个新用户并切换到该用户
RUN useradd -ms /bin/bash myuser
USER myuser

# 设置工作目录
WORKDIR /app

# 复制应用程序到工作目录
COPY . .

# 设置环境变量
ENV APP_ENV production

# 容器启动时运行的命令
CMD ["python", "app.py"]

在上面的例子中,我们使用useradd命令创建了一个名为myuser的新用户,并使用-ms /bin/bash选项指定了创建用户时使用的shell

然后,通过USER指令切换到了myuser用户

这样,在容器运行时,进程将以myuser用户的身份运行,而不是以root用户身份。

ARG

无论何种编程语言或脚本中,都不可避免的会应用到变量
用于定义变量,仅在建造当前镜像的过程中包括CMD和ENTRYPOINT有效,而要是镜像被创建了和运行容器之后,是作用失效了

语法
1
2
3
4
5
格式:
ARG <name>[=<default value>]
示例:
ARG user1
ARG user2=hello

如果你在Dockerfile中使用了ARG但并未给定初始值,则在运行docker build(编译)的时候未指定该ARG变量,则会失败

ARG指令具有默认值,并且在构建时没有传递值,则构建器将使用默认值

虽然其在容器启动后不再生效,但是不建议使用构建时变量来传递诸如github密钥用户凭据机密信息
因为使用docker history命令,镜像的任何用户都可以看到构建时的变量值。

ARG 变量应用

可以使用ARGENV指令为RUN指令指定参数。
使用ENV指令定义的环境变量会覆盖ARG指令定义的同名变量

1
2
3
4
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=v1.0.0
RUN echo $CONT_IMG_VER

实战测试

创建一个自己的centos

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
root@localhost:~# cd /homet
root@localhost:/home# mkdir dockerfile
root@localhost:/home# cd dockerfile/
root@localhost:/home/dockerfile# vim mydockerfile
# 编写mydockerfile文件
root@localhost:/home/dockerfile# cat mydockerfile
# 基于centos镜像创建
FROM centos
# 镜像是谁写的,名字+邮箱
MAINTAINER yulium<123@163.com>
# 设置环境路径
ENV MYPATH /usr/loacl
# 切换到当前工作目录
WORKDIR $MYPATH
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令
RUN yum -y install net-tools

#暴露80端口
EXPOSE 80

CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash
root@localhost:/home/dockerfile#

通过这个文件构建镜像

1
docker build -f mydockerfile(dockerfile 文件路径) -t 镜像名:[tag]
1
root@localhost:/home/dockerfile# docker build -f mydockerfile -t yulium/centos:0.1 .

如果报错信息

1
dokcer给Centos配置时出现ERROR: failed to solve: process "/bin/sh -c yum -y install vim" did not complete s

原因:是因为Docker默认拉取的是centos最新版,此时需要我们指定一下拉取的版本就比如:

1
docker pull docker pull centos:7.9.2009

解决问题:
在我们的Dockerfile文件中编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#基于centos镜像创建
FROM centos:7
#镜像是谁写的,名字+邮箱
MAINTAINER yulium<123@163.com>

# 设置环境路径
ENV MYPATH /usr/loacl
# 切换到当前工作目录
WORKDIR $MYPATH

#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令
RUN yum -y install net-tools

#暴露80端口
EXPOSE 80

CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash

查看镜像

1
2
3
4
docker images
# REPOSITORY TAG IMAGE ID CREATED SIZE
# yulium/centos latest 3bc65dff503e 4 minutes ago 668MB
# centos latest 5d0da3dc9764 23 months ago 231MB

运行容器

1
2
docker run -it 3bc65dff503e
# [root@6d868b72593b local]#
1
2
[root@6d868b72593b local]# pwd
# #/usr/local
1
[root@6d868b72593b local]# ifconfig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 10 bytes 796 (796.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

这个原生centos和上面自己的镜像对比:进去之后是根目录,没有ifconfig、vim

1
2
3
4
5
6
7
8
9
10
[root@6d868b72593b local]# exit
exit
root@localhost:/home/dockerfile# docker run -it 5d0da3dc9764
[root@3db43b195f6c /]# pwd
/
[root@3db43b195f6c /]# ifconfig
bash: ifconfig: command not found
[root@3db43b195f6c /]# vim
bash: vim: command not found
[root@3db43b195f6c /]#

列出本地进行的变更历史

1
docker history 3bc
1
2
3
4
5
6
7
8
9
10
11
12
13
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
3bc65dff503e 15 minutes ago CMD ["/bin/sh" "-c" "/bin/bash"] 0B buildkit.dockerfile.v0
<missing> 15 minutes ago CMD ["/bin/sh" "-c" "echo \"----end----\""] 0B buildkit.dockerfile.v0
<missing> 15 minutes ago CMD ["/bin/sh" "-c" "echo $MYPATH"] 0B buildkit.dockerfile.v0
<missing> 15 minutes ago EXPOSE map[80/tcp:{}] 0B buildkit.dockerfile.v0
<missing> 15 minutes ago RUN /bin/sh -c yum -y install net-tools # bu… 190MB buildkit.dockerfile.v0
<missing> 15 minutes ago RUN /bin/sh -c yum -y install vim # buildkit 274MB buildkit.dockerfile.v0
<missing> 17 minutes ago WORKDIR /usr/loacl 0B buildkit.dockerfile.v0
<missing> 17 minutes ago ENV MYPATH=/usr/loacl 0B buildkit.dockerfile.v0
<missing> 17 minutes ago MAINTAINER yulium<123@163.com> 0B buildkit.dockerfile.v0
<missing> 23 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 23 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 23 months ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB