Dockerfile 语法

document: https://docs.docker.com/engine/reference/builder/

1. 通过Dockerfile构建镜像:

docker build .  # . 指定当前路径为构建时的上下文环境(build context), 会在该路径下寻找Dockerfile文件,构建镜像

# 可以通过 -t 参数指定镜像名字和tag
docker build -t sky/app .

# 可以通过-f参数指定Dockerfile的路径, 而不是从build context下找
docker build -f /path/to/a/Dockerfile .

# 可以同时创建多个镜像, 只需要用多个-t参数
docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .

2. Dockerfile的内容:

0. ARG:

ARG是唯一一个可以在FROM之前出现的指令, 用于定义变量, 该变量可以给后续所有构建阶段的FROM指令使用:

在FROM之前定义的ARG是不属于任何构建阶段的, 所以不能被构建阶段内除FROM之外的指令访问.

该指令定义一个变量或者提供变量的默认值,在构建时可以通过--build-arg <varname>=<value>来指定变量的值

ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app

FROM extras:${CODE_VERSION}
CMD  /code/run-extras

如果要在构建阶段内部(非FROM指令)使用ARG定义的变量的值, 需要在构建阶段内部定义一个ARG指令, 这样就可以使用其默认值了

ARG VERSION=latest  # 为变量提供默认值
FROM busybox:${VERSION}
ARG VERSION
RUN echo ${VERSION} > image_version

ENV定义的环境变量可以覆盖ARG定义的变量

FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=v1.0.0
RUN echo $CONT_IMG_VER

1. FROM:

FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
  • 每个FROM指令都会初始化一个新的构建阶段(build stage). 并且为该阶段后续指令设置一个基础镜像.
  • 一个镜像中可以存在多个构建阶段, 构建阶段中的部分指令可以引用前面阶段的内容. 引用方式就是设置一个别名: AS <name>

2. RUN:

  • RUN <COMMAND>: 会被当做字符串传递给``/bin/sh -ccmd /S /C`
  • RUN ["executable", "param1", "param2"]:

RUN指令会在镜像的顶层开辟一个新的层(layer), 并在其中执行指令, 执行结果会被提交到新创建的层中, 因此结果可被后续步骤使用.

RUN /bin/bash -c 'source $HOME/.bashrc; \   
	echo $HOME'  # 通过 \ 来换行

由于一个RUN指令就会创建一个layer, 为了让镜像尽可能小, 应该尽可能减少RUN指令的个数

3. CMD:

CMD指令的唯一目的, 是为刚启动的容器提供一个默认的entrypoint(即启动容器时执行的命令).

如果启动容器时指定了entrypoint, 则CMD的指令会被覆盖

FROM ubuntu
CMD echo "This is a test." | wc -

4. LABEL:

LABEL指令的作用是为镜像提供更多描述信息…

这里只给例子:

LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
	that label-values can span multiple lines."
	
LABEL multi.label1="value1" multi.label2="value2" other="value3"

5. EXPOSE:

EXPOSE指令主要目的是暴露端口

可以指定暴露的监听端口是TCP还是UDP的, 在没指定的情况下默认是TCP

EXPOSE 80/udp

EXPOSE 80/tcp
EXPOSE 80/udp

但事实上, 在运行时, docker向外暴露的服务端口未必要是EXPOSE指定的, 因为docker run有-p参数, 可以指定端口映射, 因此可以在运行时动态改变:

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

6. ENV:

ENV指令为接下来的指令设置环境变量.

注意, 该环境变量在容器运行时还会持续保留

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

如果一个环境变量只需要在RUN指令执行阶段使用, 可以考虑这样写:

RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y ...

或者可以考虑使用ARG, 使用ARG设置的环境变量不会在容器运行时继续保持:

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y ...

7. ADD:

ADD [--chown=<user>:<group>] <src> <src2> ...  <dest>
ADD [--chown=<user>:<group>] ["<src>", ..., "<dest>"]
# 注意--chown 只支持linux容器构建过程中

ADD指令用于从复制文件、目录、远程文件URL, 并且将其添加到镜像的文件系统的目标路径: <dest>

# 路径支持简单正则匹配
ADD hom* /mydir/

ADD hom?.txt /mydir/  # ? 匹配单个字符

ADD arr[[0]].txt /mydir/  # 匹配arr[0].txt, 要对[ ]进行转义!
# --chown 可以用UID和GID 也可以用用户名和组名
# 如果只提供UID/用户名, 组名的GID将于用户名对应的UID一致
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/  # GID和UID一致
ADD --chown=1 files* /somedir/  # 1:1
ADD --chown=10:11 files* /somedir/

当没有指定build context时, 只能是文件的URL路径:

docker build - < somefile # 从标准输入中读取文件内容进行构建

**使用ADD**时必须遵循以下规则:

  1. 路径必须在build context内部. ADD ../something /some 是不允许的

  2. 如果是一个URL且尾部没有反斜线, 则从URL下载的文件直接复制到

  3. 如果是一个URL且尾部有个反斜线, 则从URL下载的文件会复制到<dest>/

  4. 如果是一个文件夹, 那么整个文件夹的内容都会复制(包括文件系统的元信息)

  5. 如果是一个本地的压缩包(tar, gzip, bzip2, xz), 那么将自动解压为一个目录, 从URL下载的压缩包不会自动解压.

  6. 如果有多个源路径或者使用了通配符, 则必须是一个路径且尾部带有反斜线

  7. 如果尾部没有反斜线会被认为是一个文件, 中的文件内容将对进行重写

  8. 如果不存在, 将会递归的创建目录

8. COPY:

COPY的通常用法:

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

似乎与ADD没啥区别, 但是COPY指令能够接受一个参数: --from=<name>. 可以从先前的build stage中复制文件(FROM ... AS <NAME>)

当指定 --from=<name>时, 就变成了先前 build stage 环境中的文件路径了!

有时可能需要在前面的build stage中编译一个东西, 要到随后若干个build stage之后才能用到, --from 参数就起到了这个作用

9. ENTRYPOINT

  1. exec form:
ENTRYPOINT ["executable", "param1", "param2"]

exec形式下, docker run 最后的额外参数将作为命令行参数附加到exectuable的参数列表后面, CMD指令将无效. 想重写该ENTRYPOINT需要通过docker run --entrypoint进行

  1. shellform:
ENTRYPOINT command padram1 param2

shell形式的entrypoint将直接覆盖CMD以及docker run的额外参数, 但是以此方式执行的指令无法接受到任何SIGNAL(即无法被KILL), 因此并不十分推荐

10. VOLUME

VOLUME 指令用于创建一个挂载点, 注意只是挂载点, 构建镜像过程中并不会挂载任何主机上的路径

挂载到挂载点的主机目录是容器运行时声明的: 通过 -v host_dir:container_dir 进行映射

VOLUME ["/data", "/data1"]
VOLUME /myvol
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

11. USER

USER <user>[:<group>]

USER <UID>[:<GID>]

USER指令用来设置执行 RUN`CMD\ENTRYPOINT` 指令的用户和所属组

12. WORKDIR

WORKDIR /path/to/workdir

这个应该不必多说…

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

The output of the final pwd command in this Dockerfile would be /a/b/c.

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fanqiliang630

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值