docker命令

1. 源设置

/etc/docker/daemon.json

1
2
3
4
5
{

"registry-mirrors": ["https://alzgoonw.mirror.aliyuncs.com"]

}

2. 镜像仓库

  1. docker login [OPTIONS] [SERVER]

    登录镜像仓库

    -u:用户名

    -p:密码

    example:

1
docler login -u username -p password
  1. docker logout

    登出镜像仓库

  2. docker search [OPTIONS] images

    –automated :只列出automated build类型的镜像

    –no-trunc:显示完整的镜像描述

    -s:列出收藏数不小于指定值的镜像

    example:

    1
    docker search -s 20 unbuntu  //列出收藏数不小于20的ubuntu镜像
  3. docker pull [OPTIONS] name[:TAG@DIGEST]

    -a:拉起所有tagged镜像

    –disable-content-trust:忽略镜像校验,默认开启

    example:

    1
    docker pull unbuntu  //拉去ubuntu最新版镜像
  4. docker push [OPTIONS] NAME[:TAG]

    将本地镜像上传到镜像仓库,首先要登录到镜像仓库,还要登录到Docker Hub创建对应名称的仓库,然后用tag命令给镜像打标签,只有打完标签后才能上传。

  5. docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/] [USERNAME/] NAME[:TAG]

    标记本地镜像,归入某一仓库。

    完整版push:

    1
    2
    3
    docker tag ubuntu:latest eara0/ubuntu:v1
    docker Hub创建对应仓库
    docker push area0/ubuntu:v1

3. 生命周期

  1. docker run

    创建一个新的容器并运行

    常用指令

    1
    2
    3
    4
    5
    6
    7
    8
    -i选项表示使用交互模式,始终保持输入流开放
    -t选项表示分配一个伪终端,一般两个参数结合时使用-it,即可在容器中利用打开的伪终端进行交互操作
    -d选项: 后台运行容器,并返回容器ID--name选项可以指定docker run命令启动的容器名字,若无此选项,Docker 将为容器随机分配一个名字
    -c选项:用于给运行在容器中的所有进程分配CPU的shares值,这是一个相对权重,实际的处理速度还与宿主机的CPU相 关
    -m选项:用于限制为容器中所有进程分配的内存总量,以B、K、M、G为单位-v选项:用于挂载一个volume,可以用多个
    -v参数同时挂载多个volume。volume的格式为[host-dir]:[container-dir]:[rw|ro]
    -p选项:用于将容器内部端口映射给宿主机的端口,其常见格式为:主机(宿主)端口:容器内部端口
    -P选项:随机端口映射,容器内部端口随机映射到宿主机的端口

    example:

    1
    2
    docker run -it ubuntu /bin/bash    		//启动并返回终端
    docker run -itd --name ubuntu-test ubuntu /bin/bash //后台启动并返回终端
  1. docker start

    启动一个或多个已经停止的容器

    1
    docker start b750bbbcfd88 
  2. docker stop

    停止一个运行的容器

    1
    docker stop b750bbbcfd88
  3. docker restart

    重启容器

    1
    docker restart b750bbbcfd88
  4. docker rm

    删除容器

    1
    2
    3
    -f :通过SIGKILL信号强制删除一个运行中的容器
    -l :移除容器间的网络连接,而非容器本身
    -v :-v 删除与容器关联的卷
    1
    docker rm -f b750bbbcfd88
  5. docker kill

    杀掉运行中的容器

    1
    docker kill -s kill b750bbbcfd88

    PS.常见rm和kill组合命令

    杀掉所有正在运行的容器

    1
    docker kill $(docker ps -a -q)

    删除所有正在运行的容器

    1
    docker rm $(docker ps -a -q)
  6. docker exec和docker attach

    在运行中的容器执行命令

    attach:

    1
    docker attach 1e560fca3906   // 如果从这个容器退出,会导致容器的停止。

    exec:

    1
    2
    3
    -d :分离模式: 在后台运行
    -i :即使没有附加也保持STDIN 打开
    -t :分配一个伪终端

    example:

    1
    docker exec -it 243c32535da7 /bin/bash    //返回shell

4. 导出和导入

  • export和import
  1. docker export

    导出镜像

    1
    docker export 1e560fca3906 > ubuntu.tar
  2. docker import

    导入镜像

    1
    2
    cat docker/ubuntu.tar | docker import - demo/ubuntu:v1
    docker import http://demo.com //支持从url导入
  3. save和load

    1. docker save

    将指定镜像保存为tar文件

    1
    docker save -o nginx.tar nginx:last
    1. docker load

    导入使用docker save命令导出的镜像

    1
    docker load -i nginx.tar

docker save和docker export的区别

  1. docker save保存的是镜像(image),docker export保存的是容器(container);
  2. docker load用来载入镜像包,docker import用来载入容器包,但两者都会恢复为镜像;
  3. docker load不能对载入的镜像重命名,而docker import可以为镜像指定新名称。

5.端口

1
2
3
-p 1234-1236:1222-1224     //指定范围添加端口
docker run -d -p 5001:5000 training/webapp python app.py //容器5000端口映射到主机5001
docker port bf08b7f2cd89 //查看映射端口

6. 镜像管理

  1. docker images

    通过docker images命令可以列出主机上的镜像,默认只列出最顶层的镜像,可以使用-a选项显示出所有镜像

    1
    docker images -a
  2. docker rmi

    docker rmi命令用于删除镜像,删除镜像时,如果已有基于该镜像启动的容器存在,则无法直接删除,需要先用rm命令删除容器。这两个子命令都提供 -f 选项,可强制删除存在容器的镜像或启动中的容器。

    1
    docker rmi kali:10.1
  3. docker commit

    docker commit命令可以将一个容器固化为一个新的镜像。当需要制定特定的镜像时,会进行修改容器的配置,比如在容器中安装一些特定的工具等,通过commit命令可以将这些修改保存起来,使其不会因为容器的停止而丢失。

    • -a:提交的镜像作者
    • -c :使用Dockerfile指令来创建镜像
    • -m :提交时的说明文字
    • -p :在commit时,将容器暂停
    1
    docker commit -a "demo" 66d682605023 kali:10.1

7. 运维相关

  1. docker ps

    常用的选项有-a和-l,-a选项可以查看所有的容器,包括停止的容器;-l选项只查看最新创建的容器,包括不在运行的容器

  2. docker rename

    重命名容器

    1
    docker rename 12312391 newname
  3. docer stats

    显示容器资源的使用情况统计信息

    1
    docker stats 12312391
  4. docker top

    查看运行的进程信息

  5. docker cp

    主机与容器之间数据拷贝

    example:

    • 将本目录下的test.php文件复制到容器的’/var/www/html/‘目录下

      1
      docker cp test.php 5198ec963e43:/var/www/html/
    • 将容器内’/var/www/html/index.php’复制到本机/root目录下:

      1
      docker cp 5198ec963e43:/var/www/html/index.php /root/
  6. docker diff

    查看容器文件结构

    1
    docker diff 5198ec963e43
  7. docker events

    从服务器获取实时时间

    1
    2
    3
    -f:根据条件过滤事件
    --since:从指定的时间戳后显示所有事件
    --until:流水时间显示到指定的时间为止
    1
    docker events --since=""2020-01-21" 
  8. docker history

    查看指定镜像的创建历史

    1
    docker history TAG
  9. docker inspect

    来查看 Docker 的底层信息

    1
    docker inspect 243c32535da7
  10. docker logs

    查看容器打印日志

    1
    docker logs -f bf08b7f2cd89  //查看日志

8. 文件映射

  1. 主机卷的映射
1
2
3
4
docker run -it -v /root/software:/software --privileged=true  docker.io/centos /bin/bash

-v 挂载目录/root/software 本地目录 /software容器目录,在创建前容器是没有software目录的容器会自己创建
--privileged=true 关闭安全权限,否则你容器操作文件夹没有权限
  1. 通过docker创建卷

    此种方式不必考虑权限问题,docker会为我们处理好权限。

    • 创建 docker volume create –name v1
    • 查看 docker inspect v1
    • 删除数据卷 docker volume rm v1

    创建容器

    1
    docker run -d -v v1:/usr/local/nginx --name nginx  //v1为创建的卷
  2. 使用共享存储的映射

