Docker学习6 --- Dockerfile详解

本文详细介绍Dockerfile的常用指令及其用法,包括FROM、LABEL、RUN等,并提供nginx的Dockerfile示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Docker学习6 — Dockerfile + docker build 详解

一、Dockerfile概述

 Docker通过Docerfile自动构建镜像,Dockerfile是一个包含用于组建镜像的文本文件,由一条一条的指令组成。

二、Dockerfile常用指令

指令描述
FROM构建新镜像是基于哪个镜像
LABEL标签
RUN构建镜像时运行的shell命令
COPY拷贝文件或目录到镜像中
ADD解压压缩包并拷贝
ENV设置环境变量
USER为RUN、CMD和ENTRYPOINT执行命令指定运行用户
EXPOSE声明容器运行的服务端口
WORKDIR为RUN、CMD、ENTRYPOINT 、COPY和ADD设置工作目录
VOLUME用于指定持久化目录
ENTRYPOINT配置容器,使其可执行化。配合CMD可省去"application",只使用参数。
ARG用于指定传递给构建运行时的变量
MAINTAINER维护者信息
CMD运行容器时默认执行,如果有多个CMD指令,最后一个生效

FROM指令:

 FROM 指令是最重要的一个且必须为 Dockerfile文件开篇的第一个非注释行,用于为映像文件构建过程指定基准镜像,后续的指令运行于此基准镜像所提供的运行环境 。
 实践中,基准镜像可以是任何可用镜像文件,默认情况下, docker build会在 docker主机上查找指定的镜像文件,在其不存在时,
 则会从 Docker Hub Registry上拉取所需的镜像文件 .如果找不到指定的镜像文件, docker build会返回一个错误信息。

 命令格式:
 	FROM <repository>[:<tag>] 或者 FROM <repository>@<digest>或 FROM <image>
 		<repository>:指定作为base image的名称
 		<tag>:base image的标签,为可选项,省略时默认为 latest;
 		<digest>为校验码

在这里插入图片描述

LABEL

LABEL用于为镜像添加元数据,元数以键值对的形式指定:

命令格式:
	LABEL <key>=<value> <key>=<value> <key>=<value> ...

示例:
	LABEL age="18"  name="小明"  gender="男"

说明:
	使用LABEL指定元数据时,一条LABEL指定可以指定一或多条元数据,指定多条元数据时不同元数据之间通过空格分隔。推荐将所有的元数据通过一条LABEL指令指定,以免生成过多的中间镜像。

RUN:构建镜像时执行的命令

RUN用于指定 docker build过程中运行的程序,其可以是任何命令,但是这里有个限定,一般为基础镜像可以运行的命令,如基础镜像为centos,安装软件命令为yum而不是ubuntu里的apt-get命令。

RUN和CMD都可以改变容器运行的命令程序,但是运行的时间节点有区别,RUN表示在docker build运行的命令,而CMD是将镜像启动为容器运行的命令。
因为一个容器正常只用来运行一个程序,因此CMD一般只有一条命令,如果CMD配置多个,则只有最后一条命令生效。而RUN可以有多个。

RUN用于在镜像容器中执行命令,其有以下两种命令执行方式:
	
	shell执行格式:
	    RUN <command>
	
	exec执行格式:
	    RUN ["executable", "param1", "param2"]

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

第二种语法格式中的参数是一个JSON格式的数组,其中<executable>为要运行的命令,后面的<paramN>为传递给命令的选项或参数;然而,此种格式指定的命令不会以“/bin/sh -c”来发起,
表示这种命令在容器中直接运行,不会作为shell的子进程,因此常见的shell操作如变量替换以及通配符(?,*等)替换将不会进行,不过,如果要运行的没能力依赖此shell特性的话,可以将其替换为类似下面的格式:
		RUN ["/bin/bash","-C","<executable>","<paraml>"]
		注意:json数组中使用双引号
示例:
    RUN apk update
    RUN ["/etc/execfile", "arg1", "arg1"]

说明:RUN指令创建的中间镜像会被缓存,并会在下次构建中使用。如果不想使用这些缓存镜像,可以在构建时指定--no-cache参数,如:docker build --no-cache。

COPY:用于从 Docker主机复制文件至创建的新映像文件

功能类似ADD,但是是不会自动解压文件,也不能访问网络资源

语法:
	COPY <src> ... <dest>或 . COPY ["<src>",... "<dest>"]
		<src>:要复制的源文件或目录,支持使用通配符
		<dest>:目标路径,即正在创建的 image的文件系统路径;建议为 <dest>使用绝对路径,<dest>绝对路径为镜像中的路径,而不是宿主机的路径。否则, COPY指定则以 WORKDIR为其起始路径
	注意:在路径中有空白字符时,通常使用第二种格式 。

文件复制准则

	<src>必须是build上下文中的路径,即只能放在workshop这个工作目录下,不能是其父目录中的文件
	
	如果<src>是目录,其内部文件或者子目录会被递归复制,但<src>目录自身不会被复制
	
	如果指定了多个<src>,或在<src>中使用了通配符,则<dest>必须是一个目录,且dest目录必须以/结尾
	
	如果<dest>事先不存在,它将会被自动创建,这包括其父目录路径

ADD:将本地文件添加到容器中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget

格式:
    ADD <src>... <dest>
    ADD ["<src>",... "<dest>"] 用于支持包含空格的路径

示例:
    ADD hom* /mydir/          # 添加所有以"hom"开头的文件
    ADD hom?.txt /mydir/      # ? 替代一个单字符,例如:"home.txt"
    ADD test relativeDir/     # 添加 "test" 到 `WORKDIR`/relativeDir/
    ADD test /absoluteDir/    # 添加 "test" 到 /absoluteDir/

说明:
	 如果<src>为URL且<dest>不以/结尾,则<src>指定的文件将被下载并直接被创建为<dest>;如果<dest>以/结尾,则文件名URL指定的文件将被直接下载,并保存为<dest>/<filename>,注意,URL不能是ftp格式的url

	 如果<src>是一个本地系统上的压缩格式的tar文件,它将被展开为一个目录,其行为类似于“tar -x”命令,然后,通过URL获取到的tar文件将不会自动展开

	 如果<src>有多个,或其间接或直接使用了通配符,则<dest>必须是一个以/结尾的目录路径;如果<dest>不以/结尾,则其被视作一个普通文件,<src>的内容将被直接写入到<dest>;

ENV:设置环境变量

ENV用于为镜像定义所需的环境变量,并可被 Dockerfile文件中位于其后的其它指令(如 ENV、ADD、COPY等)所调用 ,即先定义后调用。

格式:
    ENV <key> <value>  #<key>之后的所有内容均会被视为其<value>的组成部分,因此,一次只能设置一个变量
	ENV <key>=<value> ...  #可以设置多个变量,每个变量为一个"<key>=<value>"的键值对,如果<key>中包含空格,可以使用\来进行转义,也可以通过""来进行标示;另外,反斜线也可以用于续行
示例:
    ENV myName John Doe
    ENV myDog Rex The Dog
    ENV myCat=fluffy

USER: 指定运行容器时的用户名或 UID,后续的 RUN 也会使用指定用户。使用USER指定用户时,可以使用用户名、UID或GID,或是两者的组合。当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户。

格式:
  USER user
  USER user:group
  USER uid
  USER uid:gid
  USER user:gid
  USER uid:group

示例:
	USER www

 注:
	使用USER指定用户后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT都将使用该用户。镜像构建完成后,通过docker run运行容器时,可以通过-u参数来覆盖所指定的用户。

EXPOSE:指定于外界交互的端口

格式:
	EXPOSE <port> [<port>...]
示例:
    EXPOSE 80 443
    EXPOSE 8080    EXPOSE 11211/tcp 11211/udp
注:  
	EXPOSE并不会让容器的端口访问到主机。要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口

WORKDIR:工作目录,类似于cd命令

格式:
	WORKDIR /path/to/workdir
示例:
    WORKDIR /a  (这时工作目录为/a)
    WORKDIR b  (这时工作目录为/a/b)
    WORKDIR c  (这时工作目录为/a/b/c)
注:  
	通过WORKDIR设置工作目录后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都会在该目录下执行。在使用docker run运行容器时,可以通过-w参数覆盖构建时所设置的工作目录。
VOLUME:用于指定持久化目录
格式:
	  VOLUME ["/path/to/dir"]
示例:
	  VOLUME ["/data"]
	  VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"
注:  
	  一个卷可以存在于一个或多个容器的指定目录,该目录可以绕过联合文件系统,并具有以下功能:

			1 卷可以容器间共享和重用
			2 容器并不一定要和其它容器共享卷
			3 修改卷后会立即生效
			4 对卷的修改不会对镜像产生影响
			5 卷会一直存在,直到没有任何容器在使用它

ENTRYPOINT:配置容器,使其可执行化。配合CMD可省去"application",只使用参数

类似 CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一个单独的可执行程序。

与CMD不同的是,由 ENTRYPOINT启动的程序不会被 docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给 ENTRYPOINT指定指定的程序 .不过, docker run命令的 --entrypoint选项的参数可覆盖ENTRYPOINT指令指定的程序。

格式:
    ENTRYPOINT ["executable", "param1", "param2"] (可执行文件, 优先)
    ENTRYPOINT command param1 param2 (shell内部命令)
示例:
    FROM ubuntu
    ENTRYPOINT ["top", "-b"]
	CMD ["-c"]
注:   
	ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT。Dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令。

ARG:用于指定传递给构建运行时的变量

格式:
	ARG <name>[=<default value>]
示例:
    ARG age
    ARG build_user=nginx
MAINTAINER: 维护者信息
格式:
	MAINTAINER <name>
示例:
    MAINTAINER xiaoming
    MAINTAINER xiaoming@163.com
    MAINTAINER xiaoming <mail@163.com>

CMD:构建容器后调用,也就是在容器启动时才进行调用。

类似于 RUN指令, CMD指令也可用于运行任何命令或应用程序,不过,二者的运行时间点不同 . RUN指令运行于映像文件构建过程中,而 CMD指令运行于基于 Dockerfile构建出的新映像文件启动一个容器时 。
 CMD指令的首要目的在于为启动的容器指定默认要运行的程序,且其运行结束后,容器也将终止;不过, CMD指定的命令其可以被 docker run的命令行选项所覆盖 .在Dockerfile中可以存在多个 CMD指令,但仅最后一个会生效。

格式:
    CMD ["executable","param1","param2"] (执行可执行文件,优先)
    CMD ["param1","param2"] (设置了ENTRYPOINT,则直接调用ENTRYPOINT添加参数)
    CMD command param1 param2 (执行shell内部命令)
示例:
    CMD echo "This is a test." | wc -
    CMD ["/usr/bin/wc","--help"]
注:   
	CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令。

三、通过Dockerfile构建容器镜像

1、docker build命令

docker build命令用于根据给定的Dockerfile和上下文以构建Docker镜像。

2、命令格式

docker build [OPTIONS] <PATH | URL | ->

常用OPTIONS选项说明
	--build-arg,设置构建时的环境变量。
	--no-cache,默认false。设置该选项,将不使用Build Cache构建镜像。
	--pull,默认false。设置该选项,总是尝试pull镜像的最新版本。
	--compress,默认false。设置该选项,将使用gzip压缩构建的上下文。
	--disable-content-trust,默认true。设置该选项,将对镜像进行验证。
	-f,--file, Dockerfile的完整路径,指定Docerfile文件路径,默认值为‘PATH/Dockerfile’。
	--isolation,默认--isolation="default",即Linux命名空间;其他还有process或hyperv。
	--label,为生成的镜像设置metadata。
	--squash,默认false。设置该选项,将新构建出的多个层压缩为一个新层,但是将无法在多个镜像之间共享新层;设置该选项,实际上是创建了新image,同时保留原有image。
	-t,--tag, 镜像的名字及tag,通常name:tag或者name格式;可以在一次构建中为一个镜像设置多个tag。
	--network,默认default。设置该选项,Set the networking mode for the RUN instructions during build。
	 -q ,--quiet,默认false。设置该选项,Suppress the build output and print image ID on success。
	--force-rm,默认false。设置该选项,总是删除掉中间环节的容器。
	--rm,默认--rm=true,即整个构建过程成功后删除中间环节的容器。

PATH | URL | -说明:
	给出命令执行的上下文。
	上下文可以是构建执行所在的本地路径,也可以是远程URL,如Git库、tarball或文本文件等。
	如果是Git库,如https://github.com/docker/rootfs.git#container:docker,则隐含先执行git clone --depth 1 --recursive,到本地临时目录;然后再将该临时目录发送给构建进程。
	构建镜像的进程中,可以通过ADD命令将上下文中的任何文件(注意文件必须在上下文中)加入到镜像中。
	-表示通过STDIN给出Dockerfile或上下文。

3、构建镜像示例

示例1
	docker build -t tomcat:V1 --rm .
	解析:
		-t tomcat:V1: 为构建的镜像标记名称,即镜像名为:tomcat,打标为V1;
		--rm: 整个构建过程成功后删除中间环节的容器;
		-f /path/to/a/Dockerfile: 指定dockerfile路径,不指定的话,默认会读取上下文路径(  .  )下的 dockerfile
		.:  单独的点,意思为根据当前目录下的Dockerfile文件生成镜像


示例2
	docker build -f /path/to/a/Dockerfile .

	解析:		
		-f /path/to/a/Dockerfile: 指定dockerfile路径,不指定的话,默认会读取上下文路径(  .  )下的 dockerfile

示例3
	docker build --add-host=docker:10.1.1.143 .
	解析:
		--add-host:可以使用一个或多个 --add-host 标志将其他主机添加到容器的 /etc/hosts 文件中

四、Dockerfile示例

1、nginx的Dockerfile

# This is nginx Dockerfile
# Version 1.0.0

# Base images 基础镜像
FROM centos:7

#MAINTAINER 维护者信息
MAINTAINER lufei 

#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH

#ADD  需要再宿主机的Dockerfile目录放nginx压缩包,拷过去会自动解压
ADD nginx-1.9.2.tar.gz /usr/local/      
ADD epel-release-latest-7.noarch.rpm /usr/local/  

#RUN 执行以下命令 
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm
RUN yum install -y lftp gcc gcc-c++ make openssl-devel pcre-devel pcre iproute net-tools telnet wget curl gd-devel && yum clean all && rm -rf /var/cache/yum/*
RUN useradd -s /sbin/nologin -M www

#WORKDIR 相当于cd
WORKDIR /usr/local/nginx-1.9.2

RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-http_stub_status_module --with-pcre && make -j 4 && make install \
		ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# 拷贝配置文件,需要再宿主机的Dockerfile目录放配置文件
COPY nginx.conf /usr/local/nginx/conf/nginx.conf


#EXPOSE 映射端口
EXPOSE 80

#CMD 运行以下命令
CMD ["nginx", "-g", "daemon off;"]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

lufei0920

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

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

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

打赏作者

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

抵扣说明:

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

余额充值