前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Docker打包优化

Docker打包优化

作者头像
老高的技术博客
发布2022-12-28 10:31:54
6650
发布2022-12-28 10:31:54
举报
文章被收录于专栏:老高的技术博客

老高最近快被工作掩埋了,各种赶上线,各种修BUG,真凄惨! 今天来说说Docker打包的优化问题。为什么要说这个问题呢?请听我慢慢道来。

为什么要优化

先说说的老高的工作流程

工作流程

代码语言:javascript
复制
     +---------------------------------------------------+
     |                    BAD CODE                       |
     |                                                   |
     |                                                   |
+----v------+    +-----------+    +-----------+    +-----+-----+
|           | GP |           | GC |           | DX |           |
| GOOD CODE +---->  GIT REPO +---->  JENKINS  +---->  QA'S ENV |
|           |    |           |    |           |    |           |
+-----+-----+    +-----------+    +-----------+    +-+---+-----+
      |                                              ^   |
      |                                              |   | PASSED
      +----------------------------------------------+   |
                   SEND SINGLE FILE                      |
                                                         |
                                                   +-----v-----+
                                                   |           |
                                                   |  GIT TAG  |
                                                   |           |
                                                   +-----------+
GP = git push
GC = git checkout
DX = docker export

老高把写好的代码提交到GIT仓库,之后使用Jenkins自动化构建,构建出的Docker包会给QA人员测试。 当然为了更快的解决问题,我也可以提供散文件给QA解决一些小问题。

QA反馈某些功能不通过,我会继续修改直到通过测试,通过测试的代码会被合并到主分支并打tag留存。

问题出在哪儿

问题出在代码产出到Docker镜像的产出的过程中,因为Docker镜像的构建出错频率太多,导致频繁打包失败。有时候某一行代码的修改需要等几个小时才能等到新的包出来,这一点十分蛋疼。

于是老高实在忍不住了,主动提出要优化此处。

怎么优化

其实简单的想想,出错的地方一般都出在apt-get/yum install等安装包命令上,如yum install -t nginx mysql-server php5,而这些命令一般都是为了构建基础的运行环境。

而程序猿每次构建基本上都是代码的改动,所以每次构建都跑一次安装LAMP的过程实在没有必要!那到底怎么实现每次构建都只是把新的代码(如PHP源码)拷贝到指定地方,而不做其他的基础构建动作呢?

分离/缓存

老高想到了两个办法:

分离

分离构建步骤,使用两个Dockerfile:Dockerfile_baseDockerfile

第一步构建出base镜像,base镜像中包含lamp的运行环境,第二次构建直接以base镜像为base,再把源码等频繁变动的文件拷贝进入新镜像即可!

这样做即分离了基础环境和执行环境。

而执行docker build命令是可以使用-f指定Dockerfile,即:

代码语言:javascript
复制
# 建立基础镜像
docker build -t lamp:base -f Dockerfile_base
# 建立新镜像
docker build -t lamp:new .
缓存

最佳实践中讲到:

Docker匹配镜像决定是否使用缓存的规则如下:

  1. 从缓存中存在的基础镜像开始,比较所有子镜像,检查它们构建的指令是否和当前的是否完全一致。如果不一致则缓存不匹配。
  2. 多数情况中,使用其中一个子镜像来比较Dockerfile中的指令是足够的。然而,特定的指令需要做更多的判断。
  3. ADD COPY 指令中,将要添加到镜像中的文件也要被检查。通常是检查文件的校验和(checksum)。
  4. 缓存匹配检查并不检查容器中的文件。例如,当使用 RUN apt-get -y update 命令更新了容器中的文件,并不会被缓存检查策略作为缓存匹配的依据。

所以想要优雅的使用缓存,需要好好对之前的Dockerfile做一次大保健,参照最佳实践中的指导:

  • 合并安装包命令
代码语言:javascript
复制
RUN apt-get update \
    && apt-get install -y postgresql-common \
    && sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf \
    && apt-get install -y \
        postgresql-$PG_MAJOR=$PG_VERSION \
        postgresql-contrib-$PG_MAJOR=$PG_VERSION \
    && rm -rf /var/lib/apt/lists/*
  • COPY等命令放到后面
  • 推荐设置base为debian:jessie
  • 设置时区和语言
代码语言:javascript
复制
RUN echo "Asia/Shanghai" > /etc/timezone \
        && dpkg-reconfigure -f noninteractive tzdata \
        && dpkg-reconfigure locales  \
        && locale-gen C.UTF-8 \
        && /usr/sbin/update-locale LANG=C.UTF-8 \
        && ENV LC_ALL C.UTF-8
  • 软件源优化
代码语言:javascript
复制
#RUN sed -i "s/archive\.ubuntu\.com/mirrors\.163\.com/g" /etc/apt/sources.list
#RUN sed -i "s/archive\.ubuntu\.com/mirrors\.aliyun\.com/g" /etc/apt/sources.list
#RUN sed -i "s/archive\.ubuntu\.com/tw\.archive\.ubuntu\.com/g" /etc/apt/sources.list
#RUN sed -i "s/archive\.ubuntu\.com/cn\.archive\.ubuntu\.com/g" /etc/apt/sources.list
RUN sed -i "s/archive\.ubuntu\.com/mirrors\.ustc\.edu\.cn/g" /etc/apt/sources.list

配合Jenkins

终于我们按照最佳实践,实现了加速构建,但是为了更加灵活的控制Docker镜像构建,我们可以使用Jenkins中一些简单的功能实现如 强制不缓存,部分更新的功能。

首先在参数区加入一个Boolean Value,名为no-cache Default Value留空,Description写强制不使用缓存

之后添加构建步骤,Exec Shell:

代码语言:javascript
复制
#!/bin/bash
echo 'building base'
cd docker
if [ "$no-cache" = true ] ; then
    echo 'building base without cache'
    docker build --no-cache=true -t "lamp:base" -f Dockerfile_base .
else
    echo 'building base with cache'
    docker build --no-cache=false -t "lamp:base" -f Dockerfile_base .
fi

完成

一些问题

DockerHub里有什么Dockerfile能够参考的?

DockerHub已经为我们提供了很多常用的基础功能镜像,如

如果你想把typecho程序也做成一个Dockerfile,其实已经有了jimmyzhou/typecho-nginx-php

以上都是可以参考的Dockerfile!

源代码是COPY进去还是git clone进去?

Understanding the Docker Cache for Faster Builds

答案是都可以

如何不缓存Dockerfile中的某一条命令

New feature request: Selectively disable caching for specific RUN commands in Dockerfile

答案很多,但是都很麻烦,以后官方貌似会有NOCACHE的Dockerfile关键字。

Postgresql的加速安装

代码语言:javascript
复制
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8 
     && echo "deb http://mirrors.ustc.edu.cn/postgresql/repos/apt/ trusty-pgdg main" > /etc/apt/sources.list.d/pgdg.list
RUN groupadd -r postgres --gid=999 && useradd -r -g postgres --uid=999 postgres
RUN apt-get update 
     && apt-get install -y postgresql-9.4

计划任务(crontab)怎么添加

通过老高的观察,以执行用户为 laogao 为例,计划任务的文件会被保存在/var/spool/cron/crontabs/中,文件名为执行计划任务的用户名,即laogao,权限是600,用户组为 laogao:crontab,这样我们就可以把写有计划任务的文件放到/var/spool/cron/crontabs/laogao,然后修改权限即可。

不过这种方法略显麻烦,其实只需要把写有计划任务的文件导入/tmp/laogao,然后执行crontab -u laogao /tmp/laogao,即可为老高用户生成计划任务了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-04-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么要优化
    • 工作流程
      • 问题出在哪儿
      • 怎么优化
        • 分离/缓存
          • 分离
          • 缓存
      • 配合Jenkins
      • 一些问题
        • DockerHub里有什么Dockerfile能够参考的?
          • 源代码是COPY进去还是git clone进去?
            • 如何不缓存Dockerfile中的某一条命令
              • Postgresql的加速安装
                • 计划任务(crontab)怎么添加
                相关产品与服务
                容器镜像服务
                容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档