将一台主机做为nfs主机, 创建相应的文件夹,并将其共享给docker的两台主机,两台docker主机将分享的文件夹映射到容器中,使得对应的容器可以共享到nfs主机的内容。可以将http等服务器的相应的页面文件夹使用这种形式,从而实现多个容器跑一个业务

nfs主机配置【192.168.6.77】

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
28
29
30
31
32
33
34
35
36
[root@nfs ~]# yum -y install nfs-utils
[root@nfs ~]# vim /etc/exports
/public *(rw)
[root@nfs ~]# systemctl restart nfs-server
Failed to restart nfs-serve.service: Unit not found
[root@nfs ~]# mkdir /public
[root@nfs ~]# cd /public/
[root@nfs public]# touch nfs.txt
[root@nfs public]# ls
nfs.txt

docker1主机配置
[root@docker1 ~]# vim /etc/fstab
192.168.6.77:/public /mnt/nfs nfs defaults,_netdev 0 0
[root@docker1 ~]# mkdir /mnt/nfs
[root@docker1 ~]# systemctl restart nfs-server
[root@docker1 ~]# mount -a
[root@docker1 ~]# df -h
192.168.6.77:/public 17G 3.2G 14G 19% /mnt/nfs
[root@docker1 ~]# docker run -it -v /mnt/nfs/:/zhuhaiyan 192.168.6.153:5000/myos
[root@c7c376e3755a /]# cd /zhuhaiyan
[root@c7c376e3755a zhuhaiyan]# ls
nfs.txt

docker2主机配置
[root@docker2 ~]# vim /etc/fstab
192.168.6.77:/public /mnt/nfs nfs defaults,_netdev 0 0
[root@docker2 ~]# mkdir /mnt/nfs
[root@docker2 ~]# systemctl restart nfs-server
[root@docker2 ~]# mount -a
[root@docker2 ~]# df -h
192.168.6.77:/public 17G 3.2G 14G 19% /mnt/nfs
[root@docker2 ~]# docker run -it -v /mnt/nfs/:/zhuhaiyan 192.168.6.153:5000/myos
[root@cdd805771d07 /]# cd /zhuhaiyan/
[root@cdd805771d07 zhuhaiyan]# ls
nfs.txt

9. 网络设置

1
2
3
4
5
6
7
8
docker network create -d bridge test  //新建网络

-d:参数指定 Docker 网络类型,有 bridge、overlay。

docker network ls。 //查看创建的网络

docker run -itd --name test1 --network test ubuntu /bin/bash //--network指定使用的网络

配置 DNS

可以在宿主机的 /etc/docker/daemon.json 文件中增加以下内容来设置全部容器的 DNS:

1
2
3
4
5
6
{
"dns" : [
"114.114.114.114",
"8.8.8.8"
]
}

设置后,启动容器的 DNS 会自动配置为 114.114.114.114 和 8.8.8.8。

配置完,需要重启 docker 才能生效。

启动时设置DNS

1
2
3
4
5
docker run -it --rm host_ubuntu  --dns=114.114.114.114 --dns-search=test.com ubuntu

-h HOSTNAME或者--hostname=HOSTNAME:设定容器的主机名,它会被写到容器内的 /etc/hostname 和 /etc/hosts。
--dns=IP_ADDRESS: 添加 DNS 服务器到容器的 /etc/resolv.conf 中,让容器用这个服务器来解析所有不在 /etc/hosts 中的主机名。
--dns-search=DOMAIN: 设定容器的搜索域,当设定搜索域为 .example.com 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 host.example.com。

10 .Dockerfile

什么是 Dockerfile?

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

  1. 案例:

创建Dockerfile文件

vi Dockerfile

1
2
FROM docker.io/kalilinux/kali-linux-docker
RUN echo 'test' > /root/test

创建镜像

1
docker build -t kali:test .   // kali:test(镜像名称:镜像标签),最后的 . 代表本次执行的上下文路径
  1. FROM 和 RUN 指令的作用

    FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。

    RUN:用于执行后面跟着的命令行命令。有以下俩种格式:

shell 格式:

