Dockerfile
文件格式
- - 注释: 以 # 开头的是注释语句
- - 指令: `INSTRUCTION argument`
常用指令
FROM
指定基础镜像。
FROM [image] FROM [image:tag]
- 必须是已经存在的基础镜像
- 必须是第一条非注释指令
MAINTAINER
指定镜像的作者信息,包括镜像的所有者和联系信息。
MAINTAINER [name]
RUN
指定当前镜像中运行的命令。
RUN [command] # shell 模式 RUN ["executable", "param1", "param2"] # exec 模式
在 shell 模式下,是以 `/bin/sh -c command` 开始执行命令
比如:
RUN echo hello
在 exec 模式下,可以使用其他的 shell 执行命令
每个 RUN 命令都会在当前镜像上层创建一个新的镜像来运行命令。
所以,不要过多书写 RUN 指令,尽量将多个命令合并。
EXPOSE
指定运行该镜像的容器使用的端口。
EXPOSE [port1] [port2] ...
但是运行时Docker并不会自动开启对应服务,还需要手动开启对应的服务并添加端口的映射指令,比如:
$ docker run --name nginx-server -p 80 -d ubuntu:latest nginx -g "daemon off;"
CMD
跟 RUN 命令使用方法类似,也是运行一个指令:
CMD [command] # shell 模式 CMD ["executable", "param1", "param2"] # exec 模式 CMD ["param1", "param2"] # 作为 ENTRYPOINT 指令的默认参数
与 RUN 命令的区别:
- RUN 命令时在镜像构建时运行
- CMD 命令是在容器启动时运行
比如:
CMD ['/usr/sbin/nginx', '-g', 'deamon off;']
指定 CMD 命令之后,运行容器的时候就不需要在后面加上运行参数了,不过还是得指定端口映射:
$ docker run --name nginx-server -p 80 -d ubuntu:latest
注意:
如果在启动一个容器时,指定了运行时命令,则 CMD 中的命令会被覆盖。
ENTRYPOINT
也是运行一个命令,与 RUN 不同的是,ENTRYPOINT 中的指令不会被运行容器时覆盖。
ENTRYPOINT [command] # shell 模式 ENTRYPOINT ["executable", "param1", "param2"] # exec 模式
运行容器时如果必须覆盖 ENTRYPOINT 中的命令,需要使用
docker run -- entrypoint [command]
进行覆盖。
ADD 和 COPY
ADD 和 COPY 都是复制文件。
ADD [src]... [dest] ADD ["src"... "dest"] # 适用于文件路径中有空格的情况 COPY [src]... [dest] COPY ["src"... "dest"] # 适用于文件路径中有空格的情况
区别为:ADD 包含了类似 tar 的解压功能
如果只是简单的复制文件,推荐使用 COPY。
VOLUME
用来向基于镜像创建的容器添加卷。
VOLUME ["/data"]
WORKDIR
设置工作目录,即创建容器后进入的目录,CMD 和 ENTRYPOINT 命令都会在这个目录下执行。
WORKDIR /path/to/dir
ENV
设置环境变量。
ENV [key] [value] ENV [key]=[value]
USER
指定容器为哪个用户运行,可以使用uid(用户)和gid(用户组),以及其组合。
USER daemon
有以下几种组合:
USER user USER user:group USER user:gid USER uid USER uid:group USER uid:gid
默认使用 root 用户。
ONBUILD
ONBUILD 是一个镜像触发器。
ONBUILD [INSTRUCTION]
当一个镜像被其他镜像作为基础镜像时执行,会在构建过程中插入指令。
Dockerfile 示例
# My First Dockerfile FROM ubuntu:14.04 MAINTAINER quanzaiyu "quanzaiyu@163.com" ENV REFERSH_DATE 2015-04-01 RUN apt-get update && apt-get install -y nginx COPY index.html /usr/share/nginx/html # 将宿主机的文件覆盖到容器中 EXPOSE 80 ENTRYPOINT ['/usr/sbin/nginx', '-g', 'deamon off;'] CMD echo 'created'
为 CentOS 安装常用工具
FROM centos:latest RUN yum update -y && yum install net-tools.x86_64 -y EXPOSE 80 CMD /bin/bash
使用 Dockerfile 构建镜像
使用 docker build 构建镜像的格式:
$ docker build [OPTIONS] PATH | URL | -
其中 OPTIONS 包括:
- --force-rm=false
- --no-cache=false
- --pull=false
- -q, --quiet-false
- --rm=true
- -t, --tag="" 为镜像取个名字(打标签)
如果 Docker 文件就在当前目录,则:
$ docker build -t "731734107/test" .
Dockerfile 构建过程
1. 从基础镜像运行一个容器
2. 执行一条指令,对容器做出修改
3. 执行类似 docker commit 的操作,提交一个新的镜像层
4. 再基于刚提交的镜像运行一个新容器
5. 执行 Dockerfile 中的下一条指令,直至所有指令执行完毕
构建过程中,会生成一些中间层镜像,可以使用中间层镜像进行调试,便于定位错误的位置。
正常情况下,构建镜像会用到缓存,这样可以提升构建速度,但有的时候不想用缓存,可以在构建命令中加入 `--no-cache` 选项。
另外,修改环境变量也可以刷新缓存,比如上面的 Dockerfile 示例中,改变 REFERSH_DATE 的值即可。
可以使用 `docker history` 命令查看镜像的构建过程。
结束语
Docker的基础也大概就这么多了, 之后将会是使用Docker创建实例的教程, 比如众所周知的高并发Web容器: Nginx, 敬请期待。