文章目录

  • ①. DockerFile是什么?
  • ②. DockerFile构建过程解析
  • ③. 保留字指令
    • ①. FROM 基于哪个镜像
    • ②. LABEL 镜像的说明信息
    • ③. RUN 构建时期运行的指令
    • ④. CMD(运行时期)、ENTRYPOINT 指定启动容器、镜像的默认入口
    • ⑤. ARG 构建参数
    • ⑥. ENV 构建、运行都生效
    • ⑦. ADD 、COPY 复制文件
    • ⑧. WORKDIR 配置工作目录
    • ⑨. VOLUME 创建数据卷挂载点
    • ⑩. USER 指定运行容器时的用户名或UID
    • ⑩①. multi-stage builds 多阶段构建

①. DockerFile是什么?

  • ①. Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。

  • ②. 构建三步骤(编写Dockerfile文件 | docker build | docker run)

  • ③. 是什么样的?

  • ④. 一般而言,Dockerfile可以分为四部分
    基础镜像信息 维护者信息 镜像操作指令 启动时执行指令

# 这是我的第一个dockerfile镜像
FROM alpine
# 给镜像加注释信息
LABEL maintainer="TANGZHI " \
age=24
# 运行的指令、安装了软件、修改了文件,默认使用id=0的用户,也就是root,这个基础系统的root
# 代表镜像构建过程中的命令
RUN echo hellodockerfile
# 镜像启动要运行很长命令
# 1.准备一个sh文件 大多情况下
# 2.直接在CMD位置写即可
# 容器启动会执行的命令
CMD sleep 10;echo success

②. DockerFile构建过程解析

  • ①. Dockerfile内容基础知识
  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. #表示注释
  4. 每条指令都会创建一个新的镜像层,并对镜像进行提交
  • ②. 从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段 掌握
  1. Dockerfile是软件的原材料
  2. Docker镜像是软件的交付品
  3. Docker容器则可以认为是软件的运行态

③. 保留字指令

指令 解释
FROM 基础镜像,当前新镜像是基于哪个镜像的。必须为第一个命令
MAINTAINER 镜像维护者的姓名和邮箱地址,现在推荐用LABEL maintainer=xxx 来替代
RUN 容器构建时需要运行的命令
EXPOSE 当前容器对外暴露出的端口
WORKDIR 指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
ENV 用来在构建镜像过程中设置环境变量
ADD 带copy并且由解压功能
COPY 类似ADD,拷贝文件和目录到镜像中
VOLUME 容器数据卷,用于数据保存和持久化工作
CMD Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
ENTRYPOINT 指定一个容器启动时要运行的命令,使用docker run 之后的参数会进行一个叠加的操作
ONBUILD 当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发
LABEL 用于为镜像添加元数据
ARG 指定镜像内使用的参数(如版本号信息等),可以在build的时候,使用–build- args改变 v
USER 指定运行容器时的用户名或UID
OBBUILD 配置当创建的镜像作为其他镜像的基础镜像是,所指定的创建操作指令
STOPSIGNAL 容器退出的信号值
HEALTHCHECK 健康检查
SHELL 指定使用shell时的默认shell类型

①. FROM 基于哪个镜像

  • ①. 基础镜像,当前新镜像是基于哪个镜像的。必须为第一个命令

  • ②. busybox:是一个集成了一百多个最常用Linux命令和工具的软件

  • ③. Alpine:操作系统是一个面向安全的轻型Linux发行版经典最小镜像,基于busybox,功能比 Busybox完善(linux工具里的瑞士军刀)

  • ④. slim:docker hub中有些镜像有slim标识,都是瘦身了的镜像

  • ⑤. scratch:空镜像

②. LABEL 镜像的说明信息

  • 标注镜像的一些说明信息
LABEL maintainer="TANGZHI " \
age=24

③. RUN 构建时期运行的指令

  • ①. RUN指令有两种形式,一种是shell,另外一个是exec形式
  • ②. 在shell形式中,您可以使用(反斜杠)将一条RUN指令继续到下一行
FROM alpine
LABEL maintainer="tangzhi"
ARG prams=helloword
RUN echo $prams &&\
echo tangzhi
RUN echo "123456"
RUN echo 123456789
# 这种方式取不到环境变量
RUN ["echo","$prams"]
# 下面这种写法和RUN echo 123456789等价
RUN ["/bin/sh","-c","echo $prams"]
[root@i-id8g0yu9 ~]# docker build -t mydockerfile4 -f dockerfile57 .
Sending build context to Docker daemon  3.119MB
Step 1/8 : FROM alpine---> 6dbb9cc54074
Step 2/8 : LABEL maintainer="tangzhi"---> Using cache---> 3b6b777a2b23
Step 3/8 : ARG prams=helloword---> Using cache---> 80bcc56f3aee
Step 4/8 : RUN echo $prams &&echo tangzhi---> Running in 9e1c545b68c9
helloword
tangzhi
Removing intermediate container 9e1c545b68c9---> 93f7704f978b
Step 5/8 : RUN echo "123456"---> Running in ae14d2044897
123456
Removing intermediate container ae14d2044897---> 32ed2861f3e5
Step 6/8 : RUN echo 123456789---> Running in 84db90a766c4
123456789
Removing intermediate container 84db90a766c4---> d3fd8aeaec1f
Step 7/8 : RUN ["echo","$prams"]---> Running in 99dddaaba442
$prams
Removing intermediate container 99dddaaba442---> 31ed024c8569
Step 8/8 : RUN ["/bin/sh","-c","echo $prams"]---> Running in 4fdfca35b59f
helloword
Removing intermediate container 4fdfca35b59f---> a7457f8b7933
Successfully built a7457f8b7933
Successfully tagged mydockerfile4:latest
[root@i-id8g0yu9 ~]#

④. CMD(运行时期)、ENTRYPOINT 指定启动容器、镜像的默认入口

  • ①. ENTRYPOINT或者CMD作为唯一入口,只能写一个,最后一个生效
