【云原生 · Docker】轻松学会dockerfile构建镜像

news2024/11/26 18:22:04

目录

🍉dockerfile是什么

🍉镜像的缓存特性

🍉dockerfile命令

🍒FROM

🍒RUN

🍒CMD

🍒LABEL

🍒EXPOSE

🍒ENV

🍒ADD

🍒COPY

🍒ENTRYPOINT

🍒VOLUME

🍒USER

🍒WORKDIR

🍒ARG

🍒ONBUILD

🍒STOPSIGNAL


    🦐博客主页:大虾好吃吗的博客

    🦐专栏地址:云原生专栏

dockerfile是什么

docker中并不建议用户通过commit方式来构建镜像,主要原因如下:

  1. 这是一种手工创建镜像的方式,容易出错,效率低且可重复性弱。比如要在 debian base 镜像中也加入vi,还得重复前面的所有步骤。

  2. 更重要的:使用者并不知道镜像是如何创建出来的,里面是否有恶意程序。也就是说无法对镜像进行审计,存在安全隐患。

        用 Dockerfile(推荐方法)构建镜像,底层也 docker commit 一层一层构建新镜像的。docker commit 能够帮助我们更加深入地理解构建过程和镜像的分层结构。

强烈推荐看官方文档:MySQL官方dockerfile文档

        用 Dockerfile(推荐方法)构建镜像,底层也 docker commit 一层一层构建新镜像的。docker commit 能够帮助我们更加深入地理解构建过程和镜像的分层结构。

        下面来个小案例,使用centos:7来构建系统镜像,里面安装vim(默认里面仅支持vi)。下面使用buid构建镜像,os1镜像名,“ . ”是dockerfile的路径

[root@localhost ~]# mkdir doc_file
[root@localhost ~]# cd doc_file/
[root@localhost doc_file]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        latest    605c77e624dd   16 months ago   141MB
httpd        latest    dabbfbe0c57b   16 months ago   144MB
centos       7         eeb6ee3f44bd   19 months ago   204MB
[root@localhost doc_file]# vim dockerfile
FROM centos:7
RUN yum -y install vim
[root@localhost doc_file]# docker build -t os1 .
[+] Building 110.7s (6/6) FINISHED                                
 => [internal] load build definition from dockerfile         0.0s
 => => transferring dockerfile: 74B                          0.0s
 => [internal] load .dockerignore                            0.0s
 => => transferring context: 2B                              0.0s
 => [internal] load metadata for docker.io/library/centos:7  0.0s
 => CACHED [1/2] FROM docker.io/library/centos:7             0.0s
 => [2/2] RUN yum -y install vim                           108.6s
 => exporting to image                                       2.0s
 => => exporting layers                                      2.0s
 => => writing image sha256:8326a9eb4706b6687c5b1329426b81e  0.0s 
 => => naming to docker.io/library/os1
 [root@localhost doc_file]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
os1          latest    8326a9eb4706   14 minutes ago   468MB
nginx        latest    605c77e624dd   16 months ago    141MB
httpd        latest    dabbfbe0c57b   16 months ago    144MB
centos       7         eeb6ee3f44bd   19 months ago    204MB
[root@localhost doc_file]# docker run -it os1 /bin/bash 
[root@66fd2b023bbb /]# vim a.txt                                        #使用vim对a.txt插入内容并查看测试
[root@66fd2b023bbb /]# cat a.txt 
hello

1. 运行 docker build 命令,-t 将新镜像命名为 os1,命令末尾的 . 指明 build context 为当前目录。Docker 默认会从 build context 中查找 Dockerfile 文件,我们也可以通过 -f 参数指定 Dockerfile 的位置。

2. 从这步开始就是镜像真正的构建过程。 首先 Docker 将 build context 中的所有文件发送给 Dockerdaemon。build context 为镜像构建提供所需要的文件或目录。 Dockerfile 中的 ADD、COPY 等命令可以将 build context 中的文件添加到镜像。此例中,build context 为当前目录 /root,该目录下的所有文件和子目录都会被发送给 Docker daemon。所以,使用 build context 就得小心了,不要将多余文件放到 build context,特别不要把 /、/usr 作为 buildcontext,否则构建过程会相当缓慢甚至失败。

3. Step 1:执行 FROM,将 centos 作为 base 镜像。

4. Step 2:执行 RUN,安装 vim。

5. 启动 ID 临时容器,在容器中通过 yum 安装 vim。

6. 安装成功后,将容器保存为镜像。 这一步底层使用的是类似 docker commit的命令。

7. 删除临时容器。

8. 镜像构建成功。 通过 docker images 查看镜像信息。

镜像的缓存特性

        Docker 会缓存已有镜像的镜像层,构建新镜像时,如果某镜像层已经存在,就直接使用缓存,不在重新创建。 例如下面,在docker中添加一些新内容,因为上面的已经安装,它会直接跳过镜像选择和vim的包,直接安装net-tools,最终系统和这两个服务都可以正常运行。

[root@localhost doc_file]# vim dockerfile
FROM centos:7
RUN yum -y install vim
RUN yum -y install net-tools
[root@localhost doc_file]# docker build -t os2 .
[+] Building 5.3s (7/7) FINISHED                                  
 => [internal] load build definition from dockerfile         0.0s
 => => transferring dockerfile: 104B                         0.0s
 => [internal] load .dockerignore                            0.0s
 => => transferring context: 2B                              0.0s
 => [internal] load metadata for docker.io/library/centos:7  0.0s
 => [1/3] FROM docker.io/library/centos:7                    0.0s
 => CACHED [2/3] RUN yum -y install vim                      0.0s
 => [3/3] RUN yum -y install net-tools                       4.1s
 => exporting to image                                       1.1s 
 => => exporting layers                                      1.1s 
 => => writing image sha256:8242c9c2514d73021f09a962cf1394a  0.0s 
 => => naming to docker.io/library/os2 

        如果我们希望在构建镜像时不使用缓存,可以在 docker build 命令中加上 --no-cache 参数。 Dockerfile 中每一个指令都会创建一个镜像层,上层是依赖于下层的。无论什么时候,只要某一层发生变化,其上面所有层的缓存都会失效。 也就是说,如果我们改变 Dockerfile 指令的执行顺序,或者修改或添加指令,都会使缓存失效。举例说明,比如交换顺序:

        除了构建时使用缓存,Docker 在下载镜像时也会使用。例如我们下载 httpd 镜像。 docker pull 命令输出显示第一层(base 镜像)已经存在,不需要下载。由 Dockerfile 可知 httpd 的 base 镜像为 debian,正好之前已经下载过 debian 镜像,所以有缓存可用。通过docker history 可以进一步验证。

dockerfile命令

        在dockerfile中虽然大小写都可以使用,推荐使用大写容易区分命令。

dockerfile构建过程

1、 编写一个dockerfile文件

2、 docker build 构建称为一个镜像

3、 docker run运行镜像

4、 docker push发布镜像(DockerHub 、阿里云仓库)

FROM

        功能为指定基础镜像,并且必须是第一条指令。 如果不以任何镜像为基础,那么写法为:FROM scratch。 同时意味着接下来所写的指令将作为镜像的第一层开始 语法:

FROM <image>
FROM <image>:<tag>
FROM <image>:<digest> 

三种写法,其中<tag>和<digest> 是可选项,如果没有选择,那么默认值为latest。

RUN

功能为运行指定的命令 RUN命令有两种格式

RUN
RUN ["executable", "param1", "param2"] 

        第一种后边直接跟shell命令。在linux操作系统上默认 /bin/sh -c。 在windows操作系统上默认 cmd /S /C 第二种是类似于函数调用。 可将executable理解成为可执行文件,后面就是两个参数。

两种写法比对:

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

        注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层. 多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。 RUN书写时的换行符是\

CMD

功能为容器启动时要运行的命令 语法有三种写法

CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2

        第三种比较好理解了,就时shell这种执行方式和写法 第一种和第二种其实都是可执行文件加上参数的形式 举例说明两种写法:

CMD [ "sh", "-c", "echo $HOME" 
CMD [ "echo", "$HOME" ]

        补充细节:这里边包括参数的一定要用双引号,就是",不能是单引号。千万不能写成单引号。原因是参数传递后,docker解析的是一个JSON array

RUN & CMD

        不要把RUN和CMD搞混了。 RUN是构件容器时就运行的命令以及提交运行结果;CMD是容器启动时执行的命令,在构件时并不运行,构件时紧紧指定了这个命令到底是个什么样子。

实例

[root@localhost doc_file]# vim dockerfile
FROM centos:7
CMD echo hello
[root@localhost doc_file]# docker build -t os1 .
#省略部分内容
[root@localhost doc_file]# docker run os1
hello

LABEL

为镜像指定标签,可以标识作者等信息。

一个Dockerfile中可以有多个LABEL,语法如下:

LABEL <key>=<value> <key>=<value> <key>=<value> ...	

EXPOSE

        功能为暴露容器运行时的监听端口给外部,但是EXPOSE并不会vim,使容器访问主机的端口,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -P参数

EXPOSE <port> [<port>/<protocol>...]

实例

[root@localhost doc_file]# vim dockerfile
FROM centos:7
EXPOSE  80/tcp 88/udp
[root@localhost doc_file]# docker build -t os2 .
#省略部分内容
[root@localhost doc_file]# docker run -id os2 /bin/bash
947de4db7eae383bd4a2103637c65f3552dd361d909f317582a7ac5495bcbddc
[root@localhost doc_file]# docker ps -a | grep os2
947de4db7eae   os2        "/bin/bash"               15 seconds ago   Up 14 seconds              80/tcp, 88/udp   sweet_davinci

ENV

功能为设置环境变量 语法有两种:

ENV

ENV = <key>=<value> ...

两者的区别就是第一种是一次设置一个,第二种是一次设置多个

实例

[root@localhost doc_file]# vim dockerfile
FROM centos:7
ENV a="hello world"
CMD echo $a
[root@localhost doc_file]# docker build -t os3 .
#省略部分内容
[root@localhost doc_file]# docker run os3
hello world

ADD

        一个复制命令,把文件复制到镜象中。 如果把虚拟机与容器想象成两台linux服务器的话,那么这个命令就类似于scp,只是scp需要加用户名和密码的权限验证,而ADD不用。 语法如下:

ADD [--chown=<user>:<group>] [--chmod=<perms>] [--checksum=<checksum>] <src>... <dest>
ADD [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"]

        路径的填写可以是容器内的绝对路径,也可以是相对于工作目录的相对路径 可以是一个本地文件或者是一个本地压缩文件,还可以是一个url 如果把写成一个url,那么ADD就类似于wget命令 如以下写法都是可以的:

ADD 本地文件	目标位置
ADD URL地址	 目标位置

        尽量不要把写成一个文件夹,如果是一个文件夹,则复制整个目录的内容,包括文件系统元数据。当复制tar包进入容器,会自行解压为目录。

实例

[root@localhost doc_file]# tar zcf back.tar.gz /boot
tar: 从成员名中删除开头的“/”
[root@localhost doc_file]# ls
back.tar.gz  dockerfile
[root@localhost doc_file]# vim dockerfile 
FROM centos:7
ADD back.tar.gz /tmp
[root@localhost doc_file]# docker build -t os4 .
#省略部分内容
[root@26df4b67e3fc /]# cd /tmp/
[root@26df4b67e3fc tmp]# ls
boot  ks-script-DrRL8A  yum.log

COPY

看这个名字就知道,又是一个复制命令 语法如下:

COPY [--chown=<user>:<group>] [--chmod=<perms>] <src>... <dest>
COPY [--chown=<user>:<group>] [--chmod=<perms>] ["<src>",... "<dest>"]

与ADD的区别 COPY的只能是本地文件,其他用法一致。

ENTRYPOINT

功能是启动时的默认命令 语法如下:

ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2

第二种就是写shell 第一种就是可执行文件加参数 与CMD比较说明(这俩命令太像了,而且还可以配合使用):

  1. 相同点: 只能写一条,如果写了多条,那么只有最后一条生效 容器启动时才运行,运行时机相同

  2. 不同点: ENTRYPOINT不会被运行的command覆盖,而CMD则会被覆盖 如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD指令不是一个完整的可执行命令,那么CMD指定的内容将会作为ENTRYPOINT的参数 如下:

FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]

        如果我们在Dockerfile种同时写了ENTRYPOINT和CMD,并且CMD是一个完整的指令,那么它们两个会互相覆盖,谁在最后谁生效 如下:

FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ls -al

那么将执行ls -al ,top -b不会执行。

VOLUME

实现挂载功能,将本地文件/目录或其他容器文件/目录改在这个容器里。

语法如下:

VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME /var/log /var/db

实例如下:

FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

USER

设置启动容器的用户,有两种语法,使用用户名或UID。谨慎使用,如果使用z3用户时,RUN、CMD等都将以z3用户执行。

USER <user>[:<group>]
USER <UID>[:<GID>]

WORKDIR

设置工作目录,对RUN、CMD等生效。如果该目录不存在则会自动创建,可以设置多次。下面使用pwd执行的结果是/a/b/c。

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

也可以解析环境变量,pwd执行的结果是/path/$DIRNAME

ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd

ARG

        使用ARG定义一个变量,在构建镜像时,使用--build-arg = 指定参数,如果在构建镜像时指定的参数没有在dockerfile中,将会楚江Waring提醒。

直接定义参数

FROM busybox
ARG user1
ARG buildno
# ...

给参数一个默认值,如果给了一个默认值时,构建镜像时没有指定参数,将会自动使用默认值。

FROM busybox
ARG user1=someuser
ARG buildno=1
# ...

ONBUILD

        指定当前镜像的子镜像执行,就是说,我在构建dockerfile时,执行下面ls操作时,不执行。如果有人基于我的镜像修改时,将会执行ls操作。

ONBUILD RUN ls

STOPSIGNAL

当退出容器时,执行定义的命令。

STOPSIGNAL signal

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/615949.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅析国有企业信息化建设的难点及解决对策

01 国有企业信息化部门主要做什么&#xff1f; 国有企业信息化部门负责在企业范围内推进信息化工作。他们的职责包括但不限于&#xff1a;制定信息化战略和规划、实施信息化项目、管理信息系统和网络、维护和升级软硬件、开发新的数字化产品和服务、提高信息安全和数据隐私等。…

【正点原子STM32连载】 第二十七章 RTC实时时钟实验摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第二十…

spring 注解 @RequestPart @RequestParam 获取文件流 MultipartFile ,读取Excel等文件

RequestPart RequestPart这个注解用在 multipart/form-data 表单提交请求的方法上。 RequestParam 也可以携带文件 RequestParam也同样支持 multipart/form-data 请求。 RequestParam和RequestPart的区别 RequestParam 适用于 name-valueString 类型的请求域&#xff0c;R…

毕业五六年,明明技术越来越好,而我混的却越来越惨了...

别人都是越来越好&#xff0c;而我是越来越差&#xff01; 至于为什么会这样&#xff0c;可能是因为自己年轻气盛&#xff1b;也可能学历不高&#xff0c;仅仅是个本科&#xff1b;也可能是因为整体环境不好&#xff1b;也可能是能力不足&#xff1b;也可能是运气不好......也可…

python-常用的内置函数

文章目录 一、函数的引入二、变量的作用域三、参数传递四、常见的4类形参1. 必选参数:必须要传递的参数2. 默认参数:可传可不传的参数3. 可变参数: 参数的个数会变化&#xff0c;可以传0&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;......n4. 关键字参数:可以传递key和…

前端web入门-CSS-day05

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 选择器 结构伪类选择器 :nth-child(公式) 伪元素选择器 盒子模型 组成 边框线 内边距 内边距 – …

2023护网面试题200道(附答案)

最近日入1000的护网行动已经开始摇人了&#xff0c; 不少大学生在后台私信我如何参加护网、面试问些什么、有没有护网内推 作为一个负责任的博主&#xff0c;收到大家反馈的我&#xff0c;连夜发动钞能力&#xff0c;收集整理了一套护网蓝初面试文档 1. 什么是DDoS攻击&#x…

linux重装yum

1.先确定linux版本 cat /etc/redhat-release &#xff1b; 查看已安装的yum rpm -qa|grep yum 1 删除已有的yum rpm -aq|grep yum|xargs rpm -e --nodeps 1 下载以下安装包 http://mirrors.163.com/centos/7/os/x86_64/Packages/ 下载最新版本 安装 用FIleZillia 上传的服务…

chatgpt赋能python:Python数据分析

Python数据分析 什么是Python数据分析 Python是一种简单易学、功能强大的编程语言&#xff0c;它是数据科学中最常用的开发语言之一。数据分析是Python的主要用途之一。Python的开源性、易于使用和拥有强大的数据科学库使它成为学术和商业环境下最受欢迎的数据分析工具之一。…

chatgpt赋能python:Python如何取一个数的每位数

Python如何取一个数的每位数 Python是一门功能强大的编程语言&#xff0c;它支持许多数字处理函数&#xff0c;其中一个非常常用的功能是取一个数的每位数。在本文中&#xff0c;我们将介绍如何使用Python取一个数的每位数&#xff0c;以及一些实际应用场景。 取整除 - //操作…

IP-GUARD没有域用户是否可以使用文档云备份功能?

没有域用户是否可以使用文档云备份功能? 可以。 1.没有域控,无法关联域用户的计算机,需添加定制配置 控制台-策略-定制配置-自定义 关键字:enable_relt_common_user 内容:1 备注:允许关联本地用户进行文档云备份。 2.添加配置后,还需要手动关联用户。 设置关联后才会进…

Android Jetpack组件之Navigation

无论您如何构建应用界面&#xff08;使用 Fragment、Activity 还是其他组件&#xff09;&#xff0c;都要为应用设计屏幕间导航的功能。那么可以试试Naviagtion。 文章目录 基本使用创建项目观察使用代码底部导航控件fragment代码底部navigationView与顶部fragment的联动 Navi…

python基础知识(八):字典

目录 1. 字典及其创建2. 字典元素的获取3. 字典元素的删除与清空4. 字典元素的增加5. 字典元素的修改6. 字典的键、值和键值对的获取7. 字典元素的遍历8. 字典的特点9. 字典生成式 1. 字典及其创建 在Python中&#xff0c;字典是一系列键—值对。每个键都与一个值相关联&#…

【深度学习】跌倒识别(带数据集和源码)从0到1

文章目录 前言1. 数据集1.1 数据初探1.2 数据处理1.2 训练前验证图片1.4 翻车教训和进阶知识 2. 训练3.效果展示 前言 又要到做跌倒识别了。 主流方案有两种&#xff1a; 1.基于关键点的识别&#xff0c;然后做业务判断&#xff0c;判断跌倒&#xff0c;用openpose可以做到。…

node,yarn ,cnpm安装

1.解决npm warn config global --global, --local are deprecated. use --locationglobal instead 在安装配置node时&#xff0c;cmd检查node没问题 但是检查npm就出现**npm warn config global –global, –local are deprecated. use –locationglobal instead.**的报警 问…

ClickHouse 使用介绍

1 CK 介绍 1.1 clickhouse简介 ClickHouse 是俄罗斯的 Yandex 于 2016 年开源的用于在线分析处理查询&#xff08;OLAP :Online Analytical Processing&#xff09;MPP架构的列式存储数据库&#xff08;DBMS&#xff1a;Database Management System&#xff09;&#xff0c;能够…

SpringBoot整合第三方技术 -- SpringBoot快速入门保姆级教程(三)

文章目录 前言三、SpringBoot整合第三方技术1.SpringBoot整合junit2.Spring整合junit入门案例3.SpringBoot整合Mybatis4.SpringBoot整合Mybatis入门案例5.SpringBoot整合Mybatis更换默认数据源 总结 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博…

2023陕西省赛-部分Misc复现

目录 管道 zsteg使用&#xff1a; 可是雪啊飘进双眼 snow加密&#xff1a; 管道 用工具zsteg查看各通道的lsb&#xff0c;使用指令&#xff0c;拿到flag zsteg -a 文件 zsteg使用&#xff1a; 介绍&#xff1a;用来检测PNG和BMP中隐藏数据的工具&#xff0c;可以快速提取隐…

初学SpringBoot—01

注明&#xff1a;本人学习来源SpringForAll社区资料 我看到的资料中的springboot和idea版本较低&#xff0c;所以我这里在我学习后&#xff0c;理解并掌握的基础上将我用到的IDEA2022版本和Maven3.8.6做一个记录 学习SpringBoot前最好学习一下Maven和SSM框架 一、新建SpringBo…

RocketMQ详解+实战+常见面试题

目录 RocketMQ是什么&#xff1f; RocketMQ的主要特点包括 RocketMQ 的消息模型 队列模型/点对点 发布/订阅模型 RocketMQ 的消息模型 RocketMQ中重要的组件 RocketMQ消费模式 RoctetMQ基本架构 springboot实战讲解 基本样例 单向发送 异步发送 同步发送 推模式…