docker commit命令虽然可以很方便的创建新的镜像,但是我们在容器内操作(特别是尝试性的操作)可能会在新镜像内产生无关的内容,如命令历史和日志等。
Dockerfile是控制镜像构建过程的脚本,使用Dockerfile可以有效避免镜像中包含无关内容。
Dockerfile中包含多行指令,每个指令会在镜像中创建一层。
FROM nginx RUN echo '<h1>Hello from finley!</h1>' > /usr/share/nginx/html/index.html
$ docker build -t nginx_hello . Step 1/2 : FROM nginx ---> 3f8a4339aadd Step 2/2 : RUN echo '<h1>Hello from finley!</h1>' > /usr/share/nginx/html/index.html ---> Running in 2b3c5df09f9c ---> a918263d0f2f Removing intermediate container 2b3c5df09f9c Successfully built a918263d0f2f Successfully tagged nginx_hello:latest $ docker run --name nginx_hello -p 80:80 -d --rm nginx_hello $ curl localhost <h1>Hello from finley!</h1>上面示例中我们以nginx为基础构建了一个新镜像,并启动它提供服务。
在具体介绍Dockerfile的指令之前,我们先介绍一下docker build命令。
docker build指令用于根据Dockerfile构建镜像,通常该指令需要一个PATH参数来指定某个目录做为构建上下文(context)。
-f或--file选项用于在构建上下文指定Dockerfile文件的路径, 默认为PATH/Dockerfile。
-t或--tag选项用于为镜像指定标签,默认情况下名称仍然与基础镜像相同, 而-t NAME:TAG则会指定容器的名称。
除了使用一个目录作为构建上下文之外,也可以使用tar压缩包、git仓库作为上下文, 甚至从标准输入中读取Dockerfile或tar进行构建。
接下来介绍常用的Dockerfile命令:
FROM
FROM指令用于指定构建容器的基础镜像,标记镜像的语法与docker pull命令相同。
除了使用已存在的镜像作为基础镜像之外还有一个特殊的镜像scratch, 它是一个空镜像。
我们可以把静态编译的可执行文件放入空白镜像中,由内核直接执行可以极大的降低镜像的体积。
RUN
RUN命令在镜像中创建一个容器并执行指定指令,执行结束后commit修改作为镜像的一层。
上文示例中的Step2展示了RUN指令运行的过程:
创建一个中间容器(intermediate container): 2b3c5df09f9c
运行命令echo '<h1>Hello from finley!</h1>' > /usr/share/nginx/html/index.html
将修改提交,产生新的容器: a918263d0f2f
删除中间容器:2b3c5df09f9c
RUN命令有两种参数格式:
命令行式: RUN ls -al
函数调用式: RUN ["ls", "-al"]
在实际执行过程中命令行式指令会被映射为RUN ["sh", "-c", "ls", "-al"]。
因为每个RUN指令都会生成一层镜像, 因此最好用&&将多条指令连接而不是写多条RUN指令。
COPY
COPY from to指令将文件或目录从构建上下文(context)将文件复制到镜像内部。
COPY ./config.json /root/config.json
WORKDIR
WORKDIR path命令用于指定容器的默认工作目录。
WORKDIR命令对Dockerfile中的后续命令都有影响, 除非有另一条WORKDIR命令修改了工作目录
上文已经介绍过每条RUN指令都会创建一个临时容器, 因此RUN cd PATH &&...只对同一条RUN中的后续指令有效。
USER
USER命令用于指定容器中的当前用户:
RUN groupadd -r redis && useradd -r -g redis redis USER redis RUN redis-server
和WORKDIR命令一样,USER指令直到下一条USER指令之前始终有效。
CMD
CMD命令用于指定启动容器的指令, 和RUN命令一样有两种格式。
EXPOSE
EXPOSE命令用于声明需要暴露哪些接口,注意EXPOSE命令没有建立端口映射, 需要在创建容器时启动端口映射。
ENV
ENV命令用于为容器设置环境变量:
ENV DEBUG=on VERSION='1.0'
ENTRYPOINT
ENTRYPOINT指令和CMD一样,用于指定启动容器的指令。 当指定了ENTRYPOINT之后,CMD命令的内容将被作为参数传递给ENTRYPOINT指定的指令。
首先创建一个容器:
FROM ubuntu CMD ls
$ docker build -t ls:v1 . $ docker run --rm ls:v1 bin boot dev etc home lib ...