#最终都是以ping tangzhi.com为准
CMD ping baidu.com
CMD ping tangzhi.com
  • ②. [“echo”,"${param}"] 不是bash -c的方式,取不出环境变量性[]
    echo $param 等价于 ["/bin/sh","-c",“多长的命令都写在这里 echo ${param}”]
# CMD ["ping","baidu.com"]
# CMD ["useradd","-u","1000","-g","2000"]
# CMD ["ping","${url}"]  取不出变量
# CMD ping ${url}
  • ③. 官方都是建议使用[ ]方式(CMD ["/bin/sh","-c",“ping ${url}”]),变化的写CMD,固定不变的写ENTRYPO INT(未来他是容器启动的唯一入口)
# 一旦传递了cmd1,CMD指定的所有参数都会被覆盖
# 在控制台输入 docker run imageName  6 tangzhi.com
# ping 5 -c baidu.com
CMD [ "5","baidu.com" ]
ENTRYPOINT [ "ping","-c" ]
  • ④. 我们使用ENTRYPOINT ping baidu.com的形式输出,那么组合CMD怎么写都没用,容器启动都是以ENT RYPOINT的完整命令为准
# 最终都是以ping baidu.com为准
ENTRYPOINT ping baidu.com
CMD ping tangzhi.com

⑤. ARG 构建参数

  • ①. 定义以后的剩下环节生效(不包括运行环节),取值$param不能使用在CMD或者ENTRYPO INT中

  • ②. ARG指令定义了一个变量,用户可以在构建时使用–build-arg = 传递,docker build命令会将其传递给构建器。- -build-arg 指定参数会覆盖Dockerfile 中指定的同名参数
    docker build --build-arg param=“xiaozhi” --build-arg message=“hellodockerbuild” --no-cache -t mydockerfile:v1 -f dockerfile3 .

  • ③. 使用ENV指令定义的环境变量始终会覆盖同名的ARG指令

  • ④. ARG不像ENV,不能并排写

  • ⑤. dockerfile文件如下:

# 可以在任意位置使用,并在以后使用
ARG version=3.13.4
# 这是我的第一个dockerfile镜像
FROM alpine:$version
# 给镜像加注释信息
LABEL maintainer="TANGZHI " \age=24
# 运行的指令、安装了软件、修改了文件,默认使用id=0的用户,也就是root,这个基础系统的root
# 代表镜像构建过程中的命令
RUN echo hellodockerfile
RUN echo $param
# 定义以后的剩下环节生效(不包括运行环节),取值$param 不能使用在CMD或者ENTRYPOINT中
# 可以在构建期间进行变化,比如我们使用如下的命令
# docker build --build-arg param="xiaozhi" --build-arg message="hellodockerbuild" --no-cache -t mydockerfile:v1 -f dockerfile3 .
# ARG不像ENV 不能并排写
ARG param=helloparam
ARG message=hellodocker
# 构建时期会运行的指令(根据dockerfile创建一个镜像的整个过程时期)
RUN echo 1111
RUN echo $param
RUN echo $message
# 运行时期,我们会运行的指令(根据之前创建的镜像启动一个容器,容器启动默认运行的命令)
# docker run | docker start
# CMD和ENTRYPOINT 都是指定运行时的指令
# 当我们使用docker run -it 去执行的时候,发现只有1111输出
CMD ["/bin/sh","-c","echo 1111;echo $param"]
[root@i-id8g0yu9 ~]# docker build --build-arg param="xiaozhi" --build-arg message="hellodockerbuild" --no-cache -t mydockerfile3:v1 -f dockerfile3 .
Sending build context to Docker daemon  17.92kB
Step 1/11 : ARG version=3.13.4
Step 2/11 : FROM alpine:$version---> 49f356fa4513
Step 3/11 : LABEL maintainer="TANGZHI "     age=24---> Running in 382d67fbac27
Removing intermediate container 382d67fbac27---> bfa9c16b967a
Step 4/11 : RUN echo hellodockerfile---> Running in 5cc88771ed37
hellodockerfile
Removing intermediate container 5cc88771ed37---> 337c6e0404bd
Step 5/11 : RUN echo $param---> Running in b88d4af5b1faRemoving intermediate container b88d4af5b1fa---> e129628435dd
Step 6/11 : ARG param=helloparam---> Running in 5f10ed5dfa16
Removing intermediate container 5f10ed5dfa16---> 9904bb5f44df
Step 7/11 : ARG message=hellodocker---> Running in 50f117576dfa
Removing intermediate container 50f117576dfa---> e6c1c8a36097
Step 8/11 : RUN echo 1111---> Running in 1ae844ed29a6
1111
Removing intermediate container 1ae844ed29a6---> 5947099a85ec
Step 9/11 : RUN echo $param---> Running in c543d2f3ea4c
xiaozhi
Removing intermediate container c543d2f3ea4c---> 8353cd041e74
Step 10/11 : RUN echo $message---> Running in d58ac7513eac
hellodockerbuild
Removing intermediate container d58ac7513eac---> 07f41021c095
Step 11/11 : CMD ["/bin/sh","-c","echo 1111;echo $param"]---> Running in 5cacc787c157
Removing intermediate container 5cacc787c157---> e9ed761f20bf
Successfully built e9ed761f20bf
Successfully tagged mydockerfile3:v1
[root@i-id8g0yu9 ~]# docker run -it mydockerfile3:v1 #注意这里没有输入echo $param
1111[root@i-id8g0yu9 ~]#

⑥. ENV 构建、运行都生效

  • ①. 构建期不能修改ENV的值(docker build)

  • ②. 构建期+运行期都可以生效,但是只能在运行期进行修改

  • ③. 运行期docker run -it -e message=runENV

