四个超实用的 Docker 镜像构建方法
发布时间:2022-07-30 16:21:29 所属栏目:系统 来源:互联网
导读:最近做了一个好玩的工具,叫 xbin.io[1] 。其中有一项工作是为不同的工具来构建 Docker 镜像,让他们都运行在 Docker 中(实际上,是兼容 Docker image 的其他 sandbox 系统,没有直接用 Docker)。支持的工具越来越多,为了节省资源,Build 的 Docker image
最近做了一个好玩的工具,叫 xbin.io[1] 。其中有一项工作是为不同的工具来构建 Docker 镜像,让他们都运行在 Docker 中(实际上,是兼容 Docker image 的其他 sandbox 系统,没有直接用 Docker)。支持的工具越来越多,为了节省资源,Build 的 Docker image 就越小越好,文件越少,其实启动速度也会略微快一些,也会更安全一些。 了解了原理之后,你会发现,这种设计对于 Docker 来说非常合适: 如果 2 个 image 都是基于 Ubuntu,那么两个 Image 可以共用 Ubuntu 的 base image,只需要存储一份; 如果 pull 新的 image,某一层如果已经存在,那么这一层之前的内容其实就不需要 pull 了; 后面 build image 的技巧其实都是基于这两点。 另外稍微提一下,Docker image 其实就是一个 tar 包[5]。一般来说我们通过 Dockerfile 用 docker built 命令来构建,但是其实也可以用其他工具构建,只要构建出来的 image 符合 Docker 的规范[6],就可以运行。比如,之前的博文 Build 一个最小的 Redis Docker Image[7] 就是用 Nix 构建出来的。 技巧1:删除缓存 一般的包管理器,比如 apt, pip 等,下载包的时候,都会下载缓存,下次安装同一个包的时候不必从网络上下载,直接使用缓存即可。 但是在 Docker Image 中,我们是不需要这些缓存的。所以我们在 Dockerfile 中下载东西一般会使用这种命令: 复制 RUN dnf install -y --setopt=tsflags=nodocs httpd vim && RUN dnf clean all 1. 2. 3. 4. Dockerfile 里面的每一个 RUN 都会创建一层新的 layer,如上所说,这样其实是创建了 3 层 layer,前 2 层带来了缓存,第三层删除了缓存。如同 git 一样,你在一个新的 commit 里面删除了之前的文件,其实文件还是在 git 历史中的,最终的 docker image 其实没有减少。 但是 Docker 有了一个新的功能,docker build --squash。squash 功能会在 Docker 完成构建之后,将所有的 layers 压缩成一个 layer,也就是说,最终构建出来的 Docker image 只有一层。所以,如上在多个 RUN 中写 clean 命令,其实也可以。我不太喜欢这种方式,因为前文提到的,多个 image 共享 base image 以及加速 pull 的 feature 其实就用不到了。 一些常见的包管理器删除缓存的方法: rvm cleanup all gem gem cleanup cpan rm -rf ~/.cpan/{build,sources}/* pip rm -rf ~/.cache/pip/* apt-get apt-get clean 另外,上面这个命令其实还有一个缺点。因为我们在同一个 RUN 中写多行,不容易看出这个 dnf 到底安装了什么。而且,第一行和最后一行不一样,如果修改,diff 看到的会是两行内容,很不友好,容易出错。 可以写成这种形式,比较清晰。 复制 RUN true && dnf install -y --setopt=tsflags=nodocs httpd vim && systemctl enable httpd && dnf clean all && true 1. 2. 3. 4. 5. 6. 技巧2:改动不频繁的内容往前放 通过前文介绍过的原理,可以知道,对于一个 Docker image 有 ABCD 四层,B 修改了,那么 BCD 会改变。 根据这个原理,我们在构建的时候可以将系统依赖往前写,因为像 apt, dnf 这些安装的东西,是很少修改的。然后写应用的库依赖,比如 pip install,最后 copy 应用。 比如下面这个 Dockerfile,就会在每次代码改变的时候都重新 Build 大部分 layers,即使只改了一个网页的标题。 复制 FROM python:3.7-buster # copy source RUN mkdir -p /opt/app COPY myapp /opt/app/myapp/ WORKDIR /opt/app # install dependencies nginx RUN apt-get update && apt-get install nginx RUN pip install -r requirements.txt RUN chown -R www-data:www-data /opt/app # start server EXPOSE 8020 STOPSIGNAL SIGTERM CMD ["/opt/app/start-server.sh"] 我们可以改成,先安装 Nginx,再单独 copy requirements.txt,然后安装 pip 依赖,最后 copy 应用代码。 复制 FROM python:3.7-buster # install dependencies nginx RUN apt-get update && apt-get install nginx RUN chown -R www-data:www-data /opt/app # start server EXPOSE 8020 STOPSIGNAL SIGTERM CMD ["/opt/app/start-server.sh"] (编辑:应用网_丽江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |