0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

镜像构建Dockerfile的介绍

马哥Linux运维 来源:马哥Linux运维 作者:马哥Linux运维 2022-09-06 09:36 次阅读

一、概述

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

官方文档:

https://docs.docker.com/engine/reference/builder/

Dockerfile 示例:

https://github.com/dockerfile/

a3d18e06-2d2f-11ed-ba43-dac502259ad0.png

二、Dockerfile 结构

Dockerfile 结构主要分为四部分:

基础镜像信息

维护者信息

镜像操作指令

容器启动时执行指令 (CMD/ENTRYPOINT)

【温馨提示】Dockerfile 每行支持一条指令,每条指令可携带多个参数(支持&&),支持使用以“#“号开头的注释(jason 文件不支持#注释),但是也非必须满足上面的四点。

三、常用 Dockerfile 操作指令

ARG—— 定义创建镜像过程中使用的变量 ,唯一一个可以在 FROM 之前定义 。

FROM——基于某个镜像, FROM前面只能有一个或多个ARG指令 。

MAINTAINER(已弃用) —— 镜像维护者姓名或邮箱地址 。

VOLUME —— 指定容器挂载点到宿主机自动生成的目录或其他容器

RUN——执行镜像里的命令,跟在 liunx 执行命令一样,只需要在前面加上 RUN 关键词就行。

COPY——复制本地(宿主机)上的文件到镜像。

ADD——复制并解压(宿主机)上的压缩文件到镜像。

ENV——设置环境变量。

WORKDIR —— 为 RUN、CMD、ENTRYPOINT、COPY 和 ADD 设置工作目录,就是切换目录 。

USER —— 为 RUN、CMD、和 ENTRYPOINT 执行命令指定运行用户。

EXPOSE —— 声明容器的服务端口(仅仅是声明) 。

CMD—— 容器启动后执行的命令 ,多个 CMD 只会执行最后一个,跟 ENTRYPOINT 的区别是,CMD 可以作为 ENTRYPOINT 的参数,且会被 yaml 文件里的 command 覆盖。

ENTRYPOINT—— 容器启动后执行的命令 ,多个只会执行最后一个。

HEALTHCHECH —— 健康检查 。

ONBUILD——它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。

LABEL——LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式 ,替换 MAINTAINER。

1)镜像构建(docker build)

dockerbuild-ttext:v1.--no-cache
#要在构建后将映像标记到多个存储库中,请在运行命令-t时添加多个参数
dockerbuild-tshykes/myapp:1.0.2-tshykes/myapp:latest.

###参数解释
#-t:指定镜像名称
# . :当前目录Dockerfile
#-f:指定Dockerfile路径
#--no-cache:不缓存

2)运行容器测试(docker run)

#非交互式运行
dockerruncentos:7.4.1708/bin/echo"Helloworld"

###交互式执行
#-t:在新容器内指定一个伪终端或终端。
#-i:允许你对容器内的标准输入(STDIN)进行交互。
#会登录到docker环境中,交互式
dockerrun-itcentos:7.4.1708/bin/bash
#-d:后台执行,加了-d 参数默认不会进入容器
dockerrun-itdcentos:7.4.1708/bin/bash

###进入容器
#在使用-d 参数时,容器启动后会进入后台。此时想要进入容器,可以通过以下指令进入:
#docker exec -it :推荐大家使用 docker exec -it 命令,因为此命令会退出容器终端,但不会导致容器的停止。
#docker attach:容器退出,会导致容器的停止。
dockerexec-itb2c0235dc53/bin/bash
dockerattachb2c0235dc53

3)ARG

构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。唯一一个可以在 FROM 之前定义 。构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。

语法格式:

ARG<参数名>[=<默认值>]

示例:

#在FROM之前定义ARG,只在FROM中生效
ARGVERSION=laster
FROMcentos:${VERSION}
#在FROM之后使用,得重新定义,不需要赋值
ARGVERSION
RUNecho$VERSION>/tmp/image_version

4)FROM

定制的镜像都是基于 FROM 的镜像 ,【必选项】

语法格式:

FROM[--platform=][AS]
FROM[--platform=][:][AS]
FROM[--platform=][@][AS]

如果引用多平台图像,可选--platform标志可用于指定图像的平台。FROM例如,linux/amd64、 linux/arm64或windows/amd64。默认情况下,使用构建请求的目标平台。全局构建参数可用于此标志的值,例如允许您将阶段强制为原生构建平台 ( --platform=$BUILDPLATFORM),并使用它交叉编译到阶段内的目标平台。

示例:

ARGVERSION=latest
FROMbusybox:$VERSION
#FROM--platform="linux/amd64"busybox:$VERSION
ARGVERSION
RUNecho$VERSION>image_version

5)MAINTAINER(已弃用)

镜像维护者信息

语法格式:

MAINTAINER

示例:

LABELorg.opencontainers.image.authors="SvenDowideit@home.org.au"

6)VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。

作用:

避免重要的数据,因容器重启而丢失,这是非常致命的。

避免容器不断变大。

在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。

语法格式:

#后面路径是容器内的路径,对应宿主机的目录是随机的
VOLUME["<路径1>","<路径2>"...]
VOLUME<路径>

示例:

FROMubuntu
RUNmkdir/myvol
RUNecho"helloworld">/myvol/greeting
VOLUME/myvol

7)RUN

用于执行后面跟着的命令行命令。

语法格式:

RUN (shell形式,命令在 shell 中运行,默认/bin/sh -c在 Linux 或cmd /S /CWindows 上)

RUN ["executable", "param1", "param2"](执行形式)

示例:

#以下三种写法等价
RUN/bin/bash-c'source$HOME/.bashrc;
echo$HOME'

RUN/bin/bash-c'source$HOME/.bashrc;echo$HOME'

RUN["/bin/bash","-c","source$HOME/.bashrc;echo$HOME"]

8)COPY

拷贝(宿主机)文件或目录到容器中,跟 ADD 类似,但不具备自动下载或解压的功能 。所有新文件和目录都使用 0 的 UID 和 GID 创建,除非可选--chown标志指定给定的用户名、组名或 UID/GID 组合以请求复制内容的特定所有权。

语法格式:

COPY[--chown=:]...
COPY[--chown=:]["",...""]

示例:

#添加所有以“hom”开头的文件:
COPYhom*/mydir/
# ?替换为任何单个字符,例如“home.txt”。
COPYhom?.txt/mydir/
#使用相对路径,并将“test.txt”添加到/relativeDir/:
COPYtest.txtrelativeDir/
#使用绝对路径,并将“test.txt”添加到/absoluteDir/
COPYtest.txt/absoluteDir/

#修改文件权限
COPY--chown=55:mygroupfiles*/somedir/
COPY--chown=binfiles*/somedir/
COPY--chown=1files*/somedir/
COPY--chown=10:11files*/somedir/

9)ADD

拷贝文件或目录到容器中,如果是 URL 或压缩包便会自动下载或自动解压 。

ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。

ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

语法格式:

ADD[--chown=:]...
ADD[--chown=:]["",...""]

示例:

#通配符
ADDhom*/mydir/
#相对路径,拷贝到WORKDIR目录下relativeDir/
ADDtest.txtrelativeDir/
#绝对路径
ADDtest.txt/absoluteDir/

#更改权限
ADD--chown=55:mygroupfiles*/somedir/
ADD--chown=binfiles*/somedir/
ADD--chown=1files*/somedir/
ADD--chown=10:11files*/somedir/

ADD 和 COPY 的区别和使用场景:

ADD 支持添加远程 url 和自动提取压缩格式的文件,COPY 只允许从本机中复制文件

COPY 支持从其他构建阶段中复制源文件(--from)

根据官方 Dockerfile 最佳实践,除非真的需要从远程 url 添加文件或自动提取压缩文件才用 ADD,其他情况一律使用 COPY

10)ENV

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

语法格式:

ENV==...
#省略"="此语法不允许在单个ENV指令中设置多个环境变量,并且可能会造成混淆。
ENV

示例:

ENVJAVA_HOME=/usr/local/jdk
ENVMY_NAME="JohnDoe"MY_DOG=RexTheDog
MY_CAT=fluffy
#此语法不允许在单个ENV指令中设置多个环境变量,并且可能会造成混淆。
ENVJAVA_HOME/usr/local/jdk

11)WORKDIR

指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。

语法格式:

WORKDIR<工作目录路径>

示例:

FROMbusybox
ENVFOO=/bar
WORKDIR${FOO}#WORKDIR/bar

12)USER

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

语法格式:

USER<用户名>[:<用户组>]
USER[:]

示例:

FROMbusybox
RUNgroupadd--system--gid=9999admin&&useradd--system--home-dir/home/admin--uid=9999--gid=adminadmin
USERadmin:admin
#USER9999:9999

13)EXPOSE

暴露端口 ,仅仅只是声明端口。

作用:

帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。

在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。

语法格式:

#默认情况下,EXPOSE假定 TCP。
EXPOSE[/...]

示例:

EXPOSE80/TCP443/TCP
EXPOSE80443
EXPOSE80/tcp
EXPOSE80/udp

14)CMD

类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:CMD 在构建镜像时不会执行,在容器运行 时运行。

语法格式:

CMD
CMD["<可执行文件或命令>","","",...]
CMD["","",...]#该写法是为ENTRYPOINT指令指定的程序提供默认参数

推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

示例:

CMDcat/etc/profile
CMD["/bin/sh","-c","/etc/profile"]

注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

15)ENTRYPOINT

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

语法格式:

# exec形式,这是首选形式:
ENTRYPOINT["executable","param1","param2"]
#外壳形式:
ENTRYPOINTcommandparam1param2

示例:

FROMubuntu
ENTRYPOINT["top","-b"]
#CMD作为ENTRYPOINT参数
CMD["-c"]
#与下面的等价
ENTRYPOINT["top","-b-c"]
ENTRYPOINTtop-b-c

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

16)HEALTHCHECK

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

语法格式:

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

选项CMD有:

--interval=DURATION(默认30s:):间隔,频率

--timeout=DURATION(默认30s:):超时时间

--start-period=DURATION(默认0s:):为需要时间引导的容器提供初始化时间, 在此期间探测失败将不计入最大重试次数。

--retries=N(默认3:):重试次数

命令的exit status指示容器的运行状况。可能的值为:

0:健康状态,容器健康且已准备完成。

1:不健康状态,容器工作不正常。

2:保留,不要使用此退出代码。

示例:

FROMnginx
MAINTAINERSecuritit
HEALTHCHECK--interval=5s--timeout=3s
CMDcurl-fhttp://localhost/||exit1
CMD["usr/sbin/nginx","-g","daemonoff;"]

17)ONBUILD

ONBUILD 是一个特殊的指令,它后面跟的是其它指令,比如 RUN, COPY 等,而这些指令,在当前镜像构建时并不会被执行。只有当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行。

语法格式:

ONBUILD<其它指令>

示例:

FROMnode:slim
RUNmkdir/app
WORKDIR/app
ONBUILDCOPY./package.json/app
ONBUILDRUN["npm","install"]
ONBUILDCOPY./app/
CMD["npm","start"]

18)LABEL

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式。用来替代 MAINTAINER。

语法格式:

LABEL===...

示例:比如我们可以添加镜像的作者

LABELorg.opencontainers.image.authors="runoob"

四、ARG 和 ENV 的区别

ARG 定义的变量只会存在于镜像构建过程,启动容器后并不保留这些变量

ENV 定义的变量在启动容器后仍然保留

五、CMD,ENTRYPOINT,command,args 场景测试

当用户同时在 kubernetes 中的 yaml 文件中写了command和args的时候,默认是会覆盖DockerFile中的命令行和参数,完整的情况分类如下:

1)command 和 args 不存在场景测试

如果 command 和 args 都没有写,那么用DockerFile默认的配置。

Dockerfile

FROMcentos

COPYtest.sh/

RUNchmod+x/test.sh
###ENTRYPOINT将作为的子命令启动/bin/sh-c,它不会传递参数,要传递参数只能这样传参
#ENTRYPOINT["/bin/sh","-c","/test.shENTRYPOINT"]
ENTRYPOINT["/test.sh","ENTRYPOINT"]
CMD["CMD"]

/tmp/test.sh

#!/bin/bash

echo$*

构建

dockerbuild-ttest1:v1-fDockerfile.

yaml 编排

cat<< EOF >test1.yaml
apiVersion:apps/v1
kind:Deployment
metadata:
name:test
spec:
replicas:1
selector:
matchLabels:
app:test
template:
metadata:
labels:
app:test
spec:
nodeName:local-168-182-110
containers:
-name:test
image:test:v1
#command:['/bin/sh','-c','/test.sh']
#args:['args']
EOF

执行

kubectlapply-ftest.yaml

2)command 存在,但 args 存在场景测试

如果 command 写了,但 args 没有写,那么 Docker 默认的配置会被忽略而且仅仅执行.yaml文件的 command(不带任何参数的)。

cat<< EOF >test2.yaml
apiVersion:apps/v1
kind:Deployment
metadata:
name:test2
spec:
replicas:1
selector:
matchLabels:
app:test2
template:
metadata:
labels:
app:test2
spec:
nodeName:local-168-182-110
containers:
-name:test2
image:test:v1
#['/bin/sh','-c','/test.sh command','hello'],加了'/bin/sh','-c',也是不能外部传参,不会输出hello,只能通过这样传参,['/bin/sh','-c','/test.sh command'];CMD里面的参数会被忽略
command:['/test.sh']
#command带参数
#command:['/test.sh','command']
#args:['args']
EOF

3)command 不存在,但 args 存在场景测试

如果 command 没写,但 args 写了,那么 Docker 默认配置的 ENTRYPOINT 的命令行会被执行,但是调用的参数是.yaml中的 args,CMD 的参数会被覆盖,但是 ENTRYPOINT 自带的参数还是会执行的。

cat<< EOF >test3.yaml
apiVersion:apps/v1
kind:Deployment
metadata:
name:test3
spec:
replicas:1
selector:
matchLabels:
app:test3
template:
metadata:
labels:
app:test3
spec:
nodeName:local-168-182-110
containers:
-name:test3
image:test:v1
#['/bin/sh','-c','/test.sh command','hello'],加了'/bin/sh','-c',也是不能外部传参,不会输出hello,只能通过这样传参,['/bin/sh','-c','/test.sh command'];CMD里面的参数会被忽略
#command:['/test.sh']
#command带参数
#command:['/test.sh','command']
args:['args']
EOF

4)command 和 args 都存在场景测试

如果如果 command 和 args 都写了,那么 Docker 默认的配置被忽略,使用.yaml的配置。

cat<< EOF >test4.yaml
apiVersion:apps/v1
kind:Deployment
metadata:
name:test4
spec:
replicas:1
selector:
matchLabels:
app:test4
template:
metadata:
labels:
app:test4
spec:
nodeName:local-168-182-110
containers:
-name:test4
image:test:v1
#['/bin/sh','-c','/test.sh command','hello'],加了'/bin/sh','-c',也是不能外部传参,不会输出hello,只能通过这样传参,['/bin/sh','-c','/test.sh command'];CMD里面的参数会被忽略
#command:['/test.sh']
#command带参数,command和args都会带上
command:['/test.sh','command']
args:['args']
EOF

镜像构建 Dockerfile 的介绍就到这里了,有疑问的小伙伴欢迎给我留言哦!

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 容器
    +关注

    关注

    0

    文章

    494

    浏览量

    22050
  • 镜像
    +关注

    关注

    0

    文章

    164

    浏览量

    10701
  • 服务端
    +关注

    关注

    0

    文章

    66

    浏览量

    6994

原文标题:Docker 镜像构建保姆级入门实战指南

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    介绍一下linux环境下docker的使用流程

    dockerhub 网站,注册一个账号:创建镜像仓库:构建镜像通过上面的步骤,我们创建了一个镜像仓库;这一步,我们要构建一个
    发表于 04-27 15:03

    构建ARM64版本nacos docker镜像

    在适配过程中有大量合作伙伴用到nacos且采用容器化部署,dockerhub未提供官方镜像,因此需要在鲲鹏服务器自定义构建构建前提:Docker已部署构建步骤:1、下载包含
    发表于 06-16 14:29

    介绍一款非常方便的java领域docker镜像构建工具

    前言本文主要介绍的是google开源的一个java领域的docker构建工具jib.目前在github上的start有8.5k,fork有784,是一款非常方便的java领域docker构建
    发表于 07-19 17:41

    一文详解DockerFile基础知识

    DockerFile用来构建docker的镜像文件,可以理解为命令参数脚本。构建步骤编写一个DockerFile文件Docker build
    发表于 09-15 15:54

    Dockerfile构建环境报错如何解决?

    我正在使用以下 Dockerfile 来设置构建环境:修改local.conf文件,执行bitbake命令后,收到如下错误:ERROR: Task (virtual:native:/home
    发表于 04-11 06:17

    全面详解Dockerfile文件

    Docker 可以通过读取 Dockerfile 中的指令自动构建镜像Dockerfile 是一个文本文档,其中包含了用户创建镜像的所有命
    的头像 发表于 09-22 15:38 1860次阅读

    如何创建 Docker 镜像的能力

    本文将带大家继续深入了解 Dockerfile 镜像创建过程中最重要的配置文件内容,更加透彻地了解整个容器镜像的创建过程。
    的头像 发表于 09-16 09:39 1102次阅读

    Dockerfile的最佳实践

    随着应用的容器化、上云后,将伴随着 Docker 镜像构建构建 Docker 镜像成为了最基本的一步,其中 Dockerfile 便是用
    的头像 发表于 01-20 10:59 971次阅读
    <b class='flag-5'>Dockerfile</b>的最佳实践

    Docker入门指南之什么是Dockerfile

    发时所构建镜像或者通过Dockerfile文件构建一个新的镜像开始工作 * 对于运维人员:在部署时,可以实现应用的无缝移植
    的头像 发表于 02-06 15:25 621次阅读
    Docker入门指南之什么是<b class='flag-5'>Dockerfile</b>

    新一代更强大的镜像构建工具Earthly

    在使用 Earthly 进行构建镜像时目前强依赖于 buildkit,Earthly 通过 buildkit 支持了一些 Dockerfile 的扩展语法,同时将 Dockerfile
    的头像 发表于 03-30 11:21 889次阅读

    Dockerfile定义Docker镜像构建过程

    了解Dockerfile Dockerfile 是一个文本文件,用于定义 Docker 镜像构建过程。它以指令的形式描述了如何构建
    的头像 发表于 09-30 10:22 2522次阅读

    构建docker镜像应该遵循哪些原则

    构建 Docker 镜像时,应遵循以下原则: 单一职责:每个镜像应只包含一个应用或服务,避免将多个应用或服务放在同一个镜像中。这样可以确保镜像
    的头像 发表于 11-23 09:41 989次阅读

    如何使用dockerfile创建镜像

    Docker是一个开源的平台,用于快速构建、打包、部署应用程序的容器化工具。而Dockerfile是一个文本文件,包含了一组可自动化构建Docker镜像的指令。本文将详细
    的头像 发表于 11-23 09:52 716次阅读

    手动构建Docker镜像的方法

    不推荐使用docker commit命令,而应该使用更灵活、更强大的dockerfile构建docker镜像
    的头像 发表于 08-05 15:30 482次阅读
    手动<b class='flag-5'>构建</b>Docker<b class='flag-5'>镜像</b>的方法

    提升DevOps效率,从基础到进阶的Dockerfile编写技巧

    目录 Dockerfile 基本结构 指令 创建镜像(centos版) 创建镜像(alpine版) 基本结构 Dockerfile 是一个文本格式的配置文件,用户可以使用
    的头像 发表于 11-26 09:44 62次阅读
    提升DevOps效率,从基础到进阶的<b class='flag-5'>Dockerfile</b>编写技巧