首页 > 其他分享 >创建容器镜像:如何编写正确、高效的Dockerfile

创建容器镜像:如何编写正确、高效的Dockerfile

时间:2022-10-20 01:00:28浏览次数:56  
标签:容器 文件 指令 && 镜像 docker Dockerfile

镜像的内部机制是什么

镜像是一个打包文件,里面包含了应用程序和依赖的环境,例如:文件系统、环境变量和配置参数等。

环境变量和配置参数比较简单一个manifest清单就可以管理,真正麻烦的是文件系统。为了保证容器运行环境的一致性,镜像必须把应用程序所在操作系统的根目录,也就是rootfs都包含进来。

容器是共享宿主机内核,文件系统不包含系统内核,假如有一千个镜像基于Ubuntu系统打包,那么这些镜像里就会重复一千次Ubuntu目录,对于磁盘存储、网络传输都是很大的浪费。

把重复的部分抽取出来存放到一份根目录文件,然后让其他镜像以某种方式共享这部分数据。这个思路正是容器的分层,Layer。

一个镜像是由许多的镜像层组成的,每层都是只读不可修改的一组文件,相同的层可以在镜像之间共享,多个层像搭积木一样推叠起来,再使用一种“Union FS联合文件系统”的技术把它们合并在一起,就形成了容器最终看到的文件系统。

docker inspect可以查看镜像分层信息,比如nginx:alpine镜像

docker inspect nginx:alpine

在执行docker pull 或 docker rmi命令时输出的信息其实就是镜像里的各个Layer,Docker会检查是否有重复的层,如果本地已经存在就不会重复下载,如果层被其他镜像共享就不会被删除,这样就可以节约磁盘和网络成本。

以上就是镜像的内部结构和基本原理。

Dockerfile是什么

Dockerfile如果是施工图纸,镜像就是由旋工图纸建造的房子,而容器就是住进人的房子。

Dockerfile就是一个纯文本文件,里面记录了构建指令,比如选择基础镜像、拷贝文件、运行脚本,每个指令都会生成一个Layer,Docker顺序执行这个文件里的所有指令,最终生成一个新的镜像文件。

最简单的Dockerfile

# filename:Dockerfile.busybox
FROM busybox
CMD echo "hello world"

第一条指令:选择基础镜像

第二条指令:启动容器时默认运行的命令

根据图纸建造房子是由施工团队完成的,这里就是docker build

docker build -f Dockerfile.busybox .

查看、运行镜像

docker images
docker inspect image_id
docker run image_id

怎样编写正确、高效的Dockerfile

选择镜像 - FROM指令

选择基础镜像非常关键,如果关注镜像的安全和大小一般选择Alpine,如果关注应用运行的稳定性一般选择CentOS、Ubuntu、Debian。

FROM alpine:3.15
FROM ubunt:bionic

复制文件 - COPY指令

如果要将源码、配置文件打包进镜像,就需要COPY指令,注意复制的源文件路径必须是构建上下文里的路径,也就是用相对路径。

# 把构建上下文里的a.txt拷贝到镜像的/tmp目录
COPY ./a.txt /tmp/a.txt

# 下面方式不正确,不能用构建上下文之外的文件
COPY /etc/hosts /tmp

执行命令 - RUN指令

执行任意shell命令,就需要RUN指令,Dockerfile里一条指令只能是一行,所以RUN指令每行末尾用\续行符,命令之间用&&连接,这样就能保证在逻辑上是一行,减少Layer。


RUN apt-get update \
    && apt-get install -y \
        build-essential \
        curl \
        make \
        unzip \
    && cd /tmp \
    && curl -fSL xxx.tar.gz -o xxx.tar.gz\
    && tar xzf xxx.tar.gz \
    && cd xxx \
    && ./config \
    && make \
    && make clean

这样写一是不美观,二是一旦写错每次调试都要重新构建很麻烦,可以采用一种变通的技巧:把这些shell命令集中到一个脚本文件中,用COPY命令复制进去,再用RUN来执行。

COPY setup.sh  /tmp/                # 拷贝脚本到/tmp目录

RUN cd /tmp && chmod +x setup.sh \  # 添加执行权限
    && ./setup.sh && rm setup.sh    # 运行脚本然后再删除

定义变量 - ARG与ENV指令

ARG和ENV都是定义变量,区别是ARG定义的变量只能在镜像构建过程中可见,ENV创建的变量不仅能在构建镜像过程中使用,也能在容器运行时以环境变量的形式被应用程序使用

开放端口 - EXPOSE指令

它用来声明容器对外服务的端口号,对基于Node.js、Tomcat、Nginx、Go等开发的微服务系统来说非常有用。

# 默认是TCP协议
EXPOSE 443
# 指定UDP协议
EXOPSE 53/udp

docker build是怎么工作的

排除文件 - .dockerignore

一个机制,docker是个客户端,真正的镜像构建工作是由Docker daemon来完成的,所以Docker会把构建上下文的目录打包上传,这样服务器才能获取本地文件。

如果构建上下文中一些文件不需要打包到镜像,docker也会全部打包上传,效率很低。

可以在构建上下文目录中创建一个.dockerignore文件,将那些不需要的文件写入

# docker ignore
*.swp
*.sh

指定文件

用-f来指定Dockerfile文件,如果不指定默认文件名为Dockerfile

docker build -f xxx

指定标签

:分割名字和标签,如果不指定标签默认为latest

小结

1、容器镜像是由多个只读的Layer构成的,同一个Layer可以被不同的镜像共享,减少了存储和传输成本

2、Dockerfile中每个指令都会生成一个Layer

3、Dockerfile第一条指令必须是FROM

4、docker build使用-f来指定Dockerfile,不指定默认国为当前目录下的以Dockerfile为名的文件

5、尽量不要在构建上下文中存入多余的文件

6、尽量使用-t参数,为镜像起一个有意义的名字,方便管理

标签:容器,文件,指令,&&,镜像,docker,Dockerfile
From: https://www.cnblogs.com/okokabcd/p/16808345.html

相关文章

  • IOC--DI--自定义容器
    publicclassXXXContainer:IXXXContainer{//ContainerDicationary保存抽象与细节的映射类型privateDictionary<string,Type>XXXContainerDicationa......
  • 使用Docker将容器打成镜像的方法步骤
    1.容器打成镜像Docker提供了 commit 命令支持将容器重新打成镜像文件,其命令格式如下所示dockercommit[OPTIONS]CONTAINER[REPOSITORY[:TAG]]命令中的选项 ......
  • docker使用-03使用容器进行开发
    在本模块中,我们将逐步为先前模块中构建的应用程序建立本地开发环境。我们将使用Docker来构建镜像,并使用DockerCompose来简化所有工作。在容器中运行数据库(mysql)首先,我......
  • 安装 jenkins实现自动编译、打包、构建镜像、容器部署
      1、部署JDK maven 并进行解压重命名cd/usr/localtar-xvfjdk-8u60-linux-x64.tar.gztar-xvfapache-maven-3.3.9-bin.tar.gzmvapache-maven-3.3.9mave......
  • 004.Dockerfile运行jar文件
    文件名为:po-1.0-SNAPSHOT.jar创建目录:/data/docker/springboot_demo目录下新建文件Dockerfile文件内容为:FROMopenjdk:11-jre-slimRUNapt-getupdateRUNapt-g......
  • Kubernetes--管理Pod对象的容器(2)
    自定义运行的容器化应用由Docker镜像启动容器时运行的应用程序在相应的Dockerfile中由ENTRYPOINT指令进行定义,传递给程序的参数则通过CMD指令指定,ENTRYPOINT指令不存在时......
  • docker 安转pm2并打包成新镜像
    学习docker最好还是整个服务器,买太贵了,建议租一个,我用的是3A服务器!!!取最新版的node镜像dockerpullnodedockerimages   查看镜像dockerrun-itd--name......
  • 阿里巴巴 Noslate 正式开源 - 面向云原生的 JavaScript 容器方案
    继 2019 年开源 Midway 框架之后,阿里一直在 Node.js 的前沿进行深度研究,除了加入 TC39 参与标准化建设,向上游 Node.js 项目持续贡献,与龙蜥社区合作优化之外,也在......
  • 003.dockerfile制作镜像
    修改mysql官网镜像时区FROMmysql:5.7.31#作者信息MAINTAINERmysqlfromdateUTCbyAsia/Shanghai"[email protected]"ENVTZAsia/Shanghaibuild命令dockerbuild......
  • 使用docker exec进入Docker容器
    除了上面几种做法之外,docker在1.3.X版本之后还提供了一个新的命令exec用于进入容器,这种方式相对更简单一些,下面我们来看一下该命令的使用:$sudodockerexec--help接......