【云原生Docker篇】镜像的制作和管理

1,129 阅读14分钟

一、Docker镜像

1. 镜像的概念

镜像是创建容器的基础。

镜像是一个只读的模板文件,里面包含运行容器中的应用程序所有需要的所有内容(应用程序文件、配置文件、运行库文件、依赖包等)。

2. 镜像结构的分层

image-20220601002003156.png

Docker 镜像由多个只读层组成,每个层都包含了文件系统的一部分。

这些层按照从底向上的顺序依次叠加,形成一个完整的镜像。

镜像的最底层是一个基础镜像(Base Image),上面叠加了一系列更高层的镜像,每个层都是前一个层的增量变化。

在容器启动时,Docker 引擎会将这些层通过联合文件系统合并成一个容器文件系统。

在容器运行过程中,Docker 引擎将修改操作写入一个可写层(Writeable Layer),该层仅保存容器运行时的状态和数据。

这种分层和联合文件系统的设计使得镜像的创建和传播非常高效,节省了存储空间和下载时间。

二、Docker镜像的创建

创建镜像有三种方法,分别为基于已有镜像创建、基于本地模板创建以及基于Dockerfile创建。

1. 基于现有镜像创建

基于已有镜像创建主要使用 docker commit 命令。

本质上就是把一个容器里面运行的程序和该程序的运行环境打包,生成新的镜像。

#基本格式 
docker commit [选项] 容器ID/名称 仓库名称:[标签] 

##常用选项## 
-m:说明信息; 
-a:作者信息; 
-p:生成过程中停止容器的运行。

创建思路

1)先用现有镜像创建启动容器 ,使用 docker run命令;

2)再进入容器进行内容更新 ,使用docker exec命令;

3)最后提交成新的镜像 ,使用 docker commit命令。

docker export 将容器导出

创建一个容器,进入容器并创建文件写入数据,再使用docker export导出容器成压缩包,可以迁移,或者直接导入使用,然后通过docker import导入成镜像。

[root@localhost ~]# docker run -itd --name c1 centos:7 bash          #创建一个容器c1 
7d8c99d87c3c76df99c4793402cf0dc64c5aadd430ba694ed79c8bd807fb8333
[root@localhost ~]# docker exec -it c1 bash                          #进入容器c1  
[root@7d8c99d87c3c /]# mkdir -p /var/www/html                        #创建文件
[root@7d8c99d87c3c /]# cd /var/www/html/                             
[root@7d8c99d87c3c html]# echo "this is a test file" > index.html    #写入数据
[root@7d8c99d87c3c html]# ls
index.html
[root@7d8c99d87c3c html]# exit
exit
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE      COMMAND   CREATED         STATUS                     PORTS     NAMES
7d8c99d87c3c   centos:7   "bash"    3 minutes ago   Up 3 minutes                         c1
55938e509320   centos:7   "bash"    4 minutes ago   Exited (0) 3 minutes ago             cool_ptolemy
[root@localhost ~]# docker export -o centos7.tar 7d8c99d87c3c        #使用docker export导出容器成压缩包
[root@localhost ~]# ls
anaconda-ks.cfg  centos7.tar  initial-setup-ks.cfg  公共  模板  视频  图片  文档  下载  音乐  桌面

image.png

docker commit 将容器提交为新的镜像

使用前面的容器,将修改后的容器提交为新的镜像,需要使用该容器的ID号创建新镜像

格式docker commit -m 说明信息 -a 作者信息 -p 容器ID 生成新的镜像名称

选项

