Detailed explanation and practice of Dockerfile

Detailed explanation of Dockerfile and practice
of Docker's Network
Docker-Compose

Official document: https://docs.docker.com/engine/reference/builder/
Dockerfile is a text file used to build a Docker image. It is a script composed of instructions and parameters required to build an image.

Each command of the dockerfile will build a layer of mirroring, which is generally divided into four parts: basic mirroring information, maintainer information, mirroring operation instructions, container startup execution instructions, which #are annotations in the Dockerfile.

01. Overview of 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. Command: 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. Command: MAINTAINER

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

MAINTAINER <authtor's detail>

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

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

04. Command: COPY

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

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

05. Command: 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. Command: ENV

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

一次只能设置一个
ENV key value
一次可以设置多个键值对
ENV key1=value1 key2=value2
使用例子:
ENV MY_PATH /usr/mytest
WORKDIR $MY_PATH

docker run 命令中设置环境变量:
docker run -e key1=value1 --env key2=value2 ubuntu
docker run --env key1=value1 --env key2=value2 ubuntu

07. Command: VOLUME

1. VOLUMELike -vthe command, the files mapped on the host will not be deleted after the container is deleted.
2. The VOLUME command only declares the directory in the container as an anonymous volume, and does not bind the anonymous volume to the specified directory of the host.
If the VOLUME anonymous volume is declared in the Dockerfile, when the container is started, docker will generate a directory under the host-specific directory to bind the anonymous volume of the container. For example, the docker version mapping directory I tested is: /var/lib/docker/volumes/{随机生成的唯一ID}/_data. (You can docker inspect 容器IDview ).

3. If -va VOLUMEdifferent location is specified, the directory set by -v will prevail. In fact, the purpose of setting the VOLUME command is to avoid data loss when the user forgets to specify -v, so if the user specifies - v, naturally there is no need for the location specified by 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. Command: 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. Command: 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. Command: 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. Command: HEALTH CHECK

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. Command: 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. Command: USER

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

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

14. Command: ARG

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

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

15. Command: SHELL

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

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

16. Command: STOPSIGNAL

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

STOPSIGNAL signal

17. Command: EXPOSE

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

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

18. Command: 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. False mirror

The warehouse name and label are mirror images, commonly known as 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. Publish services to docker by Dockerfile

1. Springboot project jar package
link: https://gitee.com/michael_linux/spring-security-study/tree/master/dockerfile-use

2. Write 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. Build a mirror image

docker build -t michael_docker:1.1 .

4. Run the container

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

Guess you like

Origin blog.csdn.net/Michael_lcf/article/details/127697820