# 这是我的第一个dockerfile镜像
FROM alpine
# 给镜像加注释信息
LABEL maintainer="TANGZHI " \age=24
ARG message=helloARG
# 构建期+运行期都可以生效,但是只能在运行期进行修改
# 构建期不能修改ENV的值(docker build)
# 运行期docker run -it -e message=runENV
ENV message=helloENV
# 构建时期会运行的指令(根据dockerfile创建一个镜像的整个过程时期)
RUN echo $message
# 运行时期,我们会运行的指令(根据之前创建的镜像启动一个容器,容器启动默认运行的命令)
CMD ["/bin/sh","-c","echo 1111;echo app_$message"]
[root@i-id8g0yu9 ~]# docker build  --no-cache -t dockerfilearg:v1 -f dockerfileArg .
Sending build context to Docker daemon  20.99kB
Step 1/6 : FROM alpine
latest: Pulling from library/alpine
540db60ca938: Pull complete
Digest: sha256:69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f
Status: Downloaded newer image for alpine:latest---> 6dbb9cc54074
Step 2/6 : LABEL maintainer="TANGZHI "     age=24---> Running in f4c6286d7edc
Removing intermediate container f4c6286d7edc---> 214a711d0c39
Step 3/6 : ARG message=helloARG---> Running in a4e068cdd1a2
Removing intermediate container a4e068cdd1a2---> d502358f547c
Step 4/6 : ENV message=helloENV---> Running in 20fde633a7c2
Removing intermediate container 20fde633a7c2---> 26bcd7c0386d
Step 5/6 : RUN echo $message---> Running in 74d50778b66b
helloENV # 如果有ENV和ARY同时定义一个同名变量,我们使用的是ENV
Removing intermediate container 74d50778b66b---> 6867c5ca1d40
Step 6/6 : CMD ["/bin/sh","-c","echo 1111;echo app_$message"]---> Running in 1980007e51e0
Removing intermediate container 1980007e51e0---> a5015b515b34
Successfully built a5015b515b34
Successfully tagged dockerfilearg:v1
[root@i-id8g0yu9 ~]# docker run -it -e message=runENV dockerfilearg:v1
1111
app_runENV
[root@i-id8g0yu9 ~]#
  • ④. ENV在image阶段就会被解析并持久化(docker inspect image查看)参照下面示例
    msg1=msg2没问题,如果我运行期间修改了msg1=66666的值,请问msg1、msg2输出什么?
    结果输出 66666 hello
    这是因为env坏境的信息会固化,直接在镜像配置里面就已经写死,msg1=hello msg2=hello,而-e只能修改当前env本身
# 这是我的第一个dockerfile镜像
FROM alpine
# 给镜像加注释信息
LABEL maintainer="TANGZHI " \age=24
# msg1=msg2没问题,如果我运行期间修改了msg1=66666的值,请问msg1、msg2输出什么?
# 结果输出 66666 hello
# 这是因为env坏境的信息会固化,直接在镜像配置里面就已经写死,msg1=hello msg2=hello,而-e只能修改当前env本身
ENV msg1=hello
ENV msg2=$msg1
# 构建时期会运行的指令(根据dockerfile创建一个镜像的整个过程时期)
RUN echo $msg1
RUN echo $msg2
# 运行时期,我们会运行的指令(根据之前创建的镜像启动一个容器,容器启动默认运行的命令)
CMD ["/bin/sh","-c","echo $msg1;echo $msg2"]
[root@i-id8g0yu9 ~]# docker build --no-cache -t dockerfilearg2:v1 -f dockerfileArg2 .
Sending build context to Docker daemon  22.53kB
Step 1/7 : FROM alpine---> 6dbb9cc54074
Step 2/7 : LABEL maintainer="TANGZHI "     age=24---> Running in 6f6be6d001e0
Removing intermediate container 6f6be6d001e0---> d3cef1d085a5
Step 3/7 : ENV msg1=hello---> Running in dd2be1e7c37c
Removing intermediate container dd2be1e7c37c---> 034e061f70cc
Step 4/7 : ENV msg2=$msg1---> Running in 77908fc091f6
Removing intermediate container 77908fc091f6---> 5c5499ac0a19
Step 5/7 : RUN echo $msg1---> Running in 212c8ea2dcb2
hello
Removing intermediate container 212c8ea2dcb2---> 5db13711e330
Step 6/7 : RUN echo $msg2---> Running in 5e21ac6410e1
hello
Removing intermediate container 5e21ac6410e1---> 4765e9d7d753
Step 7/7 : CMD ["/bin/sh","-c","echo $msg1;echo $msg2"]---> Running in 67cb73e39262
Removing intermediate container 67cb73e39262---> bf71cc3088ea
Successfully built bf71cc3088ea
Successfully tagged dockerfilearg2:v1
[root@i-id8g0yu9 ~]# docker run -it -e msg1=66666  dockerfilearg2:v1
66666
hello
[root@i-id8g0yu9 ~]#

⑦. ADD 、COPY 复制文件

  • ①. ADD和COPY的功能是一样的,ADD多了自动下载远程文件和解压的功能