选项作用
-m指定说明信息
-a作者信息
-p生成过程停止原容器运行
[root@localhost ~]# docker commit -m "test" -a "lhey" -p 7d8c99d87c3c centos7:test
sha256:5c385c8e31a3b9aaa1b1ce6e4bda3cc1a58ad377fceb8d5ecb13d919667d0362
[root@localhost ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
centos7      test      5c385c8e31a3   15 seconds ago   204MB
centos       7         eeb6ee3f44bd   2 years ago      204MB
[root@localhost ~]# docker run -id centos7:test
a5fd1fadafe32c832300313410f6af2da78ea3ad9e0e6baeafaa341e377f84a9
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND   CREATED          STATUS                      PORTS     NAMES
a5fd1fadafe3   centos7:test   "bash"    15 seconds ago   Up 13 seconds                         naughty_gauss
7d8c99d87c3c   centos:7       "bash"    26 minutes ago   Up 26 minutes                         c1
55938e509320   centos:7       "bash"    27 minutes ago   Exited (0) 27 minutes ago             cool_ptolemy

image.png

2. 基于本地模板创建

通过导入操作系统模板文件可以生成镜像,模板可以从OPENVZ 开源项目下载,下载地址为:Open source container-based virtualization for Linux. (o#penvz.org)

openvz.org/:Download/template/precreated

#模板里面就是使用docker export 命令导出的容器文件

#下载模板
wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz

#导入为镜像,两种方法
cat debian-7.0-x86-minimal.tar.gz | docker import - debian:test  #方法一
  
docker import debian-7.0-x86-minimal.tar.gz -- debian:test  #方法二

#查看镜像
 docker images

 #使用导入的镜像创建容器
 docker run -itd debian:test bash
 docker ps -a

3. 基于Dockerfile创建

联合文件系统(UnionFS )

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。AUFS、overlayFS 及Devicemapper 都是一种UnionFS 。

Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

我们下载的时候看到的一层层的就是联合文件系统。

image.png

镜像加载原理

Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统就是UnionFS。

bootfs主要包含bootloader和kernel,bootloader主 要是引导加载kernel,Linux刚启动时会加载bootfs文件系统。

在Docker镜像的最底层是bootfs,这一层 与我们典型的Linux/Unix系统是一样的, 包含boot加载器和内核。当boot加载完成之 后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs,在bootfs之 上。包含的就是典型Linux系统中的/dev、/proc、/bin、/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu, Centos等。

  • bootfs就是内核引导器(引导加载内核)和内核。
  • rootfs是n多个基础镜像(提供基础操作环境)和应用镜像叠加在一起的只读层。
  • 运行的容器实例会在rootfs之上添加一个可读可写层。

三、Dockerfile

DockerFile 是一种被Docker程序解释执行的脚本,由一条条的命令组成的,每条命令对应linux下面的一条命令,Docker程序将这些DockerFile指令再翻译成真正的linux命令,其有自己的书写方式和支持的命令,Docker程序读取DockerFile并根据指令生成Docker镜像,相比手动制作镜像的方式,DockerFile更能直观的展示镜像是怎么产生的,有了DockerFile,当后期有额外的需求时,只要在之前的DockerFile添加或者修改响应的命令即可重新生成新的Docker镜像,避免了重复手动制作镜像的麻烦,类似与shell脚本一样,可以方便高效的制作镜像Docker守护程序 Dockerfile 逐一运行指令,如有必要,将每个指令的结果提交到新镜像,然后最终输出新镜像的ID。Docker守护程序将自动清理之前发送的上下文。

注意:每条指令都是独立运行的,并会导致创建新镜像,比如 RUN cd /tmp 对下一条指令不会有任何影响。

四、Dockerfile文件格式

Dockerfile 是一个有特定语法格式的文本文件

Dockerfile文件说明:

  • 每一行以Dockerfile的指令开头,指令不区分大小写,但是惯例使用大写
  • 使用 # 开始作为注释
  • 每一行只支持一条指令,每条指令可以携带多个参数
  • 指令按文件的顺序从上至下进行执行
  • 每个指令的执行会生成一个新的镜像层,为了减少分层和镜像大小,尽可能将多条指令合并成一条指令
  • 制作镜像一般可能需要反复多次,每次执行dockfile都按顺序执行,从头开始,已经执行过的指令已经缓存,不需要再执行,如果后续有一行新的指令没执行过,其往后的指令将会重新执行,所以为加速镜像制作,将最常变化的内容放下dockerfile的文件的后面

五、构建镜像docker build命令

docker build命令使用Dockerfile文件创建镜像

命令格式

docker build [OPTIONS] PATH | URL | -

//PATH | URL | -  可以使是本地路径,也可以是URL路径。若设置为 - ,则从标准输入获取Dockerfile的内容
命令选项含义
-f,--file stringDockerfile文件名,默认为 PATH/Dockerfile
--force-rm总是删除中间层容器,创建镜像失败时,删除临时容器
--no-cache不使用之前构建中创建的缓存
-q, --quiet=false不显示Dockerfile的RUN运行的输出结果
--rm=true创建镜像成功时,删除临时容器
-t,--tag list设置注册名称、镜像名称、标签。格式为 <注册名称>/<镜像名称>:<标签>(标签默认为latest)

六、Dockerfile的常见命令

命令作用
FROM image_name:tag声明基础镜像
MAINTAINER user_name声明镜像的作者
ENV key value设置环境变量 (可以写多条)
RUN command编译镜像时运行的脚本(可以写多条)
CMD设置容器的启动命令
ENTRYPOINT设置容器的入口程序
ADD source_dir/file dest_dir/file将宿主机的文件复制到镜像内,如果是一个压缩文件,将会在复制后自动解压。支持URL路径下载源文件,但下载方式不能自动解压。
COPY source_dir/file dest_dir/file和ADD相似,将宿主机的文件复制到镜像内,但是如果有压缩文件并不能解压。不支持URL路径下载。
WORKDIR path_dir设置工作目录
ARG设置编译镜像时加入的参数
VOLUMN设置容器的挂载卷

1. FROM —— 指定基础镜像

定制镜像,需要先有一个基础镜像,在这个基础镜像上进行定制。

FROM 就是指定基础镜像,此指令通常必需放在Dockerfile文件第一个非注释行。后续的指令都是运行于此基准镜像所提供的运行环境。

基础镜像可以是任何可用镜像文件,默认情况下,docker build会在docker主机上查找指定的镜像文件,在其不存在时,则会从Docker Hub Registry上拉取所需的镜像文件。如果找不到指定的镜像文件,docker build会返回一个错误信息。

如何选择合适的镜像呢?

对于不同的软件官方都提供了相关的docker镜像,比如: nginx、redis、mysql、httpd、tomcat等服务类的镜像,也有操作系统类,如: centos、ubuntu、debian等。建议使用官方镜像,比较安全。

格式:

FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]


//说明:  
--platform 指定镜像的平台,比如: linux/amd64, linux/arm64, or windows/amd64
tag 和 digest是可选项,如果不指定,默认为latest

示例:

[root@localhost ~]# mkdir /data/dockerfile/system/centos/centos7 -p
[root@localhost ~]# cd /data/dockerfile/system/centos/centos7/
[root@localhost centos7]# vim Dockerfile
FROM  centos:7.9.2009

image.png

2. LABEL —— 指定镜像元数据

LABEL:说明信息,可以指定镜像元数据,如: 镜像作者等。docker inspect 命令可以查看LABEL信息。

一个镜像可以有多个label,还可以写在一行中,即多标签写法,可以减少镜像的的大小。 一个镜像可以有多个label,还可以写在一行中,即多标签写法,可以减少镜像的的大小

//一行格式
LABEL multi.label1="value1" multi.label2="value2" other="value3"

//多行格式
LABEL multi.label1="value1" \
      multi.label2="value2" \
      other="value3"

示例

[root@localhost centos7]#  vim Dockerfile
FROM  centos:7.9.2009
LABEL author="lhey" \      //作者信息
      version="1.0"  //版本信息

3. RUN —— 执行shell命令

RUN指令用来在构建镜像阶段,需要执行 FROM 指定镜像所支持的Shell命令。通常各种基础镜像一般都支持丰富的shell命令。

注意: 每个 RUN 都是独立运行的,和前一个 RUN 无关。RUN 可以写多个,每一个 RUN 指令都会建立一个镜像层,所以尽可能合并成一条指令,比如将多个shell命令通过 && 连接一起成为一条指令。

格式

//shell 格式:相当于 /bin/sh -c <命令> 此种形式支持环境变量
RUN <命令> 

//exec 格式:此种形式不支持环境变量,注意!是双引号,不能是单引号
RUN ["可执行文件", "参数1", "参数2"]
//exec格式可以指定其它shell
RUN ["/bin/bash","-c","echo hello lao wang"]
[root@localhost centos7]# vim Dockerfile

FROM  centos:7.9.2009
LABEL author="lhey" \
      version="1.0"
RUN   cd /opt && touch lhey

[root@localhost centos7]# docker build -t centos:7.9 . 
#"docker build"命令使用Dockerfile文件创建镜像 
#"-t"指定构建的镜像的名称和标签 
#"centos"是镜像的名称 
#"7.9"是标签 
#"."是当前目录

[root@localhost centos7]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
centos       7.9       0af585d91249   About a minute ago   204MB
[root@localhost centos7]# docker run -it --name c1 centos:7.9 bash
[root@31ee3ce2c9c1 /]# ls
anaconda-post.log  bin  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@31ee3ce2c9c1 /]# cd /opt
[root@31ee3ce2c9c1 opt]# ls
lhey

image.png

image.png

image.png

4. ENV —— 设置环境变量

ENV 可以定义环境变量和值,会被后续指令(如:ENV,ADD,COPY,RUN等)通过$KEY${KEY}进行引用,并在容器运行时保持。

格式

//变量赋值格式1:此格式只能对一个key赋值,<key>之后的所有内容均会被视作其<value>的组成部分
ENV <key> <value>   
//变量赋值格式2:此格式可以支持多个key赋值,定义多个变量,推荐使用,可以减少镜像层
ENV <key1>=<value1>  <key2>=<value2>  <key3>=<value3> ...
 
//引用变量
RUN $key .....

5. COPY —— 复制文本

复制本地宿主机的文件到容器中

格式

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] #路径中有空白字符时,建议使用此格式

说明

  • 可以是多个,可以使用通配符,通配符规则满足Go的filepath.Match

  • 必须是build上下文中的路径(为 Dockerfile 所在目录的相对路径),不能是其父目录中的文件

    • 只能复制与 Dockerfile 脚本文件同级的文件或者子目录中的文件
  • 如果是目录,则其内部文件或子目录会被递归复制,但目录自身不会被复制

  • 如果指定了多个,或在中使用了通配符,则目标必须是一个目录,且必须以 / 结尾

    • 不加 / 类似于 改名 , 虽然不报错但是 效果不一样
  • 可以是绝对路径或者是 WORKDIR 指定的相对路径

  • 使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等

  • 如果事先不存在,它将会被自动创建,这包括其父目录路径,即递归创建目录

[root@localhost centos7]# vim Dockerfile

FROM  centos:7.9.2009
LABEL author="lhey" \
      version="1.0"
RUN   cd /opt && touch lhey
COPY  index.html /copyfile/
#复制宿主机的index.html文件到容器的copytest目录下;copytest目录事先不存在,会被自动创建

[root@localhost centos7]# docker build -t centos7:v2 .   //构建镜像

[root@localhost centos7]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
centos7      v2        51de589b3fe1   About a minute ago   204MB
[root@localhost centos7]# docker run -it centos7:v2 bash
[root@9ff19af5ae33 /]# ls
anaconda-post.log  bin  copyfile  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@9ff19af5ae33 /]# cd copyfile/
[root@9ff19af5ae33 copyfile]# ls
index.html

image.png

image.png

修改权限

[root@localhost centos7]# vim Dockerfile

FROM  centos:7.9.2009
LABEL author="lhey" \
      version="1.0"
RUN   cd /opt && touch lhey
COPY  --chown=lhey:lhey index.html /copyfile/
#--chown 选项添加权限

[root@localhost centos7]# docker build -t centos7:v2 .   //构建镜像

[root@localhost centos7]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED              SIZE
centos7      v2        51de589b3fe1   About a minute ago   204MB
[root@localhost centos7]# docker run -it centos7:v2 bash
[root@9ff19af5ae33 /]# ls
anaconda-post.log  bin  copyfile  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@9ff19af5ae33 /]# cd copyfile/
[root@9ff19af5ae33 copyfile]# ls
index.html

image.png

6. ADD —— 复制和解压文件

该命令可认为是增强版的COPY,不仅支持COPY,还支持自动解压。

格式:

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

说明:

  • 可以是Dockerfile所在目录的一个相对路径;也可是一个 URL;还可是一个 tar 文件(自动解压)
  • 可以是绝对路径或者是 WORKDIR 指定的相对路径
  • 如果是目录,只复制目录中的内容,而非目录本身
  • 如果是一个 URL,下载后的文件权限自动设置为 600
  • 如果为URL且不以/结尾,则指定的文件将被下载并直接被创建为,如果以 / 结尾,则文件名URL指定的文件将被直接下载并保存为/< filename>
  • 如果是一个本地文件系统上的打包文件,如: gz, bz2 ,xz ,它将被解包,其行为类似于"tar -x"命令,但是通过URL获取到的tar文件将不会自动展开
  • 如果有多个,或其间接或直接使用了通配符,则必须是一个以/结尾的目录路径;如果不以/结尾,则其被视作一个普通文件的内容将被直接写入到容器中

