Docker Dockerfile 编排
文章目录
Docker Dockerfile 编排
1. FROM
2. COPY
3. ADD
4. RUN
5. CMD
6. ENTRYPOINT
7. LABEL
8. EXPOSE
9. ENV
10. VOLUME
11. USER
12. WORKDIR
13. ARG
14. ONBUILD
15. STOPSIGNAL
16. SHELL
1. FROM
FROM指令用于指定其后构建新镜像所使用的基础镜像。
FROM <image> FROM <image>:<tag> FROM <image>:<digest>
FROM必须是Dockerfile中第一条非注释命令
在一个Dockerfile文件中创建多个镜像时,docker17.05版本以后,FROM可以多次出现。只需在每个新命令FROM之前,记录提交上次的镜像ID。
tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
多次使用FROM的情况时构建与运行分离的场景
基础镜像golang:1.10.3是非常庞大的,因为其中包含了所有的Go语言编译工具和库,而运行时候我们仅仅需要编译后的server程序
就行了,不需要编译时的编译工具,最后生成的大体积镜像就是一种浪费。
scratch 是内置关键词,并不是一个真实存在的镜像。 FROM scratch 会使用一个完全干净的文件系统,不包含任何文件。因为Go语言编译后不需要运行时,也就不需要安装任何的运行库。FROM scratch可以使得最后生成的镜像最小化,其中只包含了server 程序。
当然,你也可以FROM一个你熟悉的并且空间占用小的镜像,比如:centos、ubuntu、busybox等。
# 编译阶段 FROM golang:1.10.3 COPY server.go /build/ WORKDIR /build RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server # 运行阶段 FROM scratch # 从编译阶段的中拷贝编译结果到当前镜像中 COPY --from=0 /build/server / ENTRYPOINT ["/server"]
COPY 指令的--from=0
参数,从前边的阶段中拷贝文件到当前阶段中,多个FROM语句时,0代表第一个阶段。除了使用数字,我们还可以给阶段命名,比如:
# 编译阶段 命名为 builder FROM golang:1.10.3 as builder # ... 省略 # 运行阶段 FROM scratch # 从编译阶段的中拷贝编译结果到当前镜像中 COPY --from=builder /build/server /
COPY --from
不但可以从前置阶段中拷贝,还可以直接从一个已经存在的镜像中拷贝。比如,
FROM ubuntu:16.04 COPY --from=quay.io/coreos/etcd:v3.3.9 /usr/local/bin/etcd /usr/local/bin/
2. COPY
COPY同样用于复制构建环境中的文件或目录到镜像中。
COPY <src>... <dest> COPY ["<src>",... "<dest>"] COPY --from=builder /build/server / COPY --from=quay.io/coreos/etcd:v3.3.9 /usr/local/bin/etcd /usr/local/bin/
COPY指令非常类似于ADD,不同点在于COPY只会复制构建目录下的文件,不能使用URL也不会进行解压操作。
3. ADD
ADD用于复制构建环境中的文件或目录到镜像中。
ADD <src>... <dest> ADD ["<src>",... "<dest>"]
<src>
指定源文件位置,<dest>
来指定目标位置。<src>
可以是一个构建上下文中的文件或目录,也可以是一个URL,但不能访问构建上下文之外的文件或目录。
ADD复制一个网络文件:
ADD http://wordpress.org/test.zip $WORKER_PATH
另外,如果使用的是本地归档文件(gzip、bzip2、xz)时,Docker会自动进行解包操作,类似使用tar -x
4. RUN
RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
shell执行
在这种方式会在shell中执行命令,Linux下默认使用/bin/sh -c
,Windows下使用cmd /S /C
。
注意:通过SHELL命令修改RUN所使用的默认shell
RUN <command>
RUN /bin/bash -c 'source $HOME/.bashrc; \ echo $HOME' #通过RUN执行多条命令时,可以通过\换行执行
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME' #同一行中,通过分号分隔命令
exec执行
RUN ["executable", "param1", "param2"]
RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定–no-cache参数,如:docker build --no-cache
。
5. CMD
CMD用于指定在容器启动时所要执行的命令。CMD有以下三种格式:
CMD ["executable","param1","param2"] CMD ["param1","param2"] CMD command param1 param2
CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。
CMD与RUN在功能实现上也有相似之处。如:
docker run -t -i ghostwritten/web_server /bin/true
等价于:
cmd ["/bin/true"]
- CMD在Dockerfile文件中仅可指定一次,指定多次时,会覆盖前的指令。
- docker run命令也会覆盖Dockerfile中CMD命令。
6. ENTRYPOINT
ENTRYPOINT用于给容器配置一个可执行程序。也就是说,每次使用镜像创建容器时,通过ENTRYPOINT指定的程序都会被设置为默认程序。ENTRYPOINT有以下两种形式:
ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2
ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖
ENTRYPOINT
docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。
Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。
docker run运行容器时指定的参数都会被传递给ENTRYPOINT
,且会覆盖CMD命令指定的参数。如,执行docker run <image> -d
时,-d参数将被传递给入口点。
也可以通过docker run --entrypoint
重写ENTRYPOINT入口点。
示例:
ENTRYPOINT ["/usr/bin/nginx"]
Dockerfile
FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y nginx RUN echo 'Hello World, 我是个容器' > /var/www/html/index.html EXPOSE 80 ENTRYPOINT ["/usr/sbin/nginx"]
构建
docker build -t="ghostwritten/app" .
创建容器
docker run -i -t ghostwritten/app -g "daemon off;"
-g "daemon off;"
参数将会被传递给ENTRYPOINT
,最终在容器中执行的命令为/usr/sbin/nginx -g "daemon off;"
。
7. LABEL
LABEL用于为镜像添加元数据,元数以键值对的形式指定:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。
LABEL version="1.0" description="这是一个Web服务器" by="ghostwritten"
也可以换行
LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3"
docker inspect查看:
$ docker inspect itbilu/test "Labels": { "version": "1.0", "description": "这是一个Web服务器", "by": "ghostwritten" },
注意:Dockerfile中还有个MAINTAINER
命令,该命令用于指定镜像作者。但MAINTAINER并不推荐使用,更推荐使用LABEL来指定镜像作者。如:
LABEL maintainer="ghostwritten"
8. EXPOSE
EXPOSE用于指定容器在运行时监听的端口:
EXPOSE <port> [<port>...]