|
| 1 | +# Dockerfile 指南 |
| 2 | + |
| 3 | +## 选择基础镜像 |
| 4 | + |
| 5 | +```{topic} 基本原则 |
| 6 | +- 官方镜像优于非官方的镜像,如果没有官方镜像,则尽量选择 Dockerfile 开源的。 |
| 7 | +- 固定版本 tag 而不是每次都使用 latest。 |
| 8 | +- 尽量选择体积小的镜像。 |
| 9 | +``` |
| 10 | + |
| 11 | +## 执行指令 |
| 12 | + |
| 13 | +```{topic} RUN |
| 14 | +主要用于在镜像里执行指令,比如安装软件,下载文件等。 |
| 15 | +``` |
| 16 | + |
| 17 | +::::{tab-set} |
| 18 | +:::{tab-item} 改进版 |
| 19 | +```Dockerfile |
| 20 | +FROM python:3.8.13 |
| 21 | +RUN apt-get update \ |
| 22 | + && apt-get install -y gcc g++ libtinfo-dev zlib1g-dev build-essential cmake \ |
| 23 | + && apt install -y clang clangd llvm liblldb-dev libedit-dev libxml2-dev \ |
| 24 | + && pip install decorator scipy attrs pandas toml |
| 25 | +``` |
| 26 | +::: |
| 27 | +:::{tab-item} 臃肿版 |
| 28 | +每一行的 `RUN` 命令都会产生一层镜像层,导致镜像的臃肿。 |
| 29 | +```Dockerfile |
| 30 | +FROM python:3.8.13 |
| 31 | +RUN apt-get update |
| 32 | +RUN apt-get install -y gcc g++ libtinfo-dev zlib1g-dev build-essential cmake |
| 33 | +RUN apt install -y clang clangd llvm liblldb-dev libedit-dev libxml2-dev |
| 34 | +RUN pip install decorator scipy attrs pandas toml |
| 35 | +``` |
| 36 | +::: |
| 37 | +:::: |
| 38 | + |
| 39 | +```{tip} |
| 40 | +`docker image history fe5` 可以用于查看镜像历史。 |
| 41 | +``` |
| 42 | + |
| 43 | +## 文件复制和目录操作 |
| 44 | + |
| 45 | +往镜像里复制文件有两种方式,`COPY` 和 `ADD`。 |
| 46 | + |
| 47 | +### 复制普通文件 |
| 48 | + |
| 49 | +`COPY` 和 `ADD` 都可以把本地文件复制到镜像里,如果目标目录不存在,则会自动创建。 |
| 50 | + |
| 51 | +比如把本地的 `hello.py` 复制到 `/app` 目录下。若 `/app` 这个文件不存在,则会自动创建。 |
| 52 | + |
| 53 | +```Dockerfile |
| 54 | +FROM python:3.9.5-alpine3.13 |
| 55 | +COPY hello.py /app/hello.py |
| 56 | +``` |
| 57 | + |
| 58 | +### 复制压缩文件 |
| 59 | + |
| 60 | +`ADD` 比 `COPY` 高级一点的地方就是,如果复制的是 gzip 等压缩文件时,ADD 会帮助自动解压缩文件。 |
| 61 | + |
| 62 | +```Dockerfile |
| 63 | +FROM python:3.9.5-alpine3.13 |
| 64 | +ADD hello.tar.gz /app/ |
| 65 | +``` |
| 66 | + |
| 67 | +### 如何选择 |
| 68 | + |
| 69 | +在 `COPY` 和 `ADD` 指令中选择的时候,可以遵循这样的原则: |
| 70 | + |
| 71 | +> 所有的文件复制均使用 `COPY` 指令,仅在需要自动解压缩的场合使用 `ADD`。 |
| 72 | +
|
| 73 | +## 构建参数和环境变量 |
| 74 | + |
| 75 | +`ARG` 和 `ENV` 是经常容易被混淆的两个 `Dockerfile` 的语法,都可以用来设置 “变量”。 但实际上两者有很多的不同。 |
| 76 | + |
| 77 | +::::{tab-set} |
| 78 | +:::{tab-item} ENV |
| 79 | +```Dockerfile |
| 80 | +FROM ubuntu:20.04 |
| 81 | +ENV VERSION=2.0.1 |
| 82 | +RUN apt-get update && \ |
| 83 | + apt-get install -y wget && \ |
| 84 | + wget https://github.com/ipinfo/cli/releases/download/ipinfo-${VERSION}/ipinfo_${VERSION}_linux_amd64.tar.gz && \ |
| 85 | + tar zxf ipinfo_${VERSION}_linux_amd64.tar.gz && \ |
| 86 | + mv ipinfo_${VERSION}_linux_amd64 /usr/bin/ipinfo && \ |
| 87 | + rm -rf ipinfo_${VERSION}_linux_amd64.tar.gz |
| 88 | +``` |
| 89 | +::: |
| 90 | +:::{tab-item} ARG |
| 91 | +```Dockerfile |
| 92 | +FROM ubuntu:20.04 |
| 93 | +ARG VERSION=2.0.1 |
| 94 | +RUN apt-get update && \ |
| 95 | + apt-get install -y wget && \ |
| 96 | + wget https://github.com/ipinfo/cli/releases/download/ipinfo-${VERSION}/ipinfo_${VERSION}_linux_amd64.tar.gz && \ |
| 97 | + tar zxf ipinfo_${VERSION}_linux_amd64.tar.gz && \ |
| 98 | + mv ipinfo_${VERSION}_linux_amd64 /usr/bin/ipinfo && \ |
| 99 | + rm -rf ipinfo_${VERSION}_linux_amd64.tar.gz |
| 100 | +``` |
| 101 | +::: |
| 102 | +:::: |
| 103 | + |
| 104 | +- `ARG` 可以在镜像 build 的时候动态修改 `value`, 通过 `--build-arg`。 |
| 105 | +- `ENV` 设置的变量可以在镜像中保持,并在容器中可以被环境变量覆写。 |
| 106 | + |
| 107 | +## 构建镜像 |
| 108 | + |
| 109 | +```bash |
| 110 | +docker image build -t demo ./ |
| 111 | +``` |
| 112 | + |
| 113 | +- `demo`:镜像的名称 |
| 114 | +- `./`:build context 所指向的目录 |
| 115 | + |
| 116 | +## `.dockerignore` 文件 |
| 117 | + |
| 118 | +``` |
| 119 | +.vscode/ |
| 120 | +env/ |
| 121 | +``` |
| 122 | + |
| 123 | +有了 `.dockerignore` 文件,构建时, build context 就小了很多。 |
| 124 | + |
| 125 | +## 尽量使用非 root 用户 |
| 126 | + |
| 127 | +## 多阶段构建镜像 |
| 128 | + |
0 commit comments