在 Docker 中,可以通过 docker build 命令和 Dockerfile 文件来构造自己的 Docker 镜像。
值得注意的是,docker build 命令会递归地将构建整个上下文(如,通常是某个本地目录)发送给 docker daemon,所以不要将根目录 / 作为构建上下文。
1. 常用指令需要注意的是,只有 RUN, COPY, ADD 指令会创建新的层。
FROMFROM 指令用于初始化一个新的构建阶段,并为后续指令指定一个基础镜像。
FROM [--platform=] [: ] [AS ]
如果基础镜像有多个平台版本,可以通过 --platform 来指定要使用哪个版本,如,linux/amd64。
可以通过 AS
如,
FROM busyboxLABEL
LABEL 指令用于为镜像添加元数据,可以通过 docker image inspect 命令来查看。
LABEL= = = ...
如,
LABEL "com.example.vendor"="ACME Incorporated" LABEL com.example.label-with-value="foo" LABEL description="This text illustrates that label-values can span multiple lines."ENV
ENV 指令用于设置环境变量,其设置的环境变量可以被后续指令,且会持久地存储,容器运行时依旧存在;可以被 docker run 命令覆盖。
ENV= ...
如,
ENV DIRPATH=/path WORKDIR $DIRPATH/aARG
ARG 指令用于定义变量,用户可以在构造镜像是传递相应的变量值。不同于 ENV,ARG 不会将变量持久化至容器运行时。
ARG[= ]
如,
FROM ubuntu ARG CONT_IMG_VER RUN echo $CONT_IMG_VER
$ sudo docker build --build-arg CONT_IMG_VER=2.3 .WORKDIR
WORKDIR 指令用于为后续的 RUN, CMD, ENTRYPOINT, ADD, COPY 指令指定工作路径。如果后面的 WORKDIR 指令的参数是一个相对路径,则它是相对于上一个 WORKDIR 指令指定的工作路径的。
WORKDIR /path/to/workdir
如,
WORKDIR /a WORKDIR b WORKDIR cRUN
RUN 指令会在当前镜像之上执行给定的命令,并将执行结果作为一个新的层。
RUNRUN ["executable", "param1", "param2", ...]
- 第一种形式是在 shell 中执行命令,也就是说基础镜像需要包含指定的 shell 才行;
- 第二种形式是 exec 形式,不会调用 shell(也就不会执行环境变量替换),可以执行任意可执行文件,其参数会被解析成 JSON 数组,所以需要使用双引号!
如,
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME' RUN ["/bin/bash", "-c", "echo hello"]ADD
ADD 指令用于拷贝本地文件、目录、远程文件至镜像中。
ADD [--chown=[: ]] ... ADD [--chown= [: ]] [" ",... " "]
文件的默认属主/属组为 root,可以通过 --chown 来修改。
一些注意事项:
必须在构建上下文中; - 如果
是一个本地 tar 文件(被压缩为 gzip、bzip2、xz),则它会被解包为一个目录;
如,
ADD --chown=55:mygroup files* /somedir/ ADD --chown=bin files* /somedir/ ADD --chown=1 files* /somedir/ ADD --chown=10:11 files* /somedir/COPY
和 ADD 指令类似,但不支持从远程拷贝文件,此外它也不会自动解包 tar 文件。
COPY [--chown=[: ]] ... COPY [--chown= [: ]] [" ",... " "]
如,
COPY --chown=55:mygroup files* /somedir/ COPY --chown=bin files* /somedir/ COPY --chown=1 files* /somedir/ COPY --chown=10:11 files* /somedir/VOLUME
VOLUME 指令用于将容器中指定的目录挂载为匿名卷,可以通过 docker inspect 命令来查看其挂载到了主机哪个位置。
VOLUME path VOLUME ["path1", "path2", ...]
如,
VOLUME ["/data1","/data2"]EXPOSE
EXPOSE 指令用于指明容器应当在运行时监听指定的端口,而实际上,EXPOSE 指令并没有开放端口的功能,这需要通过 docker run 命令的 -p 选项来实现。
EXPOSE[/protocol] [ [/ ]...]
如,
EXPOSE 80/tcp EXPOSE 80/udp
$ sudo docker run -p 80:80/tcp -p 80:80/udp ...CMD
CMD 指令有3种形式,前两种和 RUN 指令类似,但不同于 RUN,CMD 指令指定的命令是在容器运行时执行的(和 ENTRYPOINT 指令功能相同),而不是构建容器时;第三种形式的作用是给 ENTRYPOINT 指令提供默认参数(可以被 docker run 命令指定的参数给覆盖掉)。
CMD command param1 param2 ... CMD ["executable", "param1", "param2", ...] CMD ["param1","param2", ...]
如,
FROM ubuntu CMD echo "This is a test." | wc - FROM ubuntu CMD ["/usr/bin/wc", "--help"]ENTRYPOINT
ENTRYPOINT 指令用于指定容器启动(执行 docker run
ENTRYPOINT command param1 param2 ... ENTRYPOINT ["executable", "param1", "param2", ...]
当使用 shell 形式时,需要以 exec 开始,以保证 docker stop 命令能够正确地终止容器。
如,
FROM ubuntu ENTRYPOINT ["top", "-b"] CMD ["-c"] FROM ubuntu ENTRYPOINT exec top -b2. 多阶段构建
多阶段构建可以有效地减小镜像的大小。它是通过为每个构建阶段提供一个名字,并结合 COPY --from=
如,
FROM golang:1.16-alpine AS build RUN apk add --no-cache git RUN go get github.com/golang/dep/cmd/dep COPY Gopkg.lock Gopkg.toml /go/src/project/ WORKDIR /go/src/project/ RUN dep ensure -vendor-only COPY . /go/src/project/ RUN go build -o /bin/project FROM scratch COPY --from=build /bin/project /bin/project ENTRYPOINT ["/bin/project"] CMD ["--help"]3. 构建镜像
默认情况下,docker build 使用构建上下文中的 Dockerfile 文件来构建镜像:
$ sudo docker build .
当然也可以通过 -f 选项来自定义 Dockerfile 文件:
$ sudo build -f /path/to/a/Dockerfile .
此外,也可以通过 -t 选项为生成的镜像打上(一个或多个)标签:
$ sudo docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
最后,可以在构建上下文中添加 .dockerignore 文件来排除掉与构建无关的文件,格式类似于 .gitignore 文件。



