Docker全系列 - Dockerfile详解

149 阅读5分钟

DockreFile详解

什么是dockerfile?

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明

一个完整的Dockerfile包含了四个功能分区,编写顺序依次为基础镜像区、描述信息区、安装镜像执行指令区、容器启动执行指令区

Dockerfile以“#”号作为文件注释,但是字符串中间的“#”号不会被判定为注释,如下述示例2、3中的“#”不会被判定为注释符1):# 我是一条dockerfile的注释2):RUN echo 'hello # dockerfile'3):RUN apt-get update \
            # install some packages
            && apt-get install -y cron

Docker参数说明

基础镜像区

(1):FROM 声明自定义镜像的基础镜像

FROM [镜像名称]:[tag编号]

# 一个Dockerfile中只会生效一个FROM标签,如果定义了多个FROM标签只会调用第一个
# FROM为必填项

描述信息区

(1):LABEL 声明镜像的作者、版本、构建时间、描述等一系列信息,此处可以声明任何信息

LABEL maintainer="PSQ"
LABEL version="v0.01"
LABEL date="2022-12-07"
LABEL description="我是一个描述标签"

# 可以根据需要添加多个LABEL标签
# LABEL非必填项

(2): MAINTAINER 声明镜像作者

MAINTAINER PSQ

# 一个Dockerfile中仅能声明一次MAINTAINER
# MAINTAINER非必填项

安装镜像执行指令区

(1):USER 执行Dockerfile中的shell指令时指定用户

USER root
或者
USER [用户名]:[组名称]

# 一个Dockerfile中仅能声明一次USER,如果定义了多个USER则只会调用最后一个
# USER非必填项

(2):EXPOSE 指定Dockerfile中的容器需要暴露的端口

EXPOSE 80

# 一个Dockerfile中可以声明多个EXPOSE标签,也可以在一个EXPOSE中声明暴露多个端口,使用空格区分开即可
# EXPOSE指令仅标识容器暴露的端口,并不会真正开放这些端口。如果要真正开放容器暴露的端口,还需要使用-p或-P选项来指定容器端口与主机端口的映射关系。
# EXPOSE非必填项

(3):WORKDIR 指定Dockerfile中的工作目录

WORKDIR /path

# 一个Dockerfile中仅能声明一次WORKDIR,如果有多个WORKDIR则只会调用最后一个
# WORKDIR非必填项
# 如果需要多个目录工作可以参考如下格式

WORKDIR /path-1
[ADD | COPY | RUN | CMD | ENTRYPOINT] your-shell

WORKDIR /path-2
[ADD | COPY | RUN | CMD | ENTRYPOINT] your-shell
....

(4):ADD 拷贝文件或目录到镜像中

ADD [文件、目录所在路径] [镜像中的目标路径]

# 一个Dockerfile中可以声明多个ADD标签,如果复制的文件后缀为.tar、.tar.gz、.tgz、.gz、.bz2后缀会被自动解压
# ADD非必填项

(5):COPY

COPY [文件、目录所在路径] [镜像中的目标路径]

# 一个Dockerfile中可以声明多个COPY标签,与ADD的区别在于压缩包文件不会被自动解压
# COPY非必填项

(6):VOLUME 把宿主机的目录映射到容器中

VOLUME  ["[宿主机目录-1]:[容器映射的目录-1]","[宿主机目录-2]:[容器映射的目录-2]"]
或者
VOLUME [宿主机目录-1]:[容器映射的目录-1]

# 一个Dockerfile中可以有多个VOLUME标签
# VOLUME标签非必填项

(7):ARG 定义一个变量

ARG name=value

# 一个Dockerfile中可以有多个ARG标签
# 定义成功后可以在别的标签中是用$name来使用它,如:RUN echo "Hello $name" 会打印结果 “hello value”
# ARG标签非必填项

(8):RUN 构建镜像时需要运行的命令(在宿主机执行)

RUN ["echo", "hello dockerfile", ">", "test.txt"]
或者
RUN echo 'hello dockerfile' > test.txt

# 一个Dockerfile中可以有多个RUN标签
# 一个Dockerfile中应至少有一个RUN标签

(9):ENV 设置容器内的环境变量(在容器内执行)

 ENV name1=value1
 
 # 一个Dockerfile中可以有多个ENV标签
 # ENV标签非必填项

容器启动执行指令区

(1):CMD 指定容器启动时要运行的命令

CMD ['/bin/bash', "xxx"]
或者
CMD /bin/bash xxx

# 一个Dockerfile中可以有多个CMD标签,存在多个CMD标签时会被依次执行
# 一个Dockerfile中至少要有一个CMD标签

(2):ENTRYPOINT

 ENTRYPOINT ['/bin/bash', "xxx"]
或者
ENTRYPOINT /bin/bash xxx

# 一个Dockerfile中可以有多个ENTRYPOINT标签,存在多个ENTRYPOINT标签时会被依次执行
# ENTRYPOINT标签与CMD标签作用想用,区别在于不能被用户指定的命令覆盖,而CMD的命令可以被用户指定的命令覆盖
# CMD与ENTRYPOINT两者选其一即可

Dockerfile示例

[root@localhost ~] vim Dockerfile

FROM centos:7

# 我声明了这个dockerfile的备注信息
LABEL manager="PSQ"
LABEL date="2022-12-08"
LABEL description="这是一个测试案例"

RUN ["echo", "Dockerfile开始工作啦~"]

# 我指定了这个dockerfile的运行角色为root
USER root

# 我向容器里复制了一个txt后缀的文本文件
ADD test.txt /root/test.txt


# 准备工作完成现在开始构建容器啦

# 我在容器里运行了一条yum update -y的指令
CMD ["yum", "update", "-y"]

# 我用yum安装了几个常用的工具
CMD ["yum", "install", "-y", "lsof", "wget", "htop"]

OK,完成上述一个简单的实例后,我们就可以开始尝试运行这个dockerfile了

 [root@localhost ~] docker build -t [你的镜像名称叫啥名字] -f Dockerfile [你的Dockerfile文件在哪个目录,如果在当前目录使用.号即可]

# 当结果底部打印了如下内容即表示你的镜像构建成功啦
Successfully built [sha256哈希码]
Successfully tagged [你的镜像名称叫啥名字]:latest

# 最后就是使用docker run -d -p -v --name  xxxx来运行你构建的容器即可