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

32次阅读

共计 2443 个字符,预计需要花费 7 分钟才能阅读完成。

镜像的外部机制是什么

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

环境变量和配置参数比较简单一个 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 参数,为镜像起一个有意义的名字,方便管理

正文完
 0