Dokerfile编写

Dokerfile编写

ARG指令与CMD

FROM alpine

LABEL  maintainer="test dockerfile"

# 定义以后剩下环节能生效
# 可以在构建时进行编号
ARG param=12345 

# 构建时期我们会运行的指令
RUN echo 11113;echo $param

# 运行时期我们会运行的指令(根据之前创建的镜像启动的一个容器,容器启动默认运行的命令)
# docker run/docker start 
# CMD 和	ENTRYPOINT 都是指定运行时命令
CMD echo 111

ARG

ARG是Dockerfile中唯一可以在FROM之前的指令。

ARG 不像ENV不能并排写。

FROM

  1. FROM指令初始化新的构建阶段,并为后续指令设置Base Image。因此,有效的Dockerfile必须以FROM指令开头
  2. 可选地,可以通过向FROM指令添加AS名称来为新的构建阶段指定名称。该名称可以在随后的FROM和COPY-FROM=指令中使用,以引用在此阶段中构建的映像。
  3. FROM可以在一个Dockerfile中多次出现,以创建多个映像或将一个构建阶段用作另一个构建的依赖项。只需在每个新的FROM指令之前记录提交输出的最后一个图像ID。每个FROM指令都会清除先前指令创建的任何状态。

RUN

RUN有两种形式:

  • RUN(shell形式,命令在shell中运行,在Linux上默认为/bin/sh-c,在Windows上默认为cmd/S/c)

  • RUN[“executable”,“param1”,“param2”](exec形式)

RUN /bin/bash -c 'source $HOME/.bashrc && \
echo $HOME'

要使用除“/bin/sh”之外的其他shell,请使用传入所需shell的exec表单。例如:
# -c 指后面的命令为完全命令
# run 指令没有上下文关系
RUN ["/bin/bash", "-c", "echo hello"] 

ENV

定义环境变量

ENV <key>=<value> ...

ENV指令将环境变量设置为值。该值将在构建阶段的所有后续指令的环境中,也可以在许多指令中内联替换。该值将被解释为其他环境变量,因此引号字符如果不转义,将被删除。与命令行解析一样,引号和反斜杠可以用于在值中包含空格。

Example:

ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy

ENV指令允许多个=。。。变量,下面的示例将在最终图像中产生相同的净结果:

Example:

ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \
    MY_CAT=fluffy

当从结果图像运行容器时,使用ENV设置的环境变量将保持不变。您可以使用docker inspect查看值,并使用docker run --env =更改它们。

docker run --env <key>=<value>

ADD 和 COPY

ADD

ADD有两种形式:

ADD [--chown=<user>:<group>] [--checksum=<checksum>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
  • ADD指令从复制新文件、目录或远程文件URL,并将它们添加到路径处的映像文件系统中。

  • 可以指定多个<src>资源,但如果它们是文件或目录,则它们的路径将被解释为相对于构建上下文的源。 每个<src>都可能包含通配符,匹配将使用Go的文件路径.Match规则完成。例如: 要添加以“hom”开头的所有文件:

    ADD hom* /mydir/
    

ADD遵守以下规则:

  • 路径必须位于构建的上下文中;无法添加/something/something,因为docker构建的第一步是将上下文目录(和子目录)发送到docker守护进程。
  • 如果<src>是一个URL,而<dest>不以斜杠结尾,则会从该URL下载一个文件并将其复制到<dest>。
  • 如果<src>是一个URL,而<dest>以斜杠结尾,则从URL推断出文件名,并将文件下载到<dest>/<filename>。例如,ADDhttp://example.com/foobar/将创建文件/foobar。URL必须具有非平凡路径,以便在这种情况下可以找到适当的文件名(http://example.com不会工作)。
  • 如果<src>是一个目录,则复制目录的全部内容,包括文件系统元数据。
  • 添加压缩包会自动解压。

COPY

注意复制的文件有没有执行权限。把复制过来的文件给所有权

COPY --chown=<user>:<group>

用法与ADD基本一致,COPY 不会自动解压和下载。

USER

以后的所有命令会用这个用户执行,有可能没有执行权限

USER指令设置用户名(或UID)和可选的用户组(或GID),以用作当前阶段剩余时间的默认用户和组。指定的用户用于RUN指令,并在运行时运行相关的ENTRYPOINT和CMD命令。

USER redis:redis 

WORKDIR

为以下所有的命令运行指定了基础目录。

多个workdir 可以嵌套

WORKDIR /ABC
WORKDIR ACD

目录为 /ABC/ACD

VOLUME

VOLUME指令使用指定的名称创建装载点,并将其标记为保存来自本机主机或其他容器的外部装载卷。该值可以是JSON数组 VOLUME [“/var/log/”],也可以是具有多个参数的纯字符串,例如VOLUME /var/log或 VOLUME /var/log/var/db。有关通过Docker客户端的更多信息/示例和安装说明,请参阅通过卷共享目录文档。 docker run命令使用存在于基本映像中指定位置的任何数据初始化新创建的卷。例如,考虑以下Dockerfile片段:

FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

## 挂载容器指定文件夹,如果不存在则创建
## 指定了VOLUME,即使启动容器没有指定-v 参数,我们也会自动进行卷挂载。

EXPOSE

EXPOSE指令通知Docker容器在运行时侦听指定的网络端口。您可以指定端口侦听TCP还是UDP,如果未指定协议,则默认为TCP。 EXPOSE指令实际上并不发布端口。它作为构建映像的人和运行容器的人之间的一种文档,用于发布哪些端口。要在运行容器时实际发布端口,请在docker run上使用-p标志发布并映射一个或多个端口,或使用-p标志发布所有公开的端口并将它们映射到高阶端口。 默认情况下,EXPOSE采用TCP。也可以指定UDP:

EXPOSE 80/tcp

无论EXPOSE设置如何,您都可以在运行时使用-p标志覆盖它们。例如

docker run -p 80:80/tcp -p 80:80/udp ...

CMD 和ENTRYPOINT

ENTRYPOINT

ENTRYPOINT是真正的入口,CMD为ENTRYPOINT提供参数。


ENTRYPOINT "ping"
# 指令有多种方式,官方建议用exec方式[]方式
CMD www.baidu.com
CMD ["bin/sh""-c""ping""www.baidu.com"]

ENTRYPOINT "ping"
CMD ["bin/sh","-c","www.baidu.com"]

下表显示了对不同ENTRYPOINT/CMD组合执行的命令:

No ENTRYPOINTENTRYPOINT exec_entry p1_entryENTRYPOINT [“exec_entry”, “p1_entry”]
No CMDerror, not allowed/bin/sh -c exec_entry p1_entryexec_entry p1_entry
CMD [“exec_cmd”, “p1_cmd”]exec_cmd p1_cmd/bin/sh -c exec_entry p1_entryexec_entry p1_entry exec_cmd p1_cmd
CMD exec_cmd p1_cmd/bin/sh -c exec_cmd p1_cmd/bin/sh -c exec_entry p1_entryexec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

多阶段构建

Docker 17.05版本以后,官方就提供了一个新的特性:Multi-stage builds(多阶段构建)。
使用多阶段构建,你可以在一个 Dockerfile 中使用多个 FROM 语句。每个 FROM 指令都可以使用不同的基础镜像,并表示开始一个新的构建阶段。你可以很方便的将一个阶段的文件复制到另外一个阶段,在最终的镜像中保留下你需要的内容即可。

多阶段构建之前

构建映像最具挑战性的事情之一是保留映像 缩小尺寸。Dockerfile 中的每个、 和 指令都会向映像添加一个图层,然后您 在继续之前,需要记住清理任何不需要的工件 下一层。要编写一个真正高效的 Dockerfile,您传统上必须 需要使用 shell 技巧和其他逻辑来保持层尽可能小 可能并确保每一层都有它需要的工件 前一层,仅此而已。RUN``COPY``ADD

实际上,有一个 Dockerfile 用于开发是很常见的(这 包含构建应用程序所需的一切),并且精简了一个 用于生产,其中仅包含您的应用程序以及确切的内容 需要运行它。这被称为“建设者 模式”。维护两个 Dockerfile 并不理想。

下面是一个示例,它遵循 上面的生成器模式:build.Dockerfile``Dockerfile

build.Dockerfile:

# syntax=docker/dockerfile:1
FROM golang:1.16
WORKDIR /go/src/github.com/alexellis/href-counter/
COPY app.go ./
RUN go get -d -v golang.org/x/net/html \
  && CGO_ENABLED=0 go build -a -installsuffix cgo -o app .

请注意,此示例还人为地将两个命令压缩在一起 使用 Bash 运算符,以避免在图像中创建额外的图层。 这容易出现故障且难以维护。插入另一个命令很容易 例如,忘记使用字符继续行。RUN``&&``\

Dockerfile:

# syntax=docker/dockerfile:1
FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app ./
CMD ["./app"]

build.sh:

#!/bin/sh
echo Building alexellis2/href-counter:build
docker build -t alexellis2/href-counter:build . -f build.Dockerfile

docker container create --name extract alexellis2/href-counter:build  
docker container cp extract:/go/src/github.com/alexellis/href-counter/app ./app  
docker container rm -f extract

echo Building alexellis2/href-counter:latest
docker build --no-cache -t alexellis2/href-counter:latest .
rm ./app

运行脚本时,它需要构建第一个映像,创建 一个容器,用于从中复制工件,然后构建第二个 图像。这两个映像都会占用系统上的空间,并且本地磁盘上仍有工件。build.sh``app

多阶段构建大大简化了这种情况!

使用多阶段构建

多阶段构建 (docker.com)

对于多阶段构建,您可以在 Dockerfile 中使用多个语句。 每条指令都可以使用不同的基数,并且每条指令都开始一个新的 构建阶段。您可以有选择地将项目从一个阶段复制到 另一个,在最终图像中留下你不想要的一切。要显示 这是如何工作的,让我们调整上一节的使用 多阶段构建。FROM``FROM``Dockerfile

# syntax=docker/dockerfile:1

FROM golang:1.16
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go ./
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app ./
CMD ["./app"]

您只需要单个 Dockerfile。您不需要单独的构建脚本, 也。只需运行.docker build

$ docker build -t alexellis2/href-counter:latest .

最终结果是与以前相同的微小生产映像,具有 显著降低复杂性。您无需创建任何中间体 图像,并且您根本不需要将任何工件提取到本地系统。

它是如何工作的?第二条指令开始一个新的构建阶段 图像作为其基础。该行仅复制 将神器从前一阶段构建到这个新阶段。Go SDK 和任何 中间伪影会留下,不会保存在最终图像中。FROM``alpine:latest``COPY --from=0

命名构建阶段

默认情况下,阶段不命名,您可以通过其整数引用它们 数字,以 0 开头表示第一条指令。但是,您可以 通过在指令中添加 A 来命名阶段。这 示例通过命名阶段并使用 指令。这意味着即使您的说明 Dockerfile 稍后重新排序,不会中断。FROM``AS <NAME>``FROM``COPY``COPY

# syntax=docker/dockerfile:1

FROM golang:1.16 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go ./
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app ./
CMD ["./app"]  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值