Dockerfile详解及优化技巧

简介: Dockerfile详解及优化技巧

写在前面

  • Dockerfile的默认相对路径是Dockerfile所在的目录;
  • Dockerfile中的每一行会被视为一层镜像

一、Dockerfile 原理

1.1 镜像定义

首先我们先来回顾一下 Docker 镜像,它由多个只读层堆叠到一起,每一层是上一层的增量修改。基于镜像创建新容器时,将在基础层的顶部添加一个新的可写层。该层通常称为“容器层”。下图展示了一个基于 docker.io/centos 基础镜像构建的应用镜像,创建出容器时的视图。

1.2 镜像来源

镜像主要是 Docker 通过读取、运行 Dockerfile 的指令来生成。我们将上篇文章中的Dockerfile拿过来

FROM gcc
MAINTAINER panda  
COPY ./hello.c ./
RUN pwd
LABEL myhello 1.0.0
LABEL env prod
RUN gcc  hello.c -o hello
CMD ["./hello"]

Dockerfile的核心逻辑就是先定义引用的基础镜像(FROM base image),然后再COPY或ADD上下文到容器,然后再RUN执行用户自定义脚本构建,最后定义容器的CMD或ENTRYPOINT。

1.3 Dockerfile 关键字

FROM

设置镜像使用的基础镜像,必须是第一条指令。如果不以任何镜像为基础镜像,则可以不写,但是,接下来的第一条指令会被作为镜像的第一层使用。

用法:FROM image:tag 其中 tag 是可选项,如果不写,默认为最新latest。

FROM nginx
MAINTAINER

设置镜像的作者。

用法:MAINTAINER name

MAINTAINER   panda
RUN

编译镜像时,要执行的命令,经常被用来安装软件包、拉取和编译代码。

RUN apt-get install python3
RUN git clone https://github.com/golang/example
RUN gcc  hello.c -o hello
RUN pwd
LABEL

设置镜像标签,一个Dockfile中可以有多个LABEL。

LABEL helloc 1.0.0
LABEL env prod
EXPOSE

设置镜像运行时对外暴露的端口

ENV

设置容器的环境变量

ENV env1=v1
ENV env2=v2
COPY 和 ADD

都是复制上下文中的文件到镜像中

COPY  ./hello.c  ./
ADD   ./nginx.tar.gz  ./
ADD   http://www.panda.com/nginx.tar.gz

