浅言碎语
Dockerfile 基本结构
Dockerfile 一般分为四个部分
- 基础镜像信息
- 维护者信息
- 镜像操作指令
- 容器启动时执行的命令
Dockerfile 指令
FROM
指定基础镜像(必须指定,否则 Dockerfile 无效)
语法格式:
FROM <镜像名称>:<镜像tag> [AS <阶段名称>]
FROM centos
FROM centos:7
ARG
定义 Dockerfile 构建时的变量
语法格式:
ARG <变量名称>=<变量值>
ARG os_version
ARG os_version=7
ARG 指令生效范围
FROM
之前的 ARG
对当前 Dockerfile 内的所有 FROM
生效,但对于 FROM
后的构建不生效一个用来验证的 Dockerfile 模板
ARG os_version=7
FROM centos:${os_version} AS arg_test1
RUN echo "${os_version}" > /tmp/arg_test.log
FROM centos:${os_version} AS arg_test2
CMD echo "This is a test."
证明 FROM 之前的 ARG 对 FROM 后的构建不生效
先构建 arg_test1
,
docker build -t arg_test:1 --target arg_test1 .
Downloaded newer image for centos:7
可以看出,FROM
之前的 ARG
,针对 FROM
是生效的,拉取的镜像的确是 centos:7
eeb6ee3f44bd
是 centos:7
镜像的id
Sending build context to Docker daemon 18.6MB
Step 1/3 : ARG os_version=7
Step 2/3 : FROM centos:${os_version} AS arg_test1
7: Pulling from library/centos
2d473b07cdd5: Already exists
Digest: sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987
Status: Downloaded newer image for centos:7
---> eeb6ee3f44bd
Step 3/3 : RUN echo "${os_version}" > /tmp/arg_test.log
---> Running in 74b009ce6878
Removing intermediate container 74b009ce6878
---> 59846e43cd35
Successfully built 59846e43cd35
Successfully tagged arg_test:1
进入容器查看文件内容,我们会发现文件是空的
docker run -it arg_test:1 bash
cat tmp/arg_test.log
证明 FROM 之前的 ARG 对当前 Dockerfile 内所有 FROM 都生效
还是沿用上面的 Dockerfile 文件
docker build -t arg_test:2 --target arg_test2 .
从第二层的 FROM 可以看出,没有再次去拉取镜像,eeb6ee3f44bd
使用的是这个 id 的镜像,咱们上面也可以看到,就是第一次构建的时候拉取的 cetnos:7
镜像
Sending build context to Docker daemon 18.6MB
Step 1/5 : ARG os_version=7
Step 2/5 : FROM centos:${os_version} AS arg_test1
---> eeb6ee3f44bd
Step 3/5 : RUN echo "${os_version}" > /tmp/arg_test.log
---> Running in 09636e8db1d9
Removing intermediate container 09636e8db1d9
---> 8db76f18804d
Step 4/5 : FROM centos:${os_version} AS arg_test2
---> eeb6ee3f44bd
Step 5/5 : CMD sleep
---> Running in 9f4697b3300f
Removing intermediate container 9f4697b3300f
---> d7361aff5854
Successfully built d7361aff5854
Successfully tagged arg_test:2
如何让 FROM 之前的 ARG 在 FROM 后的构建生效
只需要在 FROM
后面,使用 ARG <变量名称>
来再次引用即可
ARG os_version=7
FROM centos:${os_version}
ARG os_version
RUN echo "${os_version}" > /tmp/arg_test.log
docker build -t arg_test:3 .
进入容器查看文件内容,我们会发现文件里面会有 ARG
定义的变量值
docker run -it arg_test:3 bash
cat tmp/arg_test.log
MAINTAINER(官方已弃用)
功能描述,官方建议使用 LABEL
语法格式:
MAINTAINER <name>
MAINTAINER chen2ha
LABEL
功能描述,以键值对的形式,将元数据添加到镜像种语法格式:
LABEL <key>=<value> <key>=<value> <key>=<value> ......
多个标签以空格隔开
LABEL maintainer="chen2ha" today="2022-05" say="hello"
也可以使用这种方式
LABEL maintainer="chen2ha" \
today="2022-05" \
say="hello"
查看镜像 LABEL
信息
docker image inspect --format='' <镜像名称>
ENV
设置环境变量语法格式:
ENV <key> <value>
# <key>
之后的所有内容均会被视为其 <value>
的组成部分,因此,一次只能设置一个变量
ENV <key>=<value>
ENV JAVA_HOEE=/usr/local/jdk1.8.0_231
ENV PATH=${PATH}:${JAVA_HOME}/bin
USER
指定容器运行的用户和组
语法格式:
USER <用户名>[:<组名>]
USER <uid>[:<gid>]
USER www
WORKDIR
指定工作目录
语法格式:
WORKDIR <绝对路径>
ARG deploy_path=/opt/
WORKDIR ${deploy_path}
RUN
在镜像当前层执行指定的命令
语法格式:
RUN <shell 命令>
# shell 的格式
RUN ["<可执行文件>","参数1","参数2"]
# exec 的格式
- exec 会被解析成 json 数组,必须使用
RUN ["<可执行文件>","参数1"]
的格式 - exec 不会发生正常的 shell 处理,比如
RUN ["echo","$USER"]
,不会像 shell 一样将 $USER
替换成变量值
FROM centos:7
RUN yum install -y \
gcc \
gcc-c++
写 RUN 的一些小细节
相似的操作两次 RUN 和一次 RUN 的区别
FROM centos:7
RUN yum install -y vim
RUN yum install -y wget
构建完成后,使用 docker images
命令查看镜像大小,我这边构建完成后的大小是 591MB
docker build -t centos:2_run .
docker images | grep 2_run
FROM centos:7
RUN yum install -y \
vim \
wget
构建完成后,使用 docker images
命令查看镜像大小,我这边构建完成后的大小是 425MB
docker build -t centos:1_run .
docker images | grep 1_run
FROM centos:7
RUN yum install -y \
vim \
wget && \
yum clean all
构建完成后,使用 docker images
命令查看镜像大小,我这边构建完成后的大小是 284MB
docker build -t centos:1_run_clean .
docker images | grep run_clean
- 可以看出,
都是 yum 操作
,写两次 RUN
和一次 RUN
,镜像大小可以相差 174MB
,如果一个 RUN
还加上 yum clean all 清除 yum 缓存
,镜像大小可以相差 307MB
COPY
复制文件到镜像内
语法格式:
COPY [--chown=<用户名>:<组名>] <源路径> <目标路径>
COPY xxx.sh /usr/local/src/
# 从其他镜像复制文件
COPY --from=quay.io/coreos/etcd:v3.3.9 /usr/local/bin/etcd /usr/local/bin/
从其他阶段复制文件(多阶段构建)
FROM centos:7 as build
# <此处省略构建过程>
FROM centos:7
COPY --from=build /build/build_server /build
ADD
复制文件到镜像内
语法格式:
ADD [--chown=<用户名>:<组名>] <源路径> <目标路径>
# 添加所有以"hom"开头的文件
ADD hom* /mydir/
# 添加 "test.tar.gz" 到 WORKDIR/relativeDir/
ADD test.tar.gz relativeDir/
EXPOSE
容器启动时监听的端口(默认 tcp 协议),可以指定为 udp 协议
语法格式:
EXPOSE <端口>/<协议>
- 仅仅只是申明,仍然需要
docker run -p
来映射端口,docker run -p <宿主机端口>:<容器内端口>/<协议>
可以覆盖容器内申明的协议
EXPOSE 80/tcp
EXPOSE 80/udp
CMD 和 ENTRYPOINT
容器启动时需要执行的命令ENTRYPOINT 语法格式:
ENTRYPOINT ["<可执行文件>","<参数1>","<参数2>"]
ENTRYPOINT ["<shell命令>","<参数1>","<参数2>"]
CMD 语法格式:
CMD ["<可执行文件>","<参数1>","<参数2>"]
CMD ["<shell命令>","<参数1>","<参数2>"]
CMD ["<参数1>","<参数2>"]
# 只有设置了 ENTRYPOINT
指令才可以使用这种方式
CMD
和 ENTRYPOINT
之间协作的规则
CMD
和 RUN
是有区别的
CMD
是容器运行的时候要执行的命令RUN
是容器构建的时候要执行的命令
全剧终