1
2
RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。

exec 格式:

1
2
3
RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

注意:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
FROM centos
RUN yum install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz

以上执行会创建 3 层镜像。可简化为以下格式:

FROM centos
RUN yum install wget \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& tar -xvf redis.tar.gz

如上,以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

上下文路径

上面中,有提到指令最后一个 . 是上下文路径,那么什么是上下文路径呢?

1
docker build -t kali:test .

上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。

解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。

如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。

注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

指令详解

COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

格式:

1
2
COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",... "<目标路径>"]

**[–chown=:]**:可选参数,用户改变复制到容器内文件的拥有者和属组。

**<源路径>**:源文件或者源目录,这里可以是通配符表达式,其通配符规则要满足 Go 的 filepath.Match 规则。例如:

1
2
COPY hom* /mydir/
COPY hom?.txt /mydir/

**<目标路径>**:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

ADD

ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
    因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,**所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD 。**

CMD

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

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。

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

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

格式:

1
2
3
CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...]
CMD ["<param1>","<param2>",...] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

ENTRYPOINT

类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。

但是, 如果运行 docker run 时使用了 –entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序。

优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。

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

格式:

1
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

当指定了 ENTRYPOINT 后, CMD 的含义就发生了改变,不再是直接的运行其命令,而是将CMD 的内容作为参数传给 ENTRYPOINT 指令,换句话说实际执行时,将变为:

1
<ENTRYPOINT> "<CMD>"

可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参,以下示例会提到。

示例:

假设已通过 Dockerfile 构建了 nginx:test 镜像:

1
2
3
4
FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参

1、不传参运行

1
$ docker run  nginx:test

容器内会默认运行以下命令,启动主进程。

1
nginx -c /etc/nginx/nginx.conf

2、传参运行

1
$ docker run  nginx:test -c /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)

1
nginx -c /etc/nginx/new.conf

那么有了 CMD 后,为什么还要有 ENTRYPOINT 呢?这种 "" 有什么好处么?让我们来看几个场景。

场景一:让镜像变成像命令一样使用

  假设我们需要一个得知自己当前公网 IP 的镜像,那么可以先用 CMD 来实现:

1
2
3
4
5
FROM ubuntu:16.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s", "http://ip.cn" ]

假如我们使用 docker build -t myip . 来构建镜像的话,如果我们需要查询当前公网 IP,只需要执行:

1
2
$ docker run myip
当前 IP:61.148.226.66 来自:北京市 联通

嗯,这么看起来好像可以直接把镜像当做命令使用了,不过命令总有参数,如果我们希望加参数呢?比如从上面的 CMD 中可以看到实质的命令是 curl ,那么如果我们希望显示 HTTP头信息,就需要加上 -i 参数。那么我们可以直接加 -i 参数docker run myip 么?

1
2
3
4
$ docker run myip -i
docker: Error response from daemon: invalid header field value "oci runtime error: con
tainer_linux.go:247: starting container process caused \"exec: \\\"-i\\\": executable
file not found in $PATH\"\n".

我们可以看到可执行文件找不到的报错, executable file not found 。之前我们说过,跟在镜像名后面的是 command ,运行时会替换 CMD 的默认值。因此这里的 -i 替换了原来的 CMD ,而不是添加在原来的 curl -s http://ip.cn 后面。而 -i 根本不是命令,所以自然找不到。

那么如果我们希望加入 -i 这参数,我们就必须重新完整的输入这个命令:

1
$ docker run myip curl -s http://ip.cn -i

这显然不是很好的解决方案,而使用 ENTRYPOINT 就可以解决这个问题。现在我们重新用 ENTRYPOINT 来实现这个镜像:

1
2
3
4
5
FROM ubuntu:16.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]

这次我们再来尝试直接使用 docker run myip -i :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ docker run myip
当前 IP:61.148.226.66 来自:北京市 联通
$ docker run myip -i
HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Tue, 22 Nov 2016 05:12:40 GMT
Content-Type: text/html; charset=UTF-8
Vary: Accept-Encoding
X-Powered-By: PHP/5.6.24-1~dotdeb+7.1
X-Cache: MISS from cache-2
X-Cache-Lookup: MISS from cache-2:80
X-Cache: MISS from proxy-2_6
Transfer-Encoding: chunked
Via: 1.1 cache-2:80, 1.1 proxy-2_6:8006
Connection: keep-alive

