5

写 Dockerfile 的一些技巧

 4 years ago
source link: http://dockone.io/article/2434146
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

和很多开源项目一样,SQLFlow 项目为了方便调试和协同工作,把所有 build tools 安装在一个 Docker image 里。项目的贡献者们用这个 Docker image 作为自己的开发环境。写 Dockerfile 的过程里,我们总结了一些技巧,分享如下,抛砖引玉。

用 python -m pip 而不是 pip

这是为了确保我们使用的 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/

一个典型的例子(升级 pip)。
python -m pip install --quiet --upgrade pip

让 pip install 更安静

上例中,在 pip install 命令里,我们用了 --quiet 参数,减少 pip install 打印出来的信息。这样可以让 docker build 更安静。尤其是,如果在 CI 里运行 docker build 的话,减少打印信息可以让 CI log 更加可读。

让 apt-get install 更安静

类似的,用 apt-get 安装软件包的时候,我们用 -qq 命令,甚至重定向输出到 /dev/null 让它更安静。
apt-get -qq update
apt-get -qq install -y curl > /dev/null

让 curl 和 wget 更安静

首先,如果要下载文件,curl 和 wget 二选一即可。如果用 curl,可以用 --silent 参数。
curl -sLO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

wget 有 --quiet 参数。
wget -q https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

用 axel 而不是 curl 或者 wget

作为一个开源软件,中外开发者都会运行 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

让 Python setup.py 更安静

有时候我们会在 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

ARG 和 ENV 是 Dockerfile 里用来定制化 Docker image 的利器,经常结合在一起使用,也常领 Dockerfile 新手挠头。其实,记住一下几条规则,基本就可以了。
  1. ARG 存在于 docker build 命令执行期间。默认值写在 Dockerfile 里。如果需要修改,可以通过 docker build 命令里的 --build-arg 参数来指定。
  2. ENV 存在于 docker run 命令执行期间。默认值写在 Dockerfile 里。如果要修改,可以通过 docker run 命令的 --env 参数来指定。
  3. 如果要把 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 --quiet

上面一些经验是让 docker build 变得更安静的。如果要极端的安静,不需要通过在写 Dockerfile 的时候注意什么,只需要在 docker build 命令里加上 --quiet —— 如果不怕这样导致世界太过安静的话。

原文链接:https://zhuanlan.zhihu.com/p/147995194,作者:王益

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK