[TOC]
镜像
Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。
个人理解为是创建容器的基础,类似于安装系统是所需的ISO文件,镜像就是生成容器所需的ISO。
镜像
获取镜像
1 | docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] |
列出镜像
列出镜像-不显示中间层镜像
1 | ☁ ~ docker image ls |
列表包含了
仓库名
、标签
、镜像 ID
、创建时间
以及所占用的空间
为了加速镜像构建、重复利用资源,Docker 会利用 中间层镜像
所有镜像:
1 | ☁ ~ docker image ls -a |
特定格式显示镜像列表
1 | ☁ ~ docker image ls -q |
1 | docker image ls --format "{{.ID}}: {{.Repository}}" |
查看镜像、容器、数据卷所占用的空间
1 | ☁ ~ docker system df |
悬浮镜像清理
无标签镜像也被称为 虚悬镜像(dangling image) ,可以用下面的命令专门显示这类镜像:
1 | $ docker image ls -f dangling=true |
1 | ☁ ~ docker image prune |
删除镜像
1 | docker image rm [选项] <镜像1> [<镜像2> ...] |
其中,
<镜像>
可以是镜像短 ID
、镜像长 ID
、镜像名
或者镜像摘要
1 | # 删除所有镜像 |
保存容器为镜像
运行一个容器的时候(如果不使用卷的话),我们做的任何文件修改都会被记录于容器存储层里
1 | docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]] |
Demo:
1 | docker commit \ |
其中
--author
是指定修改的作者,而--message
则是记录本次修改的内容、
使用 docker commit
意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知
容器
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root
文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样
镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
仓库
一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
一个 Docker Registry 中可以包含多个仓库(Repository
);每个仓库可以包含多个标签(Tag
);每个标签对应一个镜像
通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过
<仓库名>:<标签>
的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以latest
作为默认标签。
Dockerfile
Dockerfile 是一个文本文件,其内包含了一条条的**指令(Instruction)**,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
构建镜像
1 | docker build [选项] <上下文路径/URL/-> |
在 Dockerfile
文件所在目录执行:
1 | docker build -t nginx:v3 . |
###FROM
FROM
就是指定基础镜像,因此一个 Dockerfile
中 FROM
是必备的指令,并且必须是第一条指令。
RUN 执行命令
RUN
指令是用来执行命令行命令的。由于命令行的强大能力,RUN
指令在定制镜像时是最常用的指令之一,
其格式有两种:
shell 格式:
RUN <命令>
,就像直接在命令行中输入的命令一样。刚才写的 Dockerfile 中的RUN
指令就是这种格式。```Dockerfile
RUN echo ‘Hello, Docker!
‘ > /usr/share/nginx/html/index.html1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- *exec* 格式:`RUN ["可执行文件", "参数1", "参数2"]`,这更像是函数调用中的格式。
### COPY 复制文件
格式:
- `COPY [--chown=<user>:<group>] <源路径>... <目标路径>`
- `COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]`
和 `RUN` 指令一样,也有两种格式,一种类似于命令行,一种类似于函数调用。
`COPY` 指令将从构建上下文目录中 `<源路径>` 的文件/目录复制到新的一层的镜像内的 `<目标路径>` 位置。
`<源路径>` 可以是多个,甚至可以是通配符,其通配符规则要满足 Go 的 [`filepath.Match`](https://golang.org/pkg/path/filepath/#Match) 规则,如:
```Dockerfile
COPY hom* /mydir/
COPY hom?.txt /mydir/
使用
COPY
指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等
ADD 更高级的复制文件
ADD
指令和 COPY
的格式和性质基本一致。但是在 COPY
基础上增加了一些功能。
如果 <源路径>
为一个 tar
压缩文件的话,压缩格式为 gzip
, bzip2
以及 xz
的情况下,ADD
指令将会自动解压缩这个压缩文件到 <目标路径>
去。
在 Docker 官方的 Dockerfile 最佳实践文档 中要求,尽可能的使用 COPY
,因为 COPY
的语义很明确,就是复制文件而已,而 ADD
则包含了更复杂的功能,其行为也不一定很清晰。最适合使用 ADD
的场合,就是所提及的需要自动解压缩的场合。
在使用该指令的时候还可以加上 --chown=<user>:<group>
选项来改变文件的所属用户及所属组。
1 | ADD --chown=55:mygroup files* /mydir/ |
CMD 容器启动命令
CMD
指令的格式和 RUN
相似,也是两种格式:
shell
格式:CMD <命令>
exec
格式:CMD ["可执行文件", "参数1", "参数2"...]
- 参数列表格式:
CMD ["参数1", "参数2"...]
。在指定了ENTRYPOINT
指令后,用CMD
指定具体的参数。
之前介绍容器的时候曾经说过,Docker 不是虚拟机,容器就是进程。既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数。CMD
指令就是用于指定默认的容器主进程的启动命令的。
VOLUME 定义匿名卷
格式为:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
EXPOSE 声明端口
格式为 EXPOSE <端口1> [<端口2>...]
。
要将 EXPOSE
和在运行时使用 -p <宿主端口>:<容器端口>
区分开来。-p
,是映射宿主端口和容器端口,换句话说,就是将容器的对应端口服务公开给外界访问,而 EXPOSE
仅仅是声明容器打算使用什么端口而已,并不会自动在宿主进行端口映射。
ENV 设置环境变量
格式有两种:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
这个指令很简单,就是设置环境变量而已,用法如下面的格式$KEY
ARG 构建参数
格式:ARG <参数名>[=<默认值>]
构建参数和 ENV
的效果一样,都是设置环境变量,ARG
所设置的构建环境的环境变量,在将来容器运行时是不会存在这些环境变量的。不要因此就使用 ARG
保存密码之类的信息,因为 docker history
还是可以看到所有值的。
Dockerfile
中的 ARG
指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 docker build
中用 --build-arg <参数名>=<值>
来覆盖。