DockerFile

Dockerfile是一个文本文件,其中包含了一系列指令,用于自动化构建Docker镜像。这些指令描述了如何从一个基础镜像开始,安装所需的软件包、复制文件、设置环境变量等,最终生成一个自定义的Docker镜像。Dockerfile使得构建过程可重复、可移植,并且方便在不同环境中共享和使用。

Dockerfile通常位于项目的根目录下,通过执行docker build命令,Docker会读取Dockerfile中的指令,按照顺序执行,并构建出一个新的Docker镜像。这个镜像可以被推送到Docker仓库中,供其他人使用,或者在本地运行容器实例。

Dockerfile中的指令通常包括指定基础镜像、设置工作目录、复制文件、安装软件包、设置环境变量等。例如,你可以使用FROM指令指定一个基础镜像,COPY指令将项目文件复制到镜像中,RUN指令执行一些命令(如安装软件包),以及CMDENTRYPOINT指令指定容器启动时运行的命令。

使用Dockerfile的好处是,你可以将构建镜像的过程以文本形式记录下来,这样其他人可以轻松地按照相同的步骤构建出相同的镜像。此外,Dockerfile还可以作为项目的一部分进行版本控制,方便团队之间的协作和代码审查。

总的来说,Dockerfile是Docker镜像构建的核心文件,它描述了如何从基础镜像构建出一个自定义的Docker镜像,使得构建过程更加自动化、可重复和可移植。

Dockerfile命令执行规则

  • 每条保留字指令都必须为大写且后面要跟随至少一个参数

  • 指令按照从上到下,顺序执行

  • #代表注释

  • 每条指令都会创建一个新的镜像层,并对镜像进行提交

1、应用程序运行流程

2、三者之间的关系

Dockerfile 是软件的原材料,Docker 镜像是软件的交付品,而 Docker 容器则可以认为是软件的运行态。从应用软件的角度来看,Dockerfile、Docker 镜像与 Docker 容器分别代表软件的三个不同阶段,Dockerfile 面向开发,Docker 镜像成为交付标准,Docker 容器则涉及部署与运维,综上所述,Dockerfile、Docker镜像和Docker容器三者共同协作,使得应用程序的打包、分发、部署和运行变得更加简单、高效和安全。Dockerfile定义了如何构建镜像,Docker镜像作为模板用于创建容器实例,而Docker容器则负责在隔离的环境中运行应用程序。这种协同工作的方式使得Docker成为了一个强大的应用容器引擎,为开发人员和运维人员提供了极大的便利。

3、Dockerfile命令

Dockerfile 指令 说明
FROM 指定基础镜像,用于后续的指令构建。
MAINTAINER 指定Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令)
LABEL 添加镜像的元数据,使用键值对的形式。
RUN 在构建过程中在镜像中执行命令。
CMD 指定容器创建时的默认命令。(可以被覆盖)
ENTRYPOINT 设置容器创建时的主要命令。(不可被覆盖)
EXPOSE 声明容器运行时监听的特定网络端口。
ENV 在容器内部设置环境变量。
ADD 将文件、目录或远程URL复制到镜像中。
COPY 将文件或目录复制到镜像中。
VOLUME 为容器创建挂载点或声明卷。
WORKDIR 设置后续指令的工作目录。
USER 指定后续指令的用户上下文。
ARG 定义在构建过程中传递给构建器的变量,可使用 "docker build" 命令设置。
ONBUILD 当该镜像被用作另一个构建过程的基础时,添加触发器。
STOPSIGNAL 设置发送给容器以退出的系统调用信号。
HEALTHCHECK 定义周期性检查容器健康状态的命令。
SHELL 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。

1 FROM 指定构建镜像的基础镜像,必须为Dockerfile中的第一个命令

FROM:基础镜像,当前镜像是基于哪个镜像的,必须为 Dockerfile 的第一个指令

bash 复制代码
# 格式
FROM image
FROM image[:tag]
# 示例
FROM nginx
# tag不填,默认使用latest版本

2 MAINTAINER 镜像作者信息 (已过时,推荐使用LABEL)

复制代码
# 格式
MAINTAINER <name>
# 示例:
MAINTAINER wuzhibin
MAINTAINER name wuzhibin

3 LABEL:为镜像指定标签

bash 复制代码
# 格式
LABEL key1=value1 key2=value2
# 示例:
LABEL maintainer="wuzhibin

4 RUN:容器构建时需要运行的指令

bash 复制代码
# 格式
RUN <命令行命令>
RUN ["可执行文件", "参数1", "参数2"]
# 示例:  
RUN ./test.php dev offline
RUN ["./test.php", "dev", "offline"]
 
# Dockerfile 的指令每执行一次都会在 docker上新建一层会镜像空间增大
FROM centos
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
# 如上使用了三层通过 && 在一层中执行
FROM centos
RUN yum -y install wget \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && tar -xvf redis.tar.gz

5 CMD类似于 RUN 指令,用于运行程序,但二者运行的时间点不同CMD 在docker run 时运行,RUN 是在 docker build。为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

bash 复制代码
# 格式:
CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
# 示例:
CMD echo "hello world."
CMD ["python","manager.py", "runserver"]
ENTRYPOINT ["/usr/local/bin/my_command"]  
# 设置CMD,为ENTRYPOINT指定的程序提供默认参数  
CMD ["arg1", "arg2"]
# 如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效

6 ENTRYPOINT类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。

bash 复制代码
# 格式:
ENTRYPOINT ["executable", "param1", "param2"] 
ENTRYPOINT command param1 param2 
# 示例:
ENTRYPOINT ["ps", "-aux"]
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参 
docker run  nginx:test  # 执行默认CMD的命令nginx -c /etc/nginx/nginx.conf
docker run  nginx:test -c /etc/nginx/new.conf # 覆盖CMD命令 docker run  nginx:test -c /etc/nginx/new.conf
# 如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

7 EXPOSE仅仅只是声明端口

bash 复制代码
# 格式:
EXPOSE <端口1> [<端口2>...]
# 示例:
EXPOSE 80 443
EXPOSE 8080
EXPOSE 11211/tcp 11211/udp
# 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口

8 ENV设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

bash 复制代码
# 格式:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...进行转义,也可以通过""来进行标示;另外,反斜线\也可以用于续行
# 示例:
ENV MYPATH /usr/local
ENV MYPATH1=/usr1/local MYPATH2=/usr2/local \
MYPATH3=/usr3/local
# 在后续的指令中可以通过 $NODE_VERSION 引用前面设置的环境变量值

9 ADD 将本地文件添加到容器中,ADD 指令和 COPY 的使用格类似,ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>; 访问网络资源时能自动下载。ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。

bash 复制代码
# 格式:
ADD src...dest
ADD ["src",... "dest"] 用于支持包含空格的路径
# 示例:
ADD hom* /mydir/              # 添加所有以"hom"开头的文件 到 /mydir/
ADD hom?.txt /mydir/          # ? 替代一个单字符,例如:"home.txt"
ADD test.tar /mydir/    # 自动解压缩test.tar,并添加到 /mydir/

10 COPY 将从构建上下文目录中 <源路径> 的文件 / 目录复制到新的一层的镜像内的 < 目标路径 > 位置

bash 复制代码
# 格式
COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]
# 示例
COPY hom* /mydir/
COPY hom?.txt /mydir/
# COPY 不会自动解压文件,也不能访问网络资源

11 VOLUME 定义匿名数据卷,用于数据保存和持久化工作

bash 复制代码
# 格式:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
# 示例:
VOLUME ["/data1"]
VOLUME ["/data1", "/data2", "/data3"]
# 在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

12 WORKDIR 指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。

bash 复制代码
# 格式:
WORKDIR <工作目录路径>
# 示例:
WORKDIR /home  # 指定工作目录并进入这个目录
# 通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。和RUN cd /home的区别时这个命令只在本层有效,WORKDIR的命令在以后各层都有效

13 USER 用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)

bash 复制代码
# 格式:
USER <用户名>[:<用户组>]
# 示例:
USER myuser
USER myuser:mygroup
# 可以通过-u参数来覆盖所指定的用户。

14 ARG 构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。

bash 复制代码
# 格式:
ARG <参数名>[=<默认值>]
# 示例
ARG age=20
# 构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

15 ONBUILD 用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令

bash 复制代码
# 格式:
ONBUILD [INSTRUCTION]
# 示例:
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
# 当所构建的镜像被用做其它镜像当作基础镜像时,该镜像中的触发器将会被触发

16 STOPSIGNAL 指令用于设置容器接收到的停止信号。当您执行 docker stop 命令来停止容器时,该命令默认会发送一个 SIGTERM 信号给容器。STOPSIGNAL 允许您改变这个默认行为,指定一个不同的信号来停止容器。

bash 复制代码
# 格式:
STOPSIGNAL signal
# 示例:
STOPSIGNAL SIGKILL
STOPSIGNAL 9
# 用于设置容器内进程停止信号,在docker stop时如果没有设置**STOPSIGNAL**  docker默认会使用SIGTERM信号发送

STOPSIGNAL示例

bash 复制代码
# sotp_niganl.py
import sys
import time
import signal
​
​
sys.stdout = open("output.txt", "a")
​
def cleanup(signum, frame):
    print("Cleaning up resources....", flush=True)
    print(signum, frame)
    time.sleep(2)
    print("Cleanup complte!", flush=True)
    exit()