区别:

  1. COPY 只能复制本地文件
  2. ADD 在复制压缩文件的同时会解压该文件,COPY不能解压
  3. ADD + 网址,会从执行网址下载文件(注意,如果下载的是压缩包,此时不会解压
补充:Exec和 Shell 格式

在学习CMD 和 ENTRYPOINT 之前,我们先来了解下Exec和 Shell 这两种格式。

Exec格式,当指令执行时,会直接调用 ,不会被 shell 解析

# <instruction> ["executable", "param1", "param2", ...]
RUN ["apt-get", "install", "gcc"]  
CMD ["echo", "Hello,world!"]  
ENTRYPOINT ["echo", "Hello,world!"]

Shell 格式,当指令执行时,shell 格式底层会调用 /bin/sh -c

RUN apt-get install gcc
CMD echo "Hello,world!"
ENTRYPOINT echo "Hello,world!"
CMD

设置容器的启动执行的命令和参数,但是会被 docker run 后面的命令行参数替换掉,忽略掉CMD。

CMD ["./hello"]  # 运行hello程序
CMD ["echo", "hello,world"] # 等价于在命令行执行 echo hello,world

案例1(Exec格式):

#Dockerfile部分
ENV name panda
CMD ["echo", "hello, $name"] # 输出 hello, $name 注意name没被解析为panda

如果希望name被解析,可以做以下修改

CMD ["/bin/sh", "-c", "echo hello, $name"] # 输出 hello, panda

案例2(Shell 格式):

#Dockerfile部分
ENV name panda
CMD echo "hello, $name"  # 输出 hello, panda 

小结

CMD命令有三种格式:

  1. Exec格式:CMD [“executable”,“param1”,“param2”],推荐使用这种格式
  2. Shell 格式:CMD command param1 param2
  3. CMD [“param1”,“param2”] 为 ENTRYPOINT 提供额外的参数,此时 ENTRYPOINT 必须使用 Exec 格式。
ENRYPOINT

设置容器的入口程序。

ENTRYPOINT 用法与 CMD 很像,它们都可以指定要执行的命令及其参数。不同的地方在于 ENTRYPOINT 不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令。

VOLUME

设置容器的挂载卷,可以将宿主机目录挂载到容器中,用来持久化容器中的重要数据。

VOLUME ["/var/log/"]
VOLUME /var/log
USER

设置 RUN CMD ENTRYPOINT 的用户名,使用前需要保证USER 有相应的权限。

WORKER

设置RUN CMD ENTRYPOINT COPY ADD 指令的工作目录,如果该目录不存在会自动创建。

ARG

设置编译镜像时加入的参数。ARG命令定义了一个变量,在docker build镜像的时候,需要加 --build-arg arg=val 来指定参数. 可以同时定义多个变量。

#Dockerfile 部分
ARG work_dir code_addr
RUN git clone $code_addr
docker build -t helloc --build-arg work_dir=hello --build-arg code_addr=https://github.com/golang/example .
ONBUILD

ONBUILD影响的是下游的镜像构建,本次不会执行。比如,镜像S0的Dockerfile如下:

#Dockerfile 部分
ONBUILD RUN ls -a

则在构建镜像S0的时候,不会执行。另一个镜像S1是基于S0的,那么在构建镜像S1的时候会执行RUN ls -a

STOPSIGNAL

设置容器退出时候的信号量,默认退出信号量是15. nginx 修改了退出信号量为3.

二、Dockerfile优化技巧

  1. 使用国内的基础镜像,加速构建;
  2. 使用尽量小的、够用的基础镜像即可;
  3. 减少上下文关联目录文件
  4. 减少层的数量、控制层的大小
  5. 将不变层放到前面,可变层放到后面
  6. 使用多阶段来分离 build 和 runtime


推荐一个零声学院免费教程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,点击立即学习:

相关文章
|
6月前
|
Ubuntu Shell 应用服务中间件
|
15天前
|
安全 Linux 虚拟化
LXD如何使用,跟Docker的区别都有什么?优点和缺点都有什么?
【10月更文挑战第28天】LXD如何使用,跟Docker的区别都有什么?优点和缺点都有什么?
53 1
|
1月前
|
存储 Ubuntu JavaScript
如何使用Docker优化你的开发环境配置
如何使用Docker优化你的开发环境配置
|
1月前
|
运维 Docker 容器
|
3月前
|
Ubuntu Shell 应用服务中间件
如何编写高效的Dockerfile
【8月更文挑战第17天】镜像是包含应用及其运行环境的打包文件,含文件系统等。为确保一致性,镜像需包含整个根文件系统(rootfs)。
|
6月前
|
安全 Java Maven
编写 Dockerfile 最佳实践
编写 Dockerfile 最佳实践
|
6月前
|
JavaScript 安全 开发者
深入浅出:使用Docker优化你的开发环境
在软件开发的世界里,"它在我的机器上运行得好好的"这句话几乎成了一个笑话。这主要是因为环境配置差异所带来的挑战。本文将介绍如何使用Docker来创建一致的开发环境,解决环境差异带来的问题。我们将从Docker的基本概念入手,探讨其在开发流程中的应用,并通过实际案例演示如何构建、部署和管理容器化的应用。本文旨在为开发者提供一个清晰的指南,帮助他们利用Docker优化开发流程,提高生产效率。
79 2
|
6月前
|
Kubernetes Java Docker
多阶段构建:精妙优化Docker镜像大小和性能
在容器化应用的世界中,Docker镜像大小和性能优化是至关重要的。多阶段构建是一项强大的技术,通过精心设计Dockerfile,可以在构建镜像时去除不必要的组件,从而显著减小镜像大小,提高性能。本文章将深入讨论多阶段构建的各个方面,并通过更为丰富和实际的示例代码,帮助大家全面了解和掌握这一重要技术。
|
缓存 网络协议 Linux
Dockerfile构建镜像过程中的错误记录及解决方法
本文记录了在一次使用Dockefile构建镜像的途中遇到的问题,以及后续的解决方法。
8129 1
|
存储 缓存 Java
Docker构建优化解析
Docker镜像用作Docker执行程序中的主映像。它们是容器的蓝图,提供了有关如何生成容器的说明。在本文中,我将介绍一些经常被忽视的概念,这些概念将有助于优化Docker镜像开发和构建过程。
108 0