From cbaa24c48f0a41e4adaec7c128ccde6d1ba99cc4 Mon Sep 17 00:00:00 2001 From: Kang Huaishuai Date: Sun, 6 Sep 2020 20:16:04 +0800 Subject: [PATCH] Dockerfile add shell label Signed-off-by: Kang Huaishuai --- .vuepress/config.js | 2 ++ SUMMARY.md | 2 ++ image/dockerfile/arg.md | 59 +++++++++++++++++++++++++++++++++++++ image/dockerfile/label.md | 17 +++++++++++ image/dockerfile/shell.md | 33 +++++++++++++++++++++ image/dockerfile/workdir.md | 18 +++++++++++ 6 files changed, 131 insertions(+) create mode 100644 image/dockerfile/label.md create mode 100644 image/dockerfile/shell.md diff --git a/.vuepress/config.js b/.vuepress/config.js index cc2ef1d..876a244 100644 --- a/.vuepress/config.js +++ b/.vuepress/config.js @@ -233,6 +233,8 @@ module.exports = { 'image/dockerfile/workdir', 'image/dockerfile/user', 'image/dockerfile/healthcheck', + 'image/dockerfile/label', + 'image/dockerfile/shell', 'image/dockerfile/onbuild', 'image/dockerfile/references', 'image/multistage-builds/', diff --git a/SUMMARY.md b/SUMMARY.md index db95cf3..2ba58f0 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -41,6 +41,8 @@ * [USER 指定当前用户](image/dockerfile/user.md) * [HEALTHCHECK 健康检查](image/dockerfile/healthcheck.md) * [ONBUILD 为他人作嫁衣裳](image/dockerfile/onbuild.md) + * [LABEL 为镜像添加元数据](image/dockerfile/label.md) + * [SHELL 指令](image/dockerfile/shell.md) * [参考文档](image/dockerfile/references.md) * [Dockerfile 多阶段构建](image/multistage-builds/README.md) * [实战多阶段构建 Laravel 镜像](image/multistage-builds/laravel.md) diff --git a/image/dockerfile/arg.md b/image/dockerfile/arg.md index fb7be3d..d4b2708 100644 --- a/image/dockerfile/arg.md +++ b/image/dockerfile/arg.md @@ -7,3 +7,62 @@ `Dockerfile` 中的 `ARG` 指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令 `docker build` 中用 `--build-arg <参数名>=<值>` 来覆盖。 在 1.13 之前的版本,要求 `--build-arg` 中的参数名,必须在 `Dockerfile` 中用 `ARG` 定义过了,换句话说,就是 `--build-arg` 指定的参数,必须在 `Dockerfile` 中使用了。如果对应参数没有被使用,则会报错退出构建。从 1.13 开始,这种严格的限制被放开,不再报错退出,而是显示警告信息,并继续构建。这对于使用 CI 系统,用同样的构建流程构建不同的 `Dockerfile` 的时候比较有帮助,避免构建命令必须根据每个 Dockerfile 的内容修改。 + +ARG 指令有生效范围,如果在 `FROM` 指令之前指定,那么只能用于 `FROM` 指令中。 + +```docker +ARG DOCKER_USERNAME=library + +FROM ${DOCKER_USERNAME}/alpine + +RUN set -x ; echo ${DOCKER_USERNAME} +``` + +使用上述 Dockerfile 会发现无法输出 `${DOCKER_USERNAME}` 变量的值,要想正常输出,你必须在 `FROM` 之后再次指定 `ARG` + +```docker +# 只在 FROM 中生效 +ARG DOCKER_USERNAME=library + +FROM ${DOCKER_USERNAME}/alpine + +# 要想在 FROM 之后使用,必须再次指定 +ARG DOCKER_USERNAME=library + +RUN set -x ; echo ${DOCKER_USERNAME} +``` + +对于多阶段构建,尤其要注意这个问题 + +```docker +# 这个变量在每个 FROM 中都生效 +ARG DOCKER_USERNAME=library + +FROM ${DOCKER_USERNAME}/alpine + +RUN set -x ; echo 1 + +FROM ${DOCKER_USERNAME}/alpine + +RUN set -x ; echo 2 +``` + +对于上述 Dockerfile 两个 `FROM` 指令都可以使用 `${DOCKER_USERNAME}`,对于在各个阶段中使用的变量都必须在每个阶段分别指定: + +```docker +ARG DOCKER_USERNAME=library + +FROM ${DOCKER_USERNAME}/alpine + +# 在FROM 之后使用变量,必须在每个阶段分别指定 +ARG DOCKER_USERNAME=library + +RUN set -x ; echo ${DOCKER_USERNAME} + +FROM ${DOCKER_USERNAME}/alpine + +# 在FROM 之后使用变量,必须在每个阶段分别指定 +ARG DOCKER_USERNAME=library + +RUN set -x ; echo ${DOCKER_USERNAME} +``` diff --git a/image/dockerfile/label.md b/image/dockerfile/label.md new file mode 100644 index 0000000..1f816de --- /dev/null +++ b/image/dockerfile/label.md @@ -0,0 +1,17 @@ +# LABEL 指令 + +`LABEL` 指令用来给镜像以键值对的形式添加一些元数据(metadata)。 + +```docker +LABEL = = = ... +``` + +我们还可以用一些标签来申明镜像的作者、文档地址等: + +```docker +LABEL org.opencontainers.image.authors="yeasy" + +LABEL org.opencontainers.image.documentation="https://yeasy.gitbooks.io" +``` + +具体可以参考 https://github.com/opencontainers/image-spec/blob/master/annotations.md diff --git a/image/dockerfile/shell.md b/image/dockerfile/shell.md new file mode 100644 index 0000000..c207c39 --- /dev/null +++ b/image/dockerfile/shell.md @@ -0,0 +1,33 @@ +# SHELL 指令 + +格式:`SHELL ["executable", "parameters"]` + +`SHELL` 指令可以指定 `RUN` `ENTRYPOINT` `CMD` 指令的 shell,Linux 中默认为 `["/bin/sh", "-c"]` + +```docker +SHELL ["/bin/sh", "-c"] + +RUN lll ; ls + +SHELL ["/bin/sh", "-cex"] + +RUN lll ; ls +``` + +两个 `RUN` 运行同一命令,第二个 `RUN` 运行的命令会打印出每条命令并当遇到错误时退出。 + +当 `ENTRYPOINT` `CMD` 以 shell 格式指定时,`SHELL` 指令所指定的 shell 也会成为这两个指令的 shell + +```docker +SHELL ["/bin/sh", "-cex"] + +# /bin/sh -cex "nginx" +ENTRYPOINT nginx +``` + +```docker +SHELL ["/bin/sh", "-cex"] + +# /bin/sh -cex "nginx" +CMD nginx +``` diff --git a/image/dockerfile/workdir.md b/image/dockerfile/workdir.md index 6422812..79ad395 100644 --- a/image/dockerfile/workdir.md +++ b/image/dockerfile/workdir.md @@ -16,3 +16,21 @@ RUN echo "hello" > world.txt 之前说过每一个 `RUN` 都是启动一个容器、执行命令、然后提交存储层文件变更。第一层 `RUN cd /app` 的执行仅仅是当前进程的工作目录变更,一个内存上的变化而已,其结果不会造成任何文件变更。而到第二层的时候,启动的是一个全新的容器,跟第一层的容器更完全没关系,自然不可能继承前一层构建过程中的内存变化。 因此如果需要改变以后各层的工作目录的位置,那么应该使用 `WORKDIR` 指令。 + +```docker +WORKDIR /app + +RUN echo "hello" > world.txt +``` + +如果你的 `WORKDIR` 指令使用的相对路径,那么所切换的路径与之前的 `WORKDIR` 有关: + +```docker +WORKDIR /a +WORKDIR b +WORKDIR c + +RUN pwd +``` + +`pwd` 输出的结果为 `/a/b/c`。