Dockerfile详解及优化技巧

news/2024/6/3 17:17:46 标签: docker, 运维, 容器

写在前面

  • 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

http://www.niftyadmin.cn/n/78219.html

相关文章

[数据结构]---八大经典排序算法详解

&#x1f427;作者主页&#xff1a;king&南星 &#x1f3f0;专栏链接&#xff1a;c 文章目录一、八大排序算法复杂度对比二、基于比较的排序算法1.冒泡排序2.选择排序3.插入排序4.希尔排序5.直观感受四种算法的时间复杂度三、基于非比较的排序算法1.基数排序2.箱(桶)排序四…

Python学习-----模块2.0(常用模块之时间模块-->time)

目录 前言&#xff1a; time简介 导入模块 1.时间戳 2.时间元组 &#xff08;1&#xff09;把时间戳转换为元组形式 &#xff08;2&#xff09;元组转换为时间戳输出 &#xff08;3&#xff09;把元组转换为格式化时间 &#xff08;4&#xff09;把时间戳转换为格式化时间…

XSS注入进阶练习篇(一)XSS-LABS通关教程

XSS注入进阶练习篇1.常用标签整理2. XSS-LABS 练习2.1 level 1 无限制2.2 level 2 双引号闭合2.3 level 3 源码函数书写不全&#xff0c;单引号绕过2.4 level 4 无尖括号绕过2.5 level 5 a标签使用2.6 level 6 大小写绕过2.7 level 7 置空替换绕过2.8 level 8 URL编码绕过 - 重…

网络编程(一)

网络编程 文章目录网络编程前置概念1- 字节序高低地址与高低字节高低地址&#xff1a;高低字节字节序大端小端例子代码判断当前机器是大端还是小端为何要有字节序字节序转换函数需要字节序转换的时机例子一例子二2- IP地址转换函数早期(不用管)举例现在与字节序转换函数相比:**…

中后序遍历构建二叉树与应用I

目录 题目描述 思路分析 AC代码 题目描述 按中序遍历和后序遍历给出一棵二叉树&#xff0c;求这棵二叉树中叶子节点权值的最小值。 输入保证叶子节点的权值各不相同。 输入 测试数据有多组 对于每组测试数据&#xff0c;首先输入一个整数N (1 < N < 10000)&#x…

Java中的链表实现介绍

Java中的链表实现介绍 学习数据结构的的链表和树时&#xff0c;会遇到节点&#xff08;node&#xff09;和链表&#xff08;linked list&#xff09;这两个术语&#xff0c;节点是处理数据结构的链表和树的基础。节点是一种数据元素&#xff0c;包括两个部分&#xff1a;一个是…

(三十六)Vue解决Ajax跨域问题

文章目录环境准备vue的跨域问题vue跨域问题解决方案方式一方式二上一篇&#xff1a;&#xff08;三十五&#xff09;Vue之过渡与动画 环境准备 首先我们要借助axios发送Ajax&#xff0c;axios安装命令&#xff1a;npm i axios 其次准备两台服务器&#xff0c;这里使用node.j…

Nacos超简单-管理配置文件

优点理论什么的就不说了&#xff0c;按照流程开始配配置吧。登录Centos&#xff0c;启动Naocs&#xff0c;使用sh /data/soft/restart.sh将自动启动Nacos。访问&#xff1a;http://192.168.101.65:8848/nacos/账号密码&#xff1a;nacos/nacos分为两部分&#xff0c;第一部分准…