![写 Dockerfile 的一些小技巧 写 Dockerfile 的一些小技巧]()
和很多开源项目一样,SQLFlow 项目为了方便调试和协同工作,把所有 build tools 安装在一个 Docker image 里。项目的贡献者们用这个 Docker image 作为自己的开发环境。写 Dockerfile 的过程里,我们总结了一些技巧,分享如下,抛砖引玉。
这是为了确保我们使用的 pip 是我们想用的那个 Python 对应的 pip。有时候,一个系统里安装了 Python 2 和 Python 3,而我们可能错误地设置了 PATH 环境变量(或则因为其他的原因),导致我们运行 Python 命令的时候,启动的 Python 3(或者 2),但是 pip 命令是 Python 2(或者3)的 pip。还有一些其他原因使我们更应该用 python -m pip 的,详见:https://snarky.ca/why-you-should-use-python-m-pip/
python -m pip install --quiet --upgrade pip
上例中,在 pip install 命令里,我们用了 --quiet 参数,减少 pip install 打印出来的信息。这样可以让 docker build 更安静。尤其是,如果在 CI 里运行 docker build 的话,减少打印信息可以让 CI log 更加可读。
类似的,用 apt-get 安装软件包的时候,我们用 -qq 命令,甚至重定向输出到 /dev/null 让它更安静。
apt-get -qq update
apt-get -qq install -y curl > /dev/null
首先,如果要下载文件,curl 和 wget 二选一即可。如果用 curl,可以用 --silent 参数。
curl -sLO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
wget -q https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
作为一个开源软件,中外开发者都会运行 docker build。开发者所处的地理位置不同,各自都希望从距离自己最近(最快)的 mirror 下载和安装文件。axel 可以从多个 mirror 下载同一个文件,根据各个 mirror 的速度,决定分别从不同 mirror 下载的字节数量。如果有的 mirror 挂了,axel 可以忽略之。尤其对于身处国内的开发者,axel 完全可以取代 curl 以及 wget。
axel 和 wget 一样支持 --quiet 参数。以下是一个从大洋两岸的 mirrors 下载 Go 编译器的例子。
echo "Install Go compiler ..."
GO_MIRROR_0="http://mirrors.ustc.edu.cn/golang/go1.13.4.linux-amd64.tar.gz"
GO_MIRROR_1="https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz"
axel --quiet --output go.tar.gz $GO_MIRROR_0 $GO_MIRROR_1
有时候我们会在 Dockerfile 里 build 和 install Python packages,此时我们需要运行:
python ./setup.py build --quiet
python ./setup.py install --quiet
不过如果我们要 build binary distribution package,则需要注意使用全局参数 --quiet:
python ./setup.py --quiet bdist_wheel
ARG 和 ENV 是 Dockerfile 里用来定制化 Docker image 的利器,经常结合在一起使用,也常领 Dockerfile 新手挠头。其实,记住一下几条规则,基本就可以了。
-
ARG 存在于 docker build 命令执行期间。默认值写在 Dockerfile 里。如果需要修改,可以通过 docker build 命令里的 --build-arg 参数来指定。
-
ENV 存在于 docker run 命令执行期间。默认值写在 Dockerfile 里。如果要修改,可以通过 docker run 命令的 --env 参数来指定。
-
如果要把 ARG 的值保存到 container 运行起来之后仍然可以可用,则需要在 ARG 之后写一个 ENV。
为了方便理解,请看下面几个例子。第一个例子:为了把 ARG 的值保存到 docker run 的时候也可以被用到,我们把它写入一个文件 /root/hello.sh。
FROM ubuntu:18.04
ARG releaser=王益
RUN echo "echo $releaser" > /root/hello.sh
RUN chmod +x /root/hello.sh
这样,我们可以 docker run 的时候运行 /root/hello.sh,打印出 docker bulid 的时候指定的 releaser。
docker build -t dev .
docker run --rm -it dev bash -c /root/hello.sh # 打印出 王益
不过因为 ARG 只存在于 docker build 命令执行期间,所以下面命令什么也打印不出来。
docker run --rm -it dev bash -c "echo $releaser"
如果要让上面命令也可以打印出 releaser 这个 ARG 的值,可以在 Dockerfile 里加一个 ENV。
FROM ubuntu:18.04
ARG releaser=王益
ENV releaser=$releaser
docker build -t dev .
docker run --rm -it dev bash -c "echo $releaser"
上面一些经验是让 docker build 变得更安静的。如果要极端的安静,不需要通过在写 Dockerfile 的时候注意什么,只需要在 docker build 命令里加上 --quiet —— 如果不怕这样导致世界太过安静的话。
原文链接:https://zhuanlan.zhihu.com/p/147995194
《Docker是什么?》
《Kubernetes是什么?》
《Kubernetes和Docker到底有啥关系?》
《教你如何快捷的查询选择网络仓库镜像tag》
《Docker镜像进阶:了解其背后的技术原理》
《教你如何修改运行中的容器端口映射》
《k8s学习笔记:介绍&上手》
《k8s学习笔记:缩扩容&更新》
《Docker 基础用法和命令帮助》
《在K8S上搭建Redis集群》
《灰度部署、滚动部署、蓝绿部署》
《PM2实践指南》
《Docker垃圾清理》
《Kubernetes(k8s)底层网络原理刨析》
《容器环境下Node.js的内存管理》
《MySQL 快速创建千万级测试数据》
《Linux 与 Unix 到底有什么不同?》
《浅谈几种常见 RAID 的异同》
《Git 笔记-程序员都要掌握的 Git》
《老司机必须懂的MySQL规范》
《Docker中Image、Container与Volume的迁移》
《漫画|如何用Kubernetes搞定CICD》
《写给前端的Docker实战教程》
《Linux 操作系统知识地图2.0,我看行》
《16个概念带你入门 Kubernetes》
《程序员因接外包坐牢456天,长文叙述心酸真实经历》
《IT 行业老鸟,有话对你说》
《HTTPS 为什么是安全的?说一下他的底层实现原理?》
免责声明:本文内容来源于网络,所载内容仅供参考。转载仅为学习和交流之目的,如无意中侵犯您的合法权益,请及时联系Docker中文社区!
原文始发于微信公众号(Docker中文社区):写 Dockerfile 的一些小技巧
评论