# 这是我的第一个dockerfile镜像
FROM alpine
# 把上下文context指定的内容复制到镜像中,如果是压缩包,自动解压,如果是远程文件,自动下载
# 把当前内容复制到alpine小系统里面
ADD https://download.redis.io/releases/redis-6.2.1.tar.gz /dest/
RUN ls -l
# RUN 指令上下并没有上下文关系
RUN cd /dest
# 当前还是列举的跟目录
RUN  ls -l
RUN cd /dest && ls -l
[root@i-id8g0yu9 ~]# docker build --no-cache -t dockerfileadd:v1 -f dockerfileADD .
Sending build context to Docker daemon  27.65kB
Step 1/6 : FROM alpine---> 6dbb9cc54074
Step 2/6 : ADD https://download.redis.io/releases/redis-6.2.1.tar.gz /dest/
Downloading [==================================================>]  2.438MB/2.438MB---> 80aaa61dc520
Step 3/6 : RUN ls -l---> Running in 1acdb19a9af4
total 8
drwxr-xr-x    2 root     root          4096 Apr 14 10:25 bin
drwxr-xr-x    2 root     root            32 Apr 18 12:53 dest
drwxr-xr-x    5 root     root           340 Apr 18 12:53 dev
drwxr-xr-x    1 root     root            66 Apr 18 12:53 etc
drwxr-xr-x    2 root     root             6 Apr 14 10:25 home
drwxr-xr-x    7 root     root           247 Apr 14 10:25 lib
drwxr-xr-x    5 root     root            44 Apr 14 10:25 media
drwxr-xr-x    2 root     root             6 Apr 14 10:25 mnt
drwxr-xr-x    2 root     root             6 Apr 14 10:25 opt
dr-xr-xr-x  114 root     root             0 Apr 18 12:53 proc
drwx------    2 root     root             6 Apr 14 10:25 root
drwxr-xr-x    2 root     root             6 Apr 14 10:25 run
drwxr-xr-x    2 root     root          4096 Apr 14 10:25 sbin
drwxr-xr-x    2 root     root             6 Apr 14 10:25 srv
dr-xr-xr-x   13 root     root             0 Apr 18 12:53 sys
drwxrwxrwt    2 root     root             6 Apr 14 10:25 tmp
drwxr-xr-x    7 root     root            66 Apr 14 10:25 usr
drwxr-xr-x   12 root     root           137 Apr 14 10:25 var
Removing intermediate container 1acdb19a9af4---> aff230b986d5
Step 4/6 : RUN cd /dest---> Running in e154c1af02e8
Removing intermediate container e154c1af02e8---> ef4756ff7262
Step 5/6 : RUN  ls -l---> Running in 32c3f351c176
total 8
drwxr-xr-x    2 root     root          4096 Apr 14 10:25 bin
drwxr-xr-x    2 root     root            32 Apr 18 12:53 dest
drwxr-xr-x    5 root     root           340 Apr 18 12:53 dev
drwxr-xr-x    1 root     root            66 Apr 18 12:53 etc
drwxr-xr-x    2 root     root             6 Apr 14 10:25 home
drwxr-xr-x    7 root     root           247 Apr 14 10:25 lib
drwxr-xr-x    5 root     root            44 Apr 14 10:25 media
drwxr-xr-x    2 root     root             6 Apr 14 10:25 mnt
drwxr-xr-x    2 root     root             6 Apr 14 10:25 opt
dr-xr-xr-x  113 root     root             0 Apr 18 12:53 proc
drwx------    2 root     root             6 Apr 14 10:25 root
drwxr-xr-x    2 root     root             6 Apr 14 10:25 run
drwxr-xr-x    2 root     root          4096 Apr 14 10:25 sbin
drwxr-xr-x    2 root     root             6 Apr 14 10:25 srv
dr-xr-xr-x   13 root     root             0 Apr 18 12:53 sys
drwxrwxrwt    2 root     root             6 Apr 14 10:25 tmp
drwxr-xr-x    7 root     root            66 Apr 14 10:25 usr
drwxr-xr-x   12 root     root           137 Apr 14 10:25 var
Removing intermediate container 32c3f351c176---> c45f1cca41d7
Step 6/6 : RUN cd /dest && ls -l---> Running in c82e471ef25e
total 2384
-rw-------    1 root     root       2438367 Mar  2 06:35 redis-6.2.1.tar.gz
Removing intermediate container c82e471ef25e---> 5ac189b07621
Successfully built 5ac189b07621
Successfully tagged dockerfileadd:v1
[root@i-id8g0yu9 ~]#
  • ②. 这里能使用docker build -t demo:test .的方式构建,是由于这个Dockerfile的文件在当前目录下,如果不在,那么需要将. 变成指定的文件夹(.代表的是当前上下文坏境)
# 这是我的第一个dockerfile镜像
FROM alpine
# 把上下文context指定的内容复制到镜像中,如果是压缩包,自动解压,如果是远程文件,自动下载
# 把当前内容复制到alpine小系统里面
ADD https://download.redis.io/releases/redis-6.2.1.tar.gz /dest/
# 本地linux系统的内容文件添加进去[宿主机--镜像内]
# docker build -t demo:test  .: .代表当前dockerfile指定的上下文坏境
# 通过执行我们可以看到,redis进行了自动解压的处理
ADD *.tar.gz /app/
# RUN 指令上下并没有上下文关系
RUN cd /dest && ls -l
RUN cd /app && ls -l
[root@i-id8g0yu9 ~]# docker build --no-cache -t dockerfileadd2:v1 -f dockerfileADD2 .
Sending build context to Docker daemon  2.468MB
Step 1/5 : FROM alpine---> 6dbb9cc54074
Step 2/5 : ADD https://download.redis.io/releases/redis-6.2.1.tar.gz /dest/
Downloading [==================================================>]  2.438MB/2.438MB---> b7598fcec68b
Step 3/5 : ADD *.tar.gz /app/---> 9b222d9290b5
Step 4/5 : RUN cd /dest && ls -l---> Running in 4a32a2a9866b
total 2384
-rw-------    1 root     root       2438367 Mar  2 06:35 redis-6.2.1.tar.gz
Removing intermediate container 4a32a2a9866b---> f72d59644485
Step 5/5 : RUN cd /app && ls -l---> Running in 48fe6f35756f
total 4
drwxrwxr-x    7 root     root          4096 Mar  2 06:14 redis-6.2.1
Removing intermediate container 48fe6f35756f---> 762a609e68e9
Successfully built 762a609e68e9
Successfully tagged dockerfileadd2:v1

⑧. WORKDIR 配置工作目录

  • ①. 根目录,WORKDIR指令可在Dockerfile中多次使用。 如果提供了相对路径,则它将相对于上一个WORK DIR指令的路径(如下面的/app/abc是根目录)