​
​
​
signal.signal(signal.SIGTERM, cleanup)
​
​
while True:
    print("Running....", flush=True)
    time.sleep(1)
复制代码
Dockerfile文件
bash 复制代码
FROM python:latest
​
COPY stop_signal.py /stop_signal.py
​
STOPSIGNAL SIGQUIT
​
CMD ["python3", "/stop_signal.py"]
bash 复制代码
​# 编译
docker build . -t my_signal
# 运行
docker run -ti -d --name=my_contain my_signal

17 HEALTHCHECK 用于指定某个程序或者指令来监控 docker 容器服务的运行状态。

bash 复制代码
# 格式:
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。

18 SHELL 指令允许覆盖用于 shell 形式的命令的默认 shell。在 Linux 上,默认 shell 是 ["/bin/sh", "-c"],而在 Windows 上,默认 shell 是 ["cmd", "/S", "/C"]SHELL 指令必须以 JSON 格式写入 Dockerfile 中。SHELL 指令在 Windows 上特别有用,在 Windows 上有两个常用且完全不同的本机shell:cmdpowershell,以及可用的替代 shell,包括 shSHELL 指令可以出现多次。每条 SHELL 指令都将覆盖所有先前的 SHELL 指令,并影响所有后续指令。

bash 复制代码
FROM microsoft/windowsservercore
​
# Executed as cmd /S /C echo default
RUN echo default
​
# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default
​
# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]  # 执行之后后续的命令不需要添加powershell -command 
RUN Write-Host hello
​
# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S", "/C"]
RUN echo hello
# 当它们的 shell 形式在 Dockerfile 中使用时,以下指令可能会受到 SHELL 指令的影响:RUN,CMD 和 ENTRYPOINT。

4 Dockerfile 示例

centos 构建一个nginx镜像

bash 复制代码
#基准镜像
FROM centos:7
#作者信息
MAINTAINER "nginx"
#工作目录
WORKDIR /usr/local/src/ 
#定义环境变量
ENV NG_VERSION nginx-1.21.0 
#安装epel仓库
RUN yum -y install epel-release 
#安装wget
RUN yum -y install wget 
#下载nginx文件并解压
RUN wget http://nginx.org/download/$NG_VERSION.tar.gz && tar xzvf $NG_VERSION.tar.gz 
#安装编译依赖包
RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel && yum install -y pcre-devel libxslt-devel gd-devel GeoIP GeoIP-devel GeoIP-data
#清理仓库
RUN yum clean all 
#创建nginx用户
RUN useradd -M -s /sbin/nologin nginx 
#切换工作目录
WORKDIR /usr/local/src/$NG_VERSION 
#编译安装nginx
RUN ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-file-aio --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_geoip_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_stub_status_module && make && make install
#复制测试页面到容器中
ADD index.html /usr/local/nginx/html 
#设置容器中要挂在到宿主机的目录
VOLUME /usr/local/nginx/html 
#设置sbin环境变量
ENV PATH /usr/local/nginx/sbin:$PATH 
#暴露80端口
EXPOSE 80/tcp 
ENTRYPOINT ["nginx"]
CMD ["-g","daemon off;"]
#当ENTRYPOINT和CMD连用时,CMD的命令是ENTRYPOINT命令的参数,两者连用相当于nginx -g "daemon off;"而当一起连用的时候命令格式最好一致(这里选择的都是json格式的是成功的,如果都是sh模式可以试一下)
bash 复制代码
mkdir nginx
cd nginx/
vim index.html
<h1> docker nginx build successful</h1>
# 将上面的内容复制到Dokcerfile中
# 构建镜像
docker build ./ -t centos7_nginx
# 运行容器
docker run --name mynginx -d -p 8123:80 centos7_nginx

访问 ip: 8123

上一章: docker 数据卷-CSDN博客

相关推荐
阿里嘎多学长20 分钟前
docker怎么部署高斯数据库
运维·数据库·docker·容器
明 庭41 分钟前
Ubuntu下通过Docker部署Caddy服务器
服务器·ubuntu·docker
G_whang2 小时前
windos 安装docker
运维·docker·容器
Mitch3112 小时前
【漏洞复现】CVE-2021-45788 SQL Injection
sql·web安全·docker·prometheus·metersphere
运维小文2 小时前
K8S中的PV、PVC介绍和使用
docker·云原生·容器·kubernetes·存储
CYX_cheng3 小时前
Docker挂载
docker
阿松哥哥20185 小时前
linux环境使用源码方式安装nginx(centos)
linux·nginx·centos
奉孝6 小时前
docker基础
后端·docker
编程、小哥哥7 小时前
在 Docker 中部署 Jenkins,并完成项目的构建和发布
servlet·docker·jenkins
云上的阿七8 小时前
云计算中的容器技术(如Docker)是什么?
docker·容器·云计算