Dockerfile详解与实践

Dockerfile详解与实践
Docker‘s Network
Docker-Compose

官方文档:https://docs.docker.com/engine/reference/builder/
Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。

dockerfile每条指令都会构建一层镜像,一般分为四部分:基础镜像信息、维护者信息、镜像操作指令、容器启动执行指令,#为 Dockerfile 中的注释符。

01、Dockerfile总述

docker build 基于dockerfile制作镜像。

docker build [OPTIONS] PATH | URL | -
OPTIONS参数
-t, --tag list                Name and optionally a tag in the 'name:tag' format
-c, --cpu-shares int          CPU shares (relative weight)
-m, --memory bytes            Memory limit
--build-arg list         	  Set build-time variables

02、指令:FROM

FROM:指令必须是Dockerfile中非注释行的第一个指令,为镜像文件构建提供基础镜像环境。

FROM <repository>[:<tag>]
或:
FROM <repository>@<digest>
	<repository>:指定作为 base image 的名称
	<tag>:base image 的标签,省略则默认为latest
	<digest>:镜像的哈希值

示例:
FROM busybox:latest
FROM redis:6.0.8

03、指令:MAINTAINER

Dockerfile镜像维护者的详细信息,如姓名和邮箱地址。

MAINTAINER <authtor's detail>

示例:
FROM busybox:latest
MAINTAINER "Along <[email protected]>"

FROM busybox:latest
MAINTAINER "Along <[email protected]>"

04、指令:COPY

用于从 docker 拷贝主机文件或目录 到 镜像中。
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

<src>:源路径,要复制的源文件或目录。
<dest>:目标路径,即正在创建的镜像的文件系统路径(该路径不用事先建好)。

05、指令:ADD

指令类似于COPY指令,将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包。

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

1、拷贝单个文件
ADD ./a.txt WORKDIR/b