FROM alpineRUN pwd && ls -l
# 为以下所有命令运行指令了基础目录
# /app/abc
WORKDIR /app
# 当我们使用docker exec 进入容器控制台,会发现根目录是 /app/abc
WORKDIR abc
# 复制到当前目录下
COPY *.txt ./
RUN pwd && ls -l
CMD ping baidu.com
[root@i-id8g0yu9 ~]# docker build --no-cache -t dockerfileworkdir:v1 -f dockerfileWORKDIR .
Sending build context to Docker daemon  2.472MB
Step 1/7 : FROM alpine---> 6dbb9cc54074
Step 2/7 : RUN pwd && ls -l---> Running in 7ef554287c6f
/
total 8
drwxr-xr-x    2 root     root          4096 Apr 14 10:25 bin
drwxr-xr-x    5 root     root           340 Apr 18 13:54 dev
drwxr-xr-x    1 root     root            66 Apr 18 13:54 etc
drwxr-xr-x    2 root     root             6 Apr 14 10:25 home
drwxr-xr-x    7 root     root           247 Apr 14 10:25 lib
drwxr-xr-x    5 root     root            44 Apr 14 10:25 media
drwxr-xr-x    2 root     root             6 Apr 14 10:25 mnt
drwxr-xr-x    2 root     root             6 Apr 14 10:25 opt
dr-xr-xr-x  111 root     root             0 Apr 18 13:54 proc
drwx------    2 root     root             6 Apr 14 10:25 root
drwxr-xr-x    2 root     root             6 Apr 14 10:25 run
drwxr-xr-x    2 root     root          4096 Apr 14 10:25 sbin
drwxr-xr-x    2 root     root             6 Apr 14 10:25 srv
dr-xr-xr-x   13 root     root             0 Apr 18 12:58 sys
drwxrwxrwt    2 root     root             6 Apr 14 10:25 tmp
drwxr-xr-x    7 root     root            66 Apr 14 10:25 usr
drwxr-xr-x   12 root     root           137 Apr 14 10:25 var
Removing intermediate container 7ef554287c6f---> 27e092e104fb
Step 3/7 : WORKDIR /app---> Running in ee015d4b2a18
Removing intermediate container ee015d4b2a18---> 4419d4f77345
Step 4/7 : WORKDIR abc---> Running in bc8172263488
Removing intermediate container bc8172263488---> e29383588c07
Step 5/7 : COPY *.txt ./---> 715b2d4db2d9
Step 6/7 : RUN pwd && ls -l---> Running in 5e5c8d7ab9b8
/app/abc
total 4
-rw-r--r--    1 root     root             5 Apr 18 13:46 a.txt
Removing intermediate container 5e5c8d7ab9b8---> d196ffbdf968
Step 7/7 : CMD ping baidu.com---> Running in e0b6b78b1eec
Removing intermediate container e0b6b78b1eec---> a1be08fec3d1
Successfully built a1be08fec3d1
Successfully tagged dockerfileworkdir:v1
[root@i-id8g0yu9 ~]# docker run -d --name myworkdir dockerfileworkdir:v1
b4d8744b6a920fa5eea4b2388ede0e04489905a8449d0c2e40ef8d3d298cfecb
[root@i-id8g0yu9 ~]# docker ps
CONTAINER ID   IMAGE                  COMMAND                  CREATED         STATUS         PORTS     NAMES
b4d8744b6a92   dockerfileworkdir:v1   "/bin/sh -c 'ping ba…"   3 seconds ago   Up 3 seconds             myworkdir
[root@i-id8g0yu9 ~]# docker exec -it b4d8744b6a92 /bin/sh
/app/abc #

⑨. VOLUME 创建数据卷挂载点

  • ①. 把容器的某些文件夹映射到主机外部

  • ②. 写法:这个一般写在最后
    VOLUME ["/var/log/"] #可以是JSON数组
    VOLUME /var/log #可以直接写
    VOLUME /var/log /var/db #可以空格分割多个

  • ③. 注意:用VOLUME声明了卷,那么以后对于卷内容的修改会被丢弃,所以一定在volume声明之前修改内容

FROM alpineRUN mkdir /hello && mkdir /app
RUN echo 1111 > /hello/a.txt
RUN echo 2222 > /app/b.txt
# 挂在容器内的指定文件夹,如果不存在则创建
# 指定了volume,即使启动容器没有指定-v参数,我们也会自动进行匿名卷挂载
# 这里的 hello app 都是容器里面的文件夹,请你在使用镜像启动容器的时候,自动给宿主机上挂载
VOLUME [ "/hello","/app"]# 用VOLUME声明了卷,那么以后对于卷内容的修改会被丢弃,所以一定在volume声明之前修改内容
RUN echo 6666 > /hello/a.txt
RUN echo 8888 > /app/b.txt
CMD ping baidu.com
[root@i-id8g0yu9 ~]# docker build --no-cache -t dockerfileworkvolume:v1 -f dockerfileVOLUME .
Sending build context to Docker daemon  2.474MB
Step 1/8 : FROM alpine---> 6dbb9cc54074
Step 2/8 : RUN mkdir /hello && mkdir /app---> Running in 36ed19f5446d
Removing intermediate container 36ed19f5446d---> 42af237e9a7e
Step 3/8 : RUN echo 1111 > /hello/a.txt---> Running in 662511d7ddb7
Removing intermediate container 662511d7ddb7---> f744129965ae
Step 4/8 : RUN echo 2222 > /app/b.txt---> Running in a8321f4f8d98
Removing intermediate container a8321f4f8d98---> 1d03ca553eb7
Step 5/8 : VOLUME [ "/hello","/app"]---> Running in 1d4ec1c1e8f7
Removing intermediate container 1d4ec1c1e8f7---> 4e76b09577d3
Step 6/8 : RUN echo 6666 > /hello/a.txt---> Running in 912d739bb4d4
Removing intermediate container 912d739bb4d4---> da35323435dd
Step 7/8 : RUN echo 8888 > /app/b.txt---> Running in bab5aceb4f7a
Removing intermediate container bab5aceb4f7a---> 73c45738db48
Step 8/8 : CMD ping baidu.com---> Running in 05bedb917269
Removing intermediate container 05bedb917269---> a01440e2a675
Successfully built a01440e2a675
Successfully tagged dockerfileworkvolume:v1
[root@i-id8g0yu9 ~]# docker run -d dockerfileworkvolume:v1
56ef53c95a6c7f96a8cf308be8393ee53fb70a4802f7c43e4519cf5fab438abc
[root@i-id8g0yu9 ~]# docker ps
CONTAINER ID   IMAGE                     COMMAND                  CREATED          STATUS          PORTS     NAMES
56ef53c95a6c   dockerfileworkvolume:v1   "/bin/sh -c 'ping ba…"   4 seconds ago    Up 3 seconds              stupefied_ptolemy
b4d8744b6a92   dockerfileworkdir:v1      "/bin/sh -c 'ping ba…"   49 minutes ago   Up 49 minutes             myworkdir
[root@i-id8g0yu9 ~]# docker  inspect 56ef53c95a6c
[{"Id": "56ef53c95a6c7f96a8cf308be8393ee53fb70a4802f7c43e4519cf5fab438abc","Created": "2021-04-18T14:45:15.782034507Z","Path": "/bin/sh","Args": ["-c","ping baidu.com"],"State": {"Status": "running","Running": true,"Paused": false,"Restarting": false,"OOMKilled": false,"Dead": false,"Pid": 8131,"ExitCode": 0,"Error": "","StartedAt": "2021-04-18T14:45:16.143344962Z","FinishedAt": "0001-01-01T00:00:00Z"},"Image": "sha256:a01440e2a675dab49c9fb9c788e890c81913e7f15de3a4071fec51a5a5475aea","ResolvConfPath": "/var/lib/docker/containers/56ef53c95a6c7f96a8cf308be8393ee53fb70a4802f7c43e4519cf5fab438abc/resolv.conf","HostnamePath": "/var/lib/docker/containers/56ef53c95a6c7f96a8cf308be8393ee53fb70a4802f7c43e4519cf5fab438abc/hostname","HostsPath": "/var/lib/docker/containers/56ef53c95a6c7f96a8cf308be8393ee53fb70a4802f7c43e4519cf5fab438abc/hosts","LogPath": "/var/lib/docker/containers/56ef53c95a6c7f96a8cf308be8393ee53fb70a4802f7c43e4519cf5fab438abc/56ef53c95a6c7f96a8cf308be8393ee53fb70a4802f7c43e4519cf5fab438abc-json.log","Name": "/stupefied_ptolemy","RestartCount": 0,"Driver": "overlay2","Platform": "linux","MountLabel": "","ProcessLabel": "","AppArmorProfile": "","ExecIDs": null,"HostConfig": {"Binds": null,"ContainerIDFile": "","LogConfig": {"Type": "json-file","Config": {}},"NetworkMode": "default","PortBindings": {},"RestartPolicy": {"Name": "no","MaximumRetryCount": 0},"AutoRemove": false,"VolumeDriver": "","VolumesFrom": null,"CapAdd": null,"CapDrop": null,"CgroupnsMode": "host","Dns": [],"DnsOptions": [],"DnsSearch": [],"ExtraHosts": null,"GroupAdd": null,"IpcMode": "private","Cgroup": "","Links": null,"OomScoreAdj": 0,"PidMode": "","Privileged": false,"PublishAllPorts": false,"ReadonlyRootfs": false,"SecurityOpt": null,"UTSMode": "","UsernsMode": "","ShmSize": 67108864,"Runtime": "runc","ConsoleSize": [0,0],"Isolation": "","CpuShares": 0,"Memory": 0,"NanoCpus": 0,"CgroupParent": "","BlkioWeight": 0,"BlkioWeightDevice": [],"BlkioDeviceReadBps": null,"BlkioDeviceWriteBps": null,"BlkioDeviceReadIOps": null,"BlkioDeviceWriteIOps": null,"CpuPeriod": 0,"CpuQuota": 0,"CpuRealtimePeriod": 0,"CpuRealtimeRuntime": 0,"CpusetCpus": "","CpusetMems": "","Devices": [],"DeviceCgroupRules": null,"DeviceRequests": null,"KernelMemory": 0,"KernelMemoryTCP": 0,"MemoryReservation": 0,"MemorySwap": 0,"MemorySwappiness": null,"OomKillDisable": false,"PidsLimit": null,"Ulimits": null,"CpuCount": 0,"CpuPercent": 0,"IOMaximumIOps": 0,"IOMaximumBandwidth": 0,"MaskedPaths": ["/proc/asound","/proc/acpi","/proc/kcore","/proc/keys","/proc/latency_stats","/proc/timer_list","/proc/timer_stats","/proc/sched_debug","/proc/scsi","/sys/firmware"],"ReadonlyPaths": ["/proc/bus","/proc/fs","/proc/irq","/proc/sys","/proc/sysrq-trigger"]},"GraphDriver": {"Data": {"LowerDir": "/var/lib/docker/overlay2/bca4693743c24765c88e89c05892e9b8f3f0b39918c5a400d58c9b9db5ec450c-init/diff:/var/lib/docker/overlay2/8623d3705ceea6e0f9349ac0645977e1fa8c45cc9ea6337115098c03d259a200/diff:/var/lib/docker/overlay2/960ab6c1f64fd999f44c90be57256371c1e5dd43f115e1d2ff11037408a8ffc8/diff:/var/lib/docker/overlay2/871b7ffab75435d24006f3f7bff690c903328b273764a7e4ab1922bece5b8ad7/diff:/var/lib/docker/overlay2/43d78cac3804ed1dc62283f315a185e8136796e5779d9ee8717fa9a2d99d6edd/diff","MergedDir": "/var/lib/docker/overlay2/bca4693743c24765c88e89c05892e9b8f3f0b39918c5a400d58c9b9db5ec450c/merged","UpperDir": "/var/lib/docker/overlay2/bca4693743c24765c88e89c05892e9b8f3f0b39918c5a400d58c9b9db5ec450c/diff","WorkDir": "/var/lib/docker/overlay2/bca4693743c24765c88e89c05892e9b8f3f0b39918c5a400d58c9b9db5ec450c/work"},"Name": "overlay2"},"Mounts": [{"Type": "volume","Name": "65adbd1e4997c8df05a05b30ab1a2c3df970e19b0dd38f579f428ec8442810b9","Source": "/var/lib/docker/volumes/65adbd1e4997c8df05a05b30ab1a2c3df970e19b0dd38f579f428ec8442810b9/_data","Destination": "/app","Driver": "local","Mode": "","RW": true,"Propagation": ""},{"Type": "volume","Name": "1c3739d31bd487d847d0101ac2d48bbdb661cc9cbe97799de86181c2f50d98db","Source": "/var/lib/docker/volumes/1c3739d31bd487d847d0101ac2d48bbdb661cc9cbe97799de86181c2f50d98db/_data","Destination": "/hello","Driver": "local","Mode": "","RW": true,"Propagation": ""}],"Config": {"Hostname": "56ef53c95a6c","Domainname": "","User": "","AttachStdin": false,"AttachStdout": false,"AttachStderr": false,"Tty": false,"OpenStdin": false,"StdinOnce": false,"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd": ["/bin/sh","-c","ping baidu.com"],"Image": "dockerfileworkvolume:v1","Volumes": {"/app": {},"/hello": {}},"WorkingDir": "","Entrypoint": null,"OnBuild": null,"Labels": {}},"NetworkSettings": {"Bridge": "","SandboxID": "d4490ef3887d03e22812b820c963c82a8edfe45c5f3141676a03df8d7aecfc51","HairpinMode": false,"LinkLocalIPv6Address": "","LinkLocalIPv6PrefixLen": 0,"Ports": {},"SandboxKey": "/var/run/docker/netns/d4490ef3887d","SecondaryIPAddresses": null,"SecondaryIPv6Addresses": null,"EndpointID": "671b069ea364448c75dbbb4d9365c60b46abf392bdcca26bc9713cf9051baa2e","Gateway": "172.17.0.1","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"IPAddress": "172.17.0.3","IPPrefixLen": 16,"IPv6Gateway": "","MacAddress": "02:42:ac:11:00:03","Networks": {"bridge": {"IPAMConfig": null,"Links": null,"Aliases": null,"NetworkID": "24c026c0a26cfb78a82f033887c3669c4ccaf63060e02fefe51e958cb5037c32","EndpointID": "671b069ea364448c75dbbb4d9365c60b46abf392bdcca26bc9713cf9051baa2e","Gateway": "172.17.0.1","IPAddress": "172.17.0.3","IPPrefixLen": 16,"IPv6Gateway": "","GlobalIPv6Address": "","GlobalIPv6PrefixLen": 0,"MacAddress": "02:42:ac:11:00:03","DriverOpts": null}}}}
]
[root@i-id8g0yu9 ~]# cd /var/lib/docker/volumes/65adbd1e4997c8df05a05b30ab1a2c3df970e19b0dd38f579f428ec8442810b9/_data
[root@i-id8g0yu9 _data]# ls
b.txt
[root@i-id8g0yu9 _data]# cat b.txt  # 注意这里还有追加6666或者8888
2222
[root@i-id8g0yu9 _data]#

⑩. USER 指定运行容器时的用户名或UID

# 这是我的第一个dockerfile镜像
FROM alpine
# 相当于给当前容器开一个用户,以后的命令可以用这个用户运行 有可能没有执行权限
# 容器中的ROOT虽然不是lunux宿主机的真实root,但是可以改掉这个镜像的所有
USER 1000:1000
# 不自动解压
# 以linux主机的用户为准,默认是root用户,如果我们不指定权限将复制失败
COPY --chown=1000:1000 *.txt /a.txt
# RUN 指令上下并没有上下文关系
RUN  ls -l
[root@i-id8g0yu9 ~]# docker build --no-cache -t dockerfileworkuser:v1 -f dockerfileUSER .
Sending build context to Docker daemon  2.473MB
Step 1/4 : FROM alpine---> 6dbb9cc54074
Step 2/4 : USER 1000:1000---> Running in 7d4fd2b2a54c
Removing intermediate container 7d4fd2b2a54c---> 2561ad4ce2c2
Step 3/4 : COPY --chown=1000:1000 *.txt /a.txt---> a21c8da0fb0c
Step 4/4 : RUN  ls -l---> Running in c9cbef9eac65
total 12
-rw-r--r--    1 1000     1000             5 Apr 18 13:46 a.txt
drwxr-xr-x    2 root     root          4096 Apr 14 10:25 bin
drwxr-xr-x    5 root     root           340 Apr 18 14:22 dev
drwxr-xr-x    1 root     root            66 Apr 18 14:22 etc
drwxr-xr-x    2 root     root             6 Apr 14 10:25 home
drwxr-xr-x    7 root     root           247 Apr 14 10:25 lib
drwxr-xr-x    5 root     root            44 Apr 14 10:25 media
drwxr-xr-x    2 root     root             6 Apr 14 10:25 mnt
drwxr-xr-x    2 root     root             6 Apr 14 10:25 opt
dr-xr-xr-x  115 root     root             0 Apr 18 14:22 proc
drwx------    2 root     root             6 Apr 14 10:25 root
drwxr-xr-x    2 root     root             6 Apr 14 10:25 run
drwxr-xr-x    2 root     root          4096 Apr 14 10:25 sbin
drwxr-xr-x    2 root     root             6 Apr 14 10:25 srv
dr-xr-xr-x   13 root     root             0 Apr 18 12:58 sys
drwxrwxrwt    2 root     root             6 Apr 14 10:25 tmp
drwxr-xr-x    7 root     root            66 Apr 14 10:25 usr
drwxr-xr-x   12 root     root           137 Apr 14 10:25 var
Removing intermediate container c9cbef9eac65---> db89e3d275a2
Successfully built db89e3d275a2
Successfully tagged dockerfileworkuser:v1
[root@i-id8g0yu9 ~]#

⑩①. multi-stage builds 多阶段构建

# 最终版本
FROM maven:3.5.2-jdk-8-slim AS buildapp
WORKDIR /app
COPY src .
COPY pom.xml .
RUN mvn clean package
RUN cp target/*.jar app.jar
RUN ls -lFROM openjdk:8u282-slim
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
LABEL maintainer="845195485@qq.com"
COPY --from=buildapp /app/app.jar /app.jar
# COPY demo-0.0.1-SNAPSHOT.jar /app.jar
EXPOSE 8080
# CMD ["--server.prot=8080"]
ENV JAVA_OPTS=""
ENV PARAMS=""
ENTRYPOINT [ "sh", "-c", "java -Djava.security.egd=file:/dev/./urandom $JAVA_OPTS -jar /app.jar $PARAMS" ]

DOCKER04_详解Dockerfile基本指令、FROM、LABEL、RUN、CMD、ENTRYPOINT、ARG、ENV、VOLUME、USER相关推荐

  1. AngularJS 详解Directive(指令)机制

    AngularJS  5个实例详解Directive(指令)机制 大漠穷秋  http://damoqiongqiu.iteye.com/blog/1917971 1.一点小说明 指令的作用:实现语义 ...

  2. dockerfile详解-dockerfile构建过程解析,dockerfile体系结构保留字解析,案例解析

    Dockerfile详解 1.定义:Dockerfile是用来构建Docker镜像的构建文件,是一系列命令和参数构成的脚本 2.步骤: --手动编写一个dockerfile文件,必须要要符合规范 -- ...

  3. Linux——更改文件及目录权限(d rwx r-x r-x字段详解+更改代码指令)

    目录 一.d rwx r-x r-x .字段详解: 二.Chmod (更改文件所属组权限) (1)指令讲解: (2)实列:让其他用户对test.txt文件增加写的权限 三.改变文件的所属者,所属组权限 ...

  4. Tkinter 组件详解(一):Label

    Tkinter 组件详解之Label Label(标签)组件用于在屏幕上显示文本或图像.Label 组件仅能显示单一字体的文本,但文本可以跨越多行.另外,还可以为其中的个别字符加上下划线(例如用于表示 ...

  5. 【C/C++内功心法】剖析预处理过程,详解其他预处理指令,提升C/C++内功

    文章目录 前言 一.#undef 二.命令行定义 三.条件编译 四.文件包含 1.头文件被包含的方式 2.嵌套文件包含 总结 前言 大家好啊,我是不一样的烟火a,今天我将会为大家详细讲解其他的预处理指 ...

  6. svg画半圆详解(L指令、M指令、A指令)

    svg画半圆 了解画半圆的各个指令 L指令 M指令 A指令 画整半圆 推荐:svg画整圆详解 推荐:svg的text标签字体.颜色.样式.大小.居中详解 接到需求,要求做出一个这样的活动转盘,,,,, ...

  7. angular元素属性绑定_AngularJS语法基础及数据绑定——详解各种数据绑定指令、属性应用...

    AngularJS简单易学,但是功能强大.特别是在构建单页面应用方面效果显著.而 数据绑定 可以说是他被广泛使用的最主要的优点.他舍弃了对DOM的操作方式,一切都由AngularJS来自动更新视图,我 ...

  8. 西门子atch指令详解_中文详解西门子PLC指令,瞬间都明白了!

    指令( 英文全称意思 ) :指令含义 1.LD ( Load 装载 ) :动合触点 2.LDN ( Load Not 不装载 ) : 动断触点 3.A( And 与 动合) : 用于动合触点串联 4. ...

  9. Docker镜像创建的三种方式详解——dockerfile制作apache镜像

    基于已有的镜像容器进行创建 [root@localhost opt]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAM ...

最新文章

  1. python dump函数_python中实现php的var_dump函数功能
  2. 你用对锁了吗?浅谈 Java “锁” 事
  3. 【转】“根级别上的数据无效”问题的解决
  4. java权限框架_Java高级工程师必备技术栈-由浅入深掌握Shiro权限框架
  5. 深度学习 《梯度消失和梯度爆炸》
  6. mysql无损复制_MySQL无损复制(转)
  7. 最小成本排序:两种情况
  8. win7 启用网络发现
  9. RDIFramework.NET(.NET快速信息化系统开发框架) Web版介绍
  10. RocketMQ-项目集成
  11. 玩转iOS开发:iOS 8新特性《Share Extension》
  12. 经度和纬度在SQL中的数据类型
  13. win10误删IE浏览器文件如何恢复?
  14. 倪文迪陪你学蓝桥杯2021寒假每日一题:1.25日(2019省赛A组第3题)
  15. Android 画中画模式
  16. java动态图片_Java之简单的图片动态显示(实现类似GIF动画效果)
  17. python爬虫实战:爬取王者荣耀英雄背景故事
  18. Python---数据分析---绘制条形图---横竖条形图
  19. 【第36题】JAVA高级技术-对象克隆5(几种深克隆效率比较)
  20. 全志 H6 Orange Pi Lite 2 Android 7.0 源码编译

热门文章

  1. 计算机应用基础0039答案,2016秋5205004计算机应用基础-0039【参考答案】
  2. 调节latex表格中的字体大小
  3. OSI 模型简单介绍与速记
  4. 蓝牙map协议源码解析
  5. C++多态的好处和作用(游戏程序实例)
  6. UE5连接SQL数据库
  7. 企业WAP建站的10个理由
  8. MSF开启socks代理内网渗透
  9. 优秀网页设计:25个精美的旅游网站设计示例
  10. 月薪15k的软件测试工程师需要学习什么技术?