当前 IP:61.148.226.66 来自:北京市 联通

  可以看到,这次成功了。这是因为当存在 ENTRYPOINT 后, CMD 的内容将会作为参数传给 ENTRYPOINT ,而这里 -i 就是新的 CMD ,因此会作为参数传给 curl ,从而达到了我们预期的效果。

场景二:应用运行前的准备工作

  启动容器就是启动主进程,但有些时候,启动主进程前,需要一些准备工作。比如 mysql 类的数据库,可能需要一些数据库配置、初始化的工作,这些工作要在最终的 mysql 服务器运行之前解决。

  此外,可能希望避免使用 root 用户去启动服务,从而提高安全性,而在启动服务前还需要以 root 身份执行一些必要的准备工作,最后切换到服务用户身份启动服务。或者除了服务外,其它命令依旧可以使用 root 身份执行,方便调试等。

  这些准备工作是和容器 CMD 无关的,无论 CMD 为什么,都需要事先进行一个预处理的工作。这种情况下,可以写一个脚本,然后放入 ENTRYPOINT 中去执行,而这个脚本会将接到的参数(也就是 )作为命令,在脚本最后执行。比如官方镜像 redis 中就是这么做的:

1
2
3
4
5
6
7
8
9
10
11
12
13
FROM alpine:3.4

...

RUN addgroup -S redis && adduser -S -G redis redis

...

ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 6379

CMD [ "redis-server" ]

  可以看到其中为了 redis 服务创建了 redis 用户,并在最后指定了 ENTRYPOINT 为 dockerentrypoint.sh 脚本。

1
2
3
4
5
6
7
8
9
#!/bin/sh
...
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then

chown -R redis .
exec su-exec redis "$0" "$@"
fi
exec "$@"

  该脚本的内容就是根据 CMD 的内容来判断,如果是 redis-server 的话,则切换到 redis 用户身份启动服务器,否则依旧使用 root 身份执行。比如:

1
2
$ docker run -it redis id
uid=0(root) gid=0(root) groups=0(root)

  而使用 service nginx start 命令,则是希望 systemd 来以后台守护进程形式启动 nginx 服务。而刚才说了 CMD service nginx start 会被理解为 CMD [ “sh”, “-c”, “service nginxstart”] ,因此主进程实际上是 sh 。那么当 service nginx start 命令结束后, sh 也就结束了, sh 作为主进程退出了,自然就会令容器退出。

  正确的做法是直接执行 nginx 可执行文件,并且要求以前台形式运行。比如:

1
CMD ["nginx", "-g", "daemon off;"]

EXPOSE

仅仅只是声明端口。

EXPOSE 指令是声明运行时容器提供服务端口,这只是一个声明,在运行时并不会因为这个声明应用就会开启这个端口的服务。

作用:

  • 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
  • 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

格式:

1
EXPOSE <端口1> [<端口2>...]

WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。

docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。

格式:

1
WORKDIR <工作目录路径>

USER

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

格式:

1
USER <用户名>[:<用户组>]

VOLUME 定义匿名卷

格式为:

1
2
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>

  容器运行时应该尽量保持容器存储层不发生写操作,对于数据库类需要保存动态数据的应用,其数据库文件应该保存于卷(volume)中。为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。

1
VOLUME /data

  这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化。当然,运行时可以覆盖这个挂载设置。比如:

1
docker run -d -v mydata:/data xxxx

  在这行命令中,就使用了 mydata 这个命名卷挂载到了 /data 这个位置,替代了 Dockerfile 中定义的匿名卷的挂载配置。

ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

格式:

1
2
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:

1
2
3
4
ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

ARG

构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

构建命令 docker build 中可以用 –build-arg <参数名>=<值> 来覆盖。

格式:

1
ARG <参数名>[=<默认值>]

HEALTHCHECK

用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

格式:

1
2
3
4
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

ONBUILD

用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。

格式:

1
ONBUILD <其它指令>