2、拷贝多个文件
ADD指令支持通配符:
# 拷贝当前目录下的michael文件夹的所有sh文件到/usr/bin目录下
ADD ./michael/*.sh /usr/bin/

# 拷贝当前目录下的michael文件夹的所有带后缀的文件到/usr/bin目录下
ADD ./michael/*.* /usr/bin/

# 拷贝当前目录下的michael文件夹的所有不带后缀的文件到/usr/bin目录下
ADD ./michael/* /usr/bin/

# 拷贝当前目录下的michael文件夹的所有文件到/usr/bin目录下(/usr/bin目录原有的文件会保留)
ADD ./michael/ /usr/bin/

3、拷贝文件夹
ADD ./config /usr/bin/config

06、指令:ENV

定义构建镜像的环境变量,可被Dockerfile文件中位于其后的其它指令(如ENV、ADD等)所调用。
调用格式为 $variable_name${variable_name}。

一次只能设置一个
ENV key value
一次可以设置多个键值对
ENV key1=value1 key2=value2
使用例子:
ENV MY_PATH /usr/mytest
WORKDIR $MY_PATHdocker run 命令中设置环境变量:
docker run -e key1=value1 --env key2=value2 ubuntu
docker run --env key1=value1 --env key2=value2 ubuntu

07、指令:VOLUME

1、VOLUME-v指令一样,容器被删除以后映射在主机上的文件不会被删除。
2、VOLUME指令只是起到了声明了容器中的目录作为匿名卷,并没有将匿名卷绑定到宿主机指定目录的功能。
若Dockerfile中声明了VOLUME匿名卷,启动容器的时候,docker会在主机特定目录下面生成一个目录来绑定容器的匿名卷,如我测试的docker版本映射目录为:/var/lib/docker/volumes/{随机生成的唯一ID}/_data。(可以通过 docker inspect 容器ID 查看映射关系)。

3、若-vVOLUME指定了不同的位置,会以-v设定的目录为准,其实VOLUME指令的设定的目的就是为了避免用户忘记指定-v的时候导致的数据丢失,那么如果用户指定了-v,自然而然就不需要VOLUME指定的位置了。

容器数据卷,用于在image中创建一个默认挂载点目录,达到数据保存和持久化的目的。

VOLUME <mountpoint>

格式1:The value can be a JSON array, such as 
VOLUME ["/var/log/"]
VOLUME ["/var/log/", "/var/db"]

格式2:a plain string with multiple arguments, such as 
VOLUME /var/log
VOLUME /var/log /var/db



使用命令可查看到默认挂载点具体在主机上的挂载位置
docker inspect fa158a
[
    {
    
    
        "Id": "fa158a17f30e37e1edd9e9949d7974cdd22bbfba966ca95f14938c5aa5931140",
        "Created": "2022-11-06T16:38:58.485000851Z",
		... 省略 ...............................
        "Mounts": [
            {
    
    
                "Type": "volume",
                "Name": "f657b5700e230bd6e4354dc6cc6861a4d28a8b091f97e00e03a102346b0bf6a7",
                "Source": "/var/lib/docker/volumes/f657b5700e230bd6e4354dc6cc6861a4d28a8b091f97e00e03a102346b0bf6a7/_data",
				"Destination": "/tmp",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
		... 省略 ...............................
    }
]


默认挂载点会将数据映射保存到/var/lib/docker/volumes/下的一个特定目录下
/var/lib/docker/volumes/f657b5700e230bd6e4354dc6cc6861a4d28a8b091f97e00e03a102346b0bf6a7/_data

08、指令:RUN

用于指定容器构建过程中运行的命令,其可以是任何命令,RUN是在 docker build时运行。
RUN <command>
或
RUN ["<executable>", "<param1>", "<param2>"]

第一种shell格式中,<command>通常是一个shell命令, 且以“/bin/sh -c”来运行它,这意味着此进程在容器中的PID不为1,
不能接收Unix信号,因此,当使用docker stop <container>命令停止容器时,此进程接收不到SIGTERM信号;
RUN yum -y install vim


第二种exec格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的 <paramN>为传递给命令的选项或参数;
然而,此种格式指定的命令不会以“/bin/sh -c”来发起,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行;
不过, 如果要运行的命令依赖于此shell特性的话,可以将其替换为类似下面的格式。
RUN ["/bin/bash", "-c", "<executable>", "<param1>", "<param2>"]
RUN ["yum", "-y", "install", "vim"]
RUN ["/bin/bash", "-c", "yum", "-y", "install", "vim"]

09、指令:CMD

类似于RUN指令,CMD指令也可用于运行任何命令或应用程序
RUN 运行于镜像文件构建过程中【镜像构建命令:RUN是在 docker build 时运行】。
CMD 运行于基于Dockerfile构建出的新镜像启动一个容器时【容器启动命令:CMD是在 docker run 时运行】。

CMD 的首要目的在于为启动的容器指定默认要运行的程序;
CMD 会被 docker run 之后的参数替换;
Dockerfile中可以存在多个CMD指令,但仅最后一个会生效;
docker pull billygoo/tomcat8-jdk8

可以看到猫:
docker run -it -p 8080:8080 billygoo/tomcat8-jdk8
docker run -it -p 8080:8080 30ef4019761d
### CMD ["catalina.sh", "run"]

不可以看到猫:
docker run -it -p 8080:8080 30ef4019761d /bin/bash
### CMD ["catalina.sh", "run"]
### CMD ["/bin/bash"]


语法1:格式的意义同RUN;
CMD <command>  
语法2:格式的意义同RUN;
CMD ["<executable>","<param1>","<param2>"] 
语法3:用于为 ENTRYPOINT 指令提供默认参数;
CMD ["<param1>","<param2>"]

注:json数组中,要使用双引号,单引号会出错;




10、指令:ENTRYPOINT

类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序
与CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,
这些命令行参数会被当作参数传递给ENTRYPOINT指定指定的程序
不过,docker run命令的 --entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序

ENTRYPOINT command param1 param2
或
ENTRYPOINT ["executable", "param1", "param2"]

docker run 命令传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT命令最后做为其参数使用
Dockerfile文件中也可以存在多个ENTRYPOINT指令,但仅有最后一个会生效



命令格式:
ENTRYPOINT可以和CMD一起用,一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参。当指定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行其命令而是将CMD的内容作为参数传递给ENTRYPOINT指令,他两个组合会变成 案例如下:

-----Dockerfile-----start
FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
# 假设已通过此 Dockerfile 构建了 nginx:test 镜像:
-----Dockerfile-----end

docker run nginx:test		# 实际执行命令 nginx -c /etc/nginx/nginx.conf
docker run nginx:test -c /etc/nginx/new.conf  # 实际执行命令 nginx -c /etc/nginx/new.conf 

11、指令:HEALTHCHECK

HEALTHCHECK指令告诉Docker如何测试容器以检查它是否仍在工作。
即使服务器进程仍在运行,这也可以检测出陷入无限循环且无法处理新连接的Web服务器等情况

HEALTHCHECK [OPTIONS] CMD command (通过在容器内运行命令来检查容器运行状况)
HEALTHCHECK NONE (禁用从基础映像继承的任何运行状况检查)

OPTIONS 选项:
--interval=DURATION (default: 30s):每隔多长时间探测一次,默认30秒
-- timeout= DURATION (default: 30s):服务响应超时时长,默认30秒
--start-period= DURATION (default: 0s):服务启动多久后开始探测,默认0秒
--retries=N (default: 3):认为检测失败几次为宕机,默认3次

返回值:
0:容器成功是健康的,随时可以使用
1:不健康的容器无法正常工作
2:保留不使用此退出代码

12、指令:ONBUILD

用于在Dockerfile中定义一个触发器
Dockerfile用于build映像文件,此映像文件亦可作为base image被另一个Dockerfile用作FROM指令的参数,
并以之构建新的映像文件
在后面的这个Dockerfile中的FROM指令在build过程中被执行时,将会“触发”创建其base image的Dockerfile文件
中的ONBUILD指令定义的触发器

ONBUILD < Instruction>
尽管任何指令都可注册成为触发器指令,但ONBUILD不能自我嵌套,且不会触发FROM和MAINTAINER指令
使用包含ONBUILD指令的Dockerfile构建的镜像应该使用特殊的标签,例如ruby:2.0-onbuil
在ONBUILD指令中使用ADD或COPY指令应该格外小心,因为新构建过程的上下文在缺少指定的源文件时会失败

13、指令:USER

用于指定运行image时的或运行Dockerfile中任何RUN、CMD或EntRyPoInT指令指定的程序时的用户名或UID
默认情况下,container的运行身份为root用户

USER <user>[:<group>]
或:
USER <UID>[:<GID>]
需要注意的是,<UID>可以为任意数字,但实践中其必须为/etc/ passwd中某用户的有效UID,否则,docker run命令将运行失败

14、指令:ARG

ARG指令类似ENV,定义了一个变量;区别于ENV:用户可以在构建时docker build --build-arg <varname> = <value> 
进行对变量的修改;ENV不可以
如果用户指定了未在Dockerfile中定义的构建参数,那么构建输出警告

ARG <name>[=<default value>]
Dockerfile可以包含一个或多个ARG指令

15、指令:SHELL

SHELL指令允许覆盖用于shell命令形式的默认shell。
Linux上的默认shell是[“/ bin / sh”,“c”],在Windows上是[“cmd”,“/ S”,“/ C”]
SHELL指令必须以JSON格式写入Dockerfile。
SHELL ["executable", "parameters"]

SHELL指令可以多次出现。
每个SHELL指令都会覆盖所有先前的SHELL指令,并影响所有后续指令。

16、指令:STOPSIGNAL

STOPSIGNAL指令设置将发送到容器出口的系统调用信号
此信号可以是与内核的系统调用表中的位置匹配的有效无符号数,例如9,或者SIGNAME格式的信号名,例如SIGKILL。

STOPSIGNAL signal

17、指令:EXPOSE

用于为容器打开指定要监听的端口以实现与外部通信
EXPOSE <port>[/ <protocol>] [<port>[/ <protocol>]

<protocol>用于指定传输层协议,可为tcp或udp二者之一,默认为TCP协议
EXPOSE指令可一次指定多个端口,例如:EXPOSE 11211/udp 11211/tcp

18、指令:WORKDIR

用于为Dockerfile中所有的RUN、CMD、ENTRYPOINT、COPY和ADD指定设定工作目录
WORKDIR <dirpath>


使用例子:
ENV MY_PATH /usr/mytest
WORKDIR $MY_PATH

19、centos vim+ifconfig+jdk8 Dockerfile example

docker run -it 5d0da3dc9764 /bin/bash



1111111111、编写
mkdir myDockerfile
cd myDockerfile/

vim Dockerfile
-----Dockerfile-----start-----$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
FROM centos:7
MAINTAINER [email protected]
ENV MYWORKPATH /usr/local
WORKDIR $MYWORKPATH
#安装vim编辑器
RUN yum -y install vim

#安装ifconfig命令查看网络IP
RUN yum -y install net-tools

#安装java8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把jdk-8u191-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u191-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_191
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

EXPOSE 80
CMD echo $MYWORKPATH
CMD echo "success--------------ok"
CMD /bin/bash
-----Dockerfile-----end-----$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$



2222222222、构建
格式: docker build -t 新镜像名字:TAG .
docker build -t centosjava8:custom1.1 .
# 命令最后的 点 不要忘记了哦


3333333333、运行
docker run -it centosjava8:custom1.1 /bin/bash

20、ubuntu net-tools+iproute2+inetutils-ping Dockerfile example

1111111111、编写
mkdir myUbuntuDockerfile
cd myUbuntuDockerfile/

vim Dockerfile
-----Dockerfile-----start-----$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
FROM ubuntu
MAINTAINER [email protected]
ENV MYWORKPATH /usr/local
WORKDIR $MYWORKPATH
#更新
RUN apt-get update
#安装ifconfig
RUN apt-get install -y net-tools
#安装ip addr
RUN apt-get install -y iproute2
#安装ping
RUN apt-get install -y inetutils-ping

EXPOSE 80
CMD echo $MYWORKPATH
CMD echo "install success--------------ok"
CMD /bin/bash
-----Dockerfile-----end-----$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$



2222222222、构建
-t, --tag list       Name and optionally a tag in the 'name:tag' format
格式: docker build -t 新镜像名字:TAG .
docker build -t myubuntu:1.2 .
# 命令最后的 点 不要忘记了哦


3333333333、运行
docker run -it myubuntu:1.2 /bin/bash

21、虚悬镜像

仓库名、标签都是的镜像,俗称 dangling image

1、 编写Dockerfile
vim Dockerfile

from ubuntu
CMD echo 'action is success'

2、构建镜像
docker build .

3、查看虚悬镜像
docker image ls -f dangling=true

4、删除虚悬镜像(dangling images无存在价值)
docker image prune

22、由Dockerfile发布服务到docker

1、springboot项目jar包
链接: https://gitee.com/michael_linux/spring-security-study/tree/master/dockerfile-use

2、编写 vim Dockerfile

# 基础镜像使用java
FROM java:8
# 作者
MAINTAINER [email protected]
# VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为michael_docker.jar
ADD dockerfile-use.jar michael_docker.jar
# 运行jar包
# RUN bash -c 'touch /michael_docker.jar'
ENTRYPOINT ["java","-jar","/michael_docker.jar"]
#暴露9001端口作为微服务
EXPOSE 9001

3、构建镜像

docker build -t michael_docker:1.1 .

4、运行容器

docker run -d -p 9001:9001 michael_docker:1.1

猜你喜欢

转载自blog.csdn.net/Michael_lcf/article/details/127697820
今日推荐