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

①. 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容器数据卷,用于数据保存和持久化工作
CMDDockerfile 中可以有多个 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 b88d4af5b1fa

Removing 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 alpine

RUN 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 alpine

RUN 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 -l

FROM 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" ]
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

所得皆惊喜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值