示例

[root@localhost centos7]# ls
Dockerfile  index.html  lhey.tar.gz

[root@localhost centos7]# vim Dockerfile

FROM  centos:7.9.2009
LABEL author="lhey" \
      version="1.0"
RUN   rm -rf /etc/yum.repos.d
COPY  qh.repo /etc/yum.repos.d/
ADD   lhey.tar.gz /opt/

[root@localhost centos7]# docker build -t c7:v1 .

[root@localhost centos7]# docker run -it c7:v1 
[root@9eb8ae8cc0c7 /]# ls
anaconda-post.log  bin  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@9eb8ae8cc0c7 /]# cd /opt
[root@9eb8ae8cc0c7 opt]# ls
index.html

image.png

image.png

image.png

image.png

7. CMD —— 容器启动命令

一个容器中需要持续运行的进程一般只有一个,CMD 用来指定启动容器时默认执行的一个命令,且其运行结束后,容器也会停止,所以一般CMD 指定的命令为持续运行且为前台命令。

格式:

//使用 exec 执行,推荐方式,第一个参数必须是命令的全路径,此种形式不支持环境变量
CMD ["executable","param1","param2"] 

//在 /bin/sh 中执行,提供给需要交互的应用;此种形式支持环境变量
CMD command param1 param2 

//提供给 ENTRYPOINT 命令的默认参数
CMD ["param1","param2"]

说明:

  • 如果docker run没有指定任何的执行命令或者dockerfile里面也没有ENTRYPOINT,那么开启容器时就会使用执行CMD指定的默认的命令
  • 前面介绍过的 RUN 命令是在构建镜像进执行的命令,注意二者的不同之处
  • 每个 Dockerfile 只能有一条 CMD 命令。如指定了多条,只有最后一条被执行
  • 如果用户启动容器时用 docker run xxx 指定运行的命令,则会覆盖 CMD 指定的命令

示例:

CMD tail -f /etc/hosts

CMD  ["tail","-f","/etc/hosts"]

image.png

image.png

8. ENTRYPOINT —— 入口点

功能类似于CMD,配置容器启动后执行的命令及参数

格式

// 使用 exec 执行
ENTRYPOINT ["executable", "param1", "param2"]

// shell中执行
ENTRYPOINT command param1 param2

说明

  • ENTRYPOINT 不能被 docker run 提供的参数覆盖,而是追加,即如果docker run 命令有参数,那么参数全部都会作为ENTRYPOINT的参数
  • 如果docker run 后面没有额外参数,但是dockerfile中的CMD里有(即上面CMD的第三种用法),即Dockerfile中即有CMD也有ENTRYPOINT,那么CMD的全部内容会作为ENTRYPOINT的参数
  • 如果docker run 后面有额外参数,同时Dockerfile中即有CMD也有ENTRYPOINT,那么docker run后面的参数覆盖掉CMD参数内容,最终作为ENTRYPOINT的参数
  • 可以通过docker run --entrypoint string 参数在运行时替换,注意string不要加空格
  • 使用CMD要在运行时重新写命令本身,然后在后面才能追加运行参数,ENTRYPOINT则可以运行时无需重写命令就可以直接接受新参数
  • 每个 Dockerfile 中只能有一个 ENTRYPOINT,当指定多个时,只有最后一个生效

示例:

CMD   ["-g","daemon off;"]
ENTRYPOINT   ["/apps/nginx/sbin/nginx"]
//CMD和ENTRYPOINT一起出现,CMD将作为ENTRYPOINT后面的参数;执行的是 nginx -g daemon off

9. ARG —— 构建参数

ARG指令在 build 阶段指定变量,和ENV不同的是,容器运行时不会存在这些环境变量

格式:

ARG <name>[=<default value>]

10. VOLUME —— 匿名卷

在容器中创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保持的数据等,一般会将宿主机上的目录挂载至 VOLUME 指令指定的容器目录。即使容器后期被删除,此宿主机的目录仍会保留,从而实现容器数据的持久保存。

宿主机目录为/var/lib/docker/volumes/<volume_id>/_data

格式

vOLUME <容器内路径>
VOLUME ["<容器内路径1>", "<容器内路径2>"...]

说明

  • Dockerfile中的VOLUME实现的是匿名数据卷,无法指定宿主机路径和容器目录的挂载关系
  • 通过docker rm -fv <容器ID> 可以删除容器的同时删除VOLUME指定的卷

示例

[root@localhost centos7]# vim Dockerfile

FROM  centos:7.9.2009
LABEL author="lhey" \
      version="1.0"
VOLUME ["data1","data2"]
#在容器创建 /data1 ,/data2 两个挂载点


[root@localhost centos7]# docker build -t c7:v3 .

[root@localhost centos7]# docker run -it c7:v3
[root@7de1a2b391e1 /]# ls
anaconda-post.log  bin  data1  data2  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@7de1a2b391e1 /]# cd /data1
[root@7de1a2b391e1 data1]# touch lhey
[root@7de1a2b391e1 data1]# ls
lhey

[root@localhost centos7]# docker inspect 7de1a2b391e1     #查看详细信息

[root@localhost centos7]# cd /var/lib/docker/volumes/
[root@localhost volumes]# ls
2772f10d132b43021dc0b3a00538c79f32934fd5fac3d3434d40d991e1033469  bec828a8d3de58a38da1a498b6fb40a2689875ed1de78b72434f76b8a6fd1e3e
backingFsBlockDev                                                 metadata.db
[root@localhost volumes]# cd 2772f10d132b43021dc0b3a00538c79f32934fd5fac3d3434d40d991e1033469/_data/
[root@localhost _data]# ls
lhey             #可以看到在容器中建立的文件,同样显示在了真机中

[root@localhost _data]# docker rm -fv 7de1a2b391e1    #删除容器的同时删除VOLUME指定的卷
7de1a2b391e1
[root@localhost _data]# ls
[root@localhost _data]# cd /var/lib/docker/volumes/2772f10d132b43021dc0b3a00538c79f32934fd5fac3d3434d40d991e1033469
-bash: cd: /var/lib/docker/volumes/2772f10d132b43021dc0b3a00538c79f32934fd5fac3d3434d40d991e1033469: 没有那个文件或目录

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

11. EXPOSE —— 暴露端口

指定服务端的容器需要对外暴露(监听)的端口号,以实现容器与外部通信。EXPOSE 仅仅是声明容器打算使用什么端口而已,并不会真正暴露端口,即不会自动在宿主进行端口映射因此,在启动容器时需要通过 -P-p ,Docker 主机才会真正分配一个端口转发到指定暴露的端口才可使用。

格式

EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>] ..]
    
#说明:<protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议

注意:即使Dockerfile没有 EXPOSE 端口指令,也可以通过docker run -p临时暴露容器内程序真正监听的端口,所以 EXPOSE 相当于指定默认的暴露端口,可以通过docker run -P 进行真正暴露。

示例

EXPOSE  80  443

12. WORKDIR —— 指定工作目录

为后续的 RUN、CMD、ENTRYPOINT 指令配置工作目录,当容器运行后,进入容器内WORKDIR指定的默认目录。

WORKDIR 指定工作目录(或称当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会自行创建。

格式:

WORKDIR /path/to/workdir

例:WORKDIR /app

七、总结

Dockerfile 指令作用
FROM iamge_name:tag声明基础镜像
MAINTAINER user_name声明镜像的作者
LABEL代替了MAINTAINER
ENV key value设置环境变量(可以写多条)
RUN command编译镜像时运行的脚本(可以写多条)
CMD设置容器的启动命令
ENTRYPOINT设置容器的入口程序
ADD source_dir/file dest_dir/file将宿主机的文件复制到镜像内,如果是一个压缩文件,将会在复制后自动解压。 支持URL路径下载源文件,但下载方式不能自动解压。
COPY source_dir/file dest_dir/file和ADD相似,将宿主机的文件复制到镜像内,但是如果有压缩文件并不能解压。不支持URL路径下载。
WORKDIR path_dir设置工作目录
ENV设置环境变量
ARG构建参数
VOLUME设置容器的挂载卷

1. 用Dockerfile创建nginx-1.18.0镜像

[root@localhost ~]# mkdir -p /data/dockerfile/system/centos/nginx/
[root@localhost ~]# cd /data/dockerfile/system/centos/nginx/
[root@localhost centos7]# vim /etc/docker/daemon.json    #编辑Docker的守护进程配置文件

{
"registry-mirrors":[
"https://docker.m.daocloud.io",
"https://huecker.io",
"https://dockerhub.timeweb.cloud",
"https://noohub.ru"
]
}

[root@localhost nginx]# vim qh.repo      #编辑清华源文件

[base]
name=CentOS-$releasever - Base - mirrors.aliyun.com
failovermethod=priority
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.9.2009/os/x86_64/
gpgcheck=0

[root@localhost nginx]# vim Dockerfile   #编辑Dockerfile文件

FROM centos:7.9.2009
LABEL author="lhey" \
      version="1.0"
RUN rm -rf /etc/yum.repos.d
COPY qh.repo /etc/yum.repos.d/
RUN yum -y install gcc pcre-devel openssl-devel zlib-devel openssl  openssl-devel
RUN useradd -M -s /sbin/nologin nginx
ADD nginx-1.18.0.tar.gz /opt/
RUN cd /opt/nginx-1.18.0 && ./configure --prefix=/apps/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module && make -j2 && make install
RUN chown -R nginx.nginx /apps/nginx
RUN ln -s /apps/nginx/sbin/nginx /usr/sbin
EXPOSE 80
CMD ["nginx","-g","daemon off;"]

[root@localhost nginx]# docker build -t nginx-1.18.0:v1 .    #创建nginx-1.18.0镜像

[root@localhost centos7]# docker images
REPOSITORY     TAG        IMAGE ID       CREATED         SIZE
nginx-1.18.0   v1         5d218ee0e98d   2 minutes ago   366MB

//上传到阿里云镜像仓库
#将本地镜像标记为阿里云镜像仓库中的镜像
docker tag nginx-1.18.0:v1 registry.cn-hangzhou.aliyuncs.com/lhey-0915/nginx-1.18.0:v1
#将标记后的镜像推送到阿里云镜像仓库
docker push registry.cn-hangzhou.aliyuncs.com/lhey-0915/nginx-1.18.0:v1

2. 用Dockerfile创建tomcat-9.0.16镜像

[root@localhost ~]# mkdir -p /data/dockerfile/system/centos/tomcat/
[root@localhost ~]# cd /data/dockerfile/system/centos/tomcat/
[root@localhost tomcat]# vim /etc/docker/daemon.json    #编辑Docker的守护进程配置文件

{
"registry-mirrors":[
"https://docker.m.daocloud.io",
"https://huecker.io",
"https://dockerhub.timeweb.cloud",
"https://noohub.ru"
]
}

[root@localhost centos7]# vim qh.repo      #编辑清华源文件

[base]
name=CentOS-$releasever - Base - mirrors.aliyun.com
failovermethod=priority
baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.9.2009/os/x86_64/
gpgcheck=0

[root@localhost tomcat]# vim Dockerfile    #编辑Dockerfile文件 

FROM centos:7.9.2009
LABEL author="lhey" \
      version="1.0"
RUN rm -rf /etc/yum.repos.d/*
COPY qh.repo /etc/yum.repos.d/
ADD jdk-8u291-linux-x64.tar.gz /opt
ADD apache-tomcat-9.0.16.tar.gz /opt
RUN cd /opt/apache-tomcat-9.0.16
RUN ln -s /opt/apache-tomcat-9.0.16 /usr/local/tomcat
RUN useradd -s /sbin/nologin tomcat
RUN chown -R tomcat.tomcat /usr/local/tomcat
ENV JAVA_HOME /opt/jdk1.8.0_291
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 8080
WORKDIR /usr/local/tomcat/bin
USER tomcat
CMD ["catalina.sh","run"]

[root@localhost tomcat]# docker build -t tomcat-9.0.16:v1 .   #创建tomcat-9.0.16镜像

[root@localhost tomcat]# docker images
REPOSITORY      TAG        IMAGE ID       CREATED             SIZE
tomcat-9.0.16   v1         43bf423960aa   22 seconds ago      579MB

//上传到阿里云镜像仓库
#将本地镜像标记为阿里云镜像仓库中的镜像
docker tag tomcat-9.0.16:v1 registry.cn-hangzhou.aliyuncs.com/lhey-0915/tomcat-9.0.16:v1
#将标记后的镜像推送到阿里云镜像仓库
docker push registry.cn-hangzhou.aliyuncs.com/lhey-0915/tomcat-9.0.16:v1