Update dockerfile format
parent
11e2bf1701
commit
234ac706a3
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
下面是来自 `buildpack-deps` 镜像的例子:
|
下面是来自 `buildpack-deps` 镜像的例子:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
bzr \
|
bzr \
|
||||||
cvs \
|
cvs \
|
||||||
|
@ -72,7 +72,7 @@ RUN apt-get update && apt-get install -y \
|
||||||
|
|
||||||
>注意:如果你的字符串中包含空格,必须将字符串放入引号中或者对空格使用转义。如果字符串内容本身就包含引号,必须对引号使用转义。
|
>注意:如果你的字符串中包含空格,必须将字符串放入引号中或者对空格使用转义。如果字符串内容本身就包含引号,必须对引号使用转义。
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
# Set one or more individual labels
|
# Set one or more individual labels
|
||||||
LABEL com.example.version="0.0.1-beta"
|
LABEL com.example.version="0.0.1-beta"
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ LABEL com.example.version.is-production=""
|
||||||
|
|
||||||
一个镜像可以包含多个标签,但建议将多个标签放入到一个 `LABEL` 指令中。
|
一个镜像可以包含多个标签,但建议将多个标签放入到一个 `LABEL` 指令中。
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
# Set multiple labels at once, using line-continuation characters to break long lines
|
# Set multiple labels at once, using line-continuation characters to break long lines
|
||||||
LABEL vendor=ACME\ Incorporated \
|
LABEL vendor=ACME\ Incorporated \
|
||||||
com.example.is-beta= \
|
com.example.is-beta= \
|
||||||
|
@ -108,7 +108,7 @@ LABEL vendor=ACME\ Incorporated \
|
||||||
|
|
||||||
永远将 `RUN apt-get update` 和 `apt-get install` 组合成一条 `RUN` 声明,例如:
|
永远将 `RUN apt-get update` 和 `apt-get install` 组合成一条 `RUN` 声明,例如:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
package-bar \
|
package-bar \
|
||||||
package-baz \
|
package-baz \
|
||||||
|
@ -117,7 +117,7 @@ RUN apt-get update && apt-get install -y \
|
||||||
|
|
||||||
将 `apt-get update` 放在一条单独的 `RUN` 声明中会导致缓存问题以及后续的 `apt-get install` 失败。比如,假设你有一个 `Dockerfile` 文件:
|
将 `apt-get update` 放在一条单独的 `RUN` 声明中会导致缓存问题以及后续的 `apt-get install` 失败。比如,假设你有一个 `Dockerfile` 文件:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
FROM ubuntu:18.04
|
FROM ubuntu:18.04
|
||||||
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
|
@ -127,7 +127,7 @@ RUN apt-get install -y curl
|
||||||
|
|
||||||
构建镜像后,所有的层都在 Docker 的缓存中。假设你后来又修改了其中的 `apt-get install` 添加了一个包:
|
构建镜像后,所有的层都在 Docker 的缓存中。假设你后来又修改了其中的 `apt-get install` 添加了一个包:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
FROM ubuntu:18.04
|
FROM ubuntu:18.04
|
||||||
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
|
@ -139,7 +139,7 @@ Docker 发现修改后的 `RUN apt-get update` 指令和之前的完全一样。
|
||||||
|
|
||||||
使用 `RUN apt-get update && apt-get install -y` 可以确保你的 Dockerfiles 每次安装的都是包的最新的版本,而且这个过程不需要进一步的编码或额外干预。这项技术叫作 `cache busting`。你也可以显示指定一个包的版本号来达到 `cache-busting`,这就是所谓的固定版本,例如:
|
使用 `RUN apt-get update && apt-get install -y` 可以确保你的 Dockerfiles 每次安装的都是包的最新的版本,而且这个过程不需要进一步的编码或额外干预。这项技术叫作 `cache busting`。你也可以显示指定一个包的版本号来达到 `cache-busting`,这就是所谓的固定版本,例如:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
package-bar \
|
package-bar \
|
||||||
package-baz \
|
package-baz \
|
||||||
|
@ -150,7 +150,7 @@ RUN apt-get update && apt-get install -y \
|
||||||
|
|
||||||
下面是一个 `RUN` 指令的示例模板,展示了所有关于 `apt-get` 的建议。
|
下面是一个 `RUN` 指令的示例模板,展示了所有关于 `apt-get` 的建议。
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
aufs-tools \
|
aufs-tools \
|
||||||
automake \
|
automake \
|
||||||
|
@ -193,7 +193,7 @@ RUN apt-get update && apt-get install -y \
|
||||||
|
|
||||||
最后,`ENV` 也能用于设置常见的版本号,比如下面的示例:
|
最后,`ENV` 也能用于设置常见的版本号,比如下面的示例:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
ENV PG_MAJOR 9.3
|
ENV PG_MAJOR 9.3
|
||||||
|
|
||||||
ENV PG_VERSION 9.3.4
|
ENV PG_VERSION 9.3.4
|
||||||
|
@ -211,7 +211,7 @@ ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
|
||||||
|
|
||||||
如果你的 `Dockerfile` 有多个步骤需要使用上下文中不同的文件。单独 `COPY` 每个文件,而不是一次性的 `COPY` 所有文件,这将保证每个步骤的构建缓存只在特定的文件变化时失效。例如:
|
如果你的 `Dockerfile` 有多个步骤需要使用上下文中不同的文件。单独 `COPY` 每个文件,而不是一次性的 `COPY` 所有文件,这将保证每个步骤的构建缓存只在特定的文件变化时失效。例如:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
COPY requirements.txt /tmp/
|
COPY requirements.txt /tmp/
|
||||||
|
|
||||||
RUN pip install --requirement /tmp/requirements.txt
|
RUN pip install --requirement /tmp/requirements.txt
|
||||||
|
@ -223,7 +223,7 @@ COPY . /tmp/
|
||||||
|
|
||||||
为了让镜像尽量小,最好不要使用 `ADD` 指令从远程 URL 获取包,而是使用 `curl` 和 `wget`。这样你可以在文件提取完之后删掉不再需要的文件来避免在镜像中额外添加一层。比如尽量避免下面的用法:
|
为了让镜像尽量小,最好不要使用 `ADD` 指令从远程 URL 获取包,而是使用 `curl` 和 `wget`。这样你可以在文件提取完之后删掉不再需要的文件来避免在镜像中额外添加一层。比如尽量避免下面的用法:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
ADD http://example.com/big.tar.xz /usr/src/things/
|
ADD http://example.com/big.tar.xz /usr/src/things/
|
||||||
|
|
||||||
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
|
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
|
||||||
|
@ -233,7 +233,7 @@ RUN make -C /usr/src/things all
|
||||||
|
|
||||||
而是应该使用下面这种方法:
|
而是应该使用下面这种方法:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
RUN mkdir -p /usr/src/things \
|
RUN mkdir -p /usr/src/things \
|
||||||
&& curl -SL http://example.com/big.tar.xz \
|
&& curl -SL http://example.com/big.tar.xz \
|
||||||
| tar -xJC /usr/src/things \
|
| tar -xJC /usr/src/things \
|
||||||
|
@ -250,7 +250,7 @@ RUN mkdir -p /usr/src/things \
|
||||||
|
|
||||||
例如,下面的示例镜像提供了命令行工具 `s3cmd`:
|
例如,下面的示例镜像提供了命令行工具 `s3cmd`:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
ENTRYPOINT ["s3cmd"]
|
ENTRYPOINT ["s3cmd"]
|
||||||
|
|
||||||
CMD ["--help"]
|
CMD ["--help"]
|
||||||
|
@ -295,7 +295,7 @@ exec "$@"
|
||||||
|
|
||||||
该辅助脚本被拷贝到容器,并在容器启动时通过 `ENTRYPOINT` 执行:
|
该辅助脚本被拷贝到容器,并在容器启动时通过 `ENTRYPOINT` 执行:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
COPY ./docker-entrypoint.sh /
|
COPY ./docker-entrypoint.sh /
|
||||||
|
|
||||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
第一步,因为应用将要运行在一个满足所有环境依赖的 Docker 容器里面,那么我们可以通过编辑 `Dockerfile` 文件来指定 Docker 容器要安装内容。内容如下:
|
第一步,因为应用将要运行在一个满足所有环境依赖的 Docker 容器里面,那么我们可以通过编辑 `Dockerfile` 文件来指定 Docker 容器要安装内容。内容如下:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
FROM python:3
|
FROM python:3
|
||||||
ENV PYTHONUNBUFFERED 1
|
ENV PYTHONUNBUFFERED 1
|
||||||
RUN mkdir /code
|
RUN mkdir /code
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
首先,因为应用将要运行在一个满足所有环境依赖的 Docker 容器里面,那么我们可以通过编辑 `Dockerfile` 文件来指定 Docker 容器要安装内容。内容如下:
|
首先,因为应用将要运行在一个满足所有环境依赖的 Docker 容器里面,那么我们可以通过编辑 `Dockerfile` 文件来指定 Docker 容器要安装内容。内容如下:
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
FROM ruby
|
FROM ruby
|
||||||
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev
|
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev
|
||||||
RUN mkdir /myapp
|
RUN mkdir /myapp
|
||||||
|
|
|
@ -40,7 +40,7 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
编写 `Dockerfile` 文件,内容为
|
编写 `Dockerfile` 文件,内容为
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
FROM python:3.6-alpine
|
FROM python:3.6-alpine
|
||||||
ADD . /code
|
ADD . /code
|
||||||
WORKDIR /code
|
WORKDIR /code
|
||||||
|
@ -60,7 +60,7 @@ services:
|
||||||
build: .
|
build: .
|
||||||
ports:
|
ports:
|
||||||
- "5000:5000"
|
- "5000:5000"
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: "redis:alpine"
|
image: "redis:alpine"
|
||||||
```
|
```
|
||||||
|
|
|
@ -8,15 +8,11 @@
|
||||||
|
|
||||||
一种方式是将所有的构建过程编包含在一个 `Dockerfile` 中,包括项目及其依赖库的编译、测试、打包等流程,这里可能会带来的一些问题:
|
一种方式是将所有的构建过程编包含在一个 `Dockerfile` 中,包括项目及其依赖库的编译、测试、打包等流程,这里可能会带来的一些问题:
|
||||||
|
|
||||||
* `Dockerfile` 特别长,可维护性降低
|
|
||||||
|
|
||||||
* 镜像层次多,镜像体积较大,部署时间变长
|
* 镜像层次多,镜像体积较大,部署时间变长
|
||||||
|
|
||||||
* 源代码存在泄露的风险
|
* 源代码存在泄露的风险
|
||||||
|
|
||||||
例如
|
例如,编写 `app.go` 文件,该程序输出 `Hello World!`
|
||||||
|
|
||||||
编写 `app.go` 文件,该程序输出 `Hello World!`
|
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
@ -30,7 +26,7 @@ func main(){
|
||||||
|
|
||||||
编写 `Dockerfile.one` 文件
|
编写 `Dockerfile.one` 文件
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
FROM golang:1.9-alpine
|
FROM golang:1.9-alpine
|
||||||
|
|
||||||
RUN apk --no-cache add git ca-certificates
|
RUN apk --no-cache add git ca-certificates
|
||||||
|
@ -58,11 +54,9 @@ $ docker build -t go/helloworld:1 -f Dockerfile.one .
|
||||||
|
|
||||||
另一种方式,就是我们事先在一个 `Dockerfile` 将项目及其依赖库编译测试打包好后,再将其拷贝到运行环境中,这种方式需要我们编写两个 `Dockerfile` 和一些编译脚本才能将其两个阶段自动整合起来,这种方式虽然可以很好地规避第一种方式存在的风险,但明显部署过程较复杂。
|
另一种方式,就是我们事先在一个 `Dockerfile` 将项目及其依赖库编译测试打包好后,再将其拷贝到运行环境中,这种方式需要我们编写两个 `Dockerfile` 和一些编译脚本才能将其两个阶段自动整合起来,这种方式虽然可以很好地规避第一种方式存在的风险,但明显部署过程较复杂。
|
||||||
|
|
||||||
例如
|
例如,编写 `Dockerfile.build` 文件
|
||||||
|
|
||||||
编写 `Dockerfile.build` 文件
|
```dockerfile
|
||||||
|
|
||||||
```docker
|
|
||||||
FROM golang:1.9-alpine
|
FROM golang:1.9-alpine
|
||||||
|
|
||||||
RUN apk --no-cache add git
|
RUN apk --no-cache add git
|
||||||
|
@ -77,7 +71,7 @@ RUN go get -d -v github.com/go-sql-driver/mysql \
|
||||||
|
|
||||||
编写 `Dockerfile.copy` 文件
|
编写 `Dockerfile.copy` 文件
|
||||||
|
|
||||||
```docker
|
```dockerfile
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
RUN apk --no-cache add ca-certificates
|
RUN apk --no-cache add ca-certificates
|
||||||
|
@ -129,11 +123,9 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
|
||||||
|
|
||||||
为解决以上问题,Docker v17.05 开始支持多阶段构建 (`multistage builds`)。使用多阶段构建我们就可以很容易解决前面提到的问题,并且只需要编写一个 `Dockerfile`:
|
为解决以上问题,Docker v17.05 开始支持多阶段构建 (`multistage builds`)。使用多阶段构建我们就可以很容易解决前面提到的问题,并且只需要编写一个 `Dockerfile`:
|
||||||
|
|
||||||
例如
|
例如,编写 `Dockerfile` 文件
|
||||||
|
|
||||||
编写 `Dockerfile` 文件
|
```dockerfile
|
||||||
|
|
||||||
```docker
|
|
||||||
FROM golang:1.9-alpine as builder
|
FROM golang:1.9-alpine as builder
|
||||||
|
|
||||||
RUN apk --no-cache add git
|
RUN apk --no-cache add git
|
||||||
|
@ -184,7 +176,7 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
|
||||||
FROM golang:1.9-alpine as builder
|
FROM golang:1.9-alpine as builder
|
||||||
```
|
```
|
||||||
|
|
||||||
例如当我们只想构建 `builder` 阶段的镜像时,我们可以在使用 `docker build` 命令时加上 `--target` 参数即可
|
例如当我们只想构建 `builder` 阶段的镜像时,增加 `--target=builder` 参数即可
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ docker build --target builder -t username/imagename:tag .
|
$ docker build --target builder -t username/imagename:tag .
|
||||||
|
|
Loading…
Reference in New Issue