-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #247 from yeasy/dev
Add multistage builds
- Loading branch information
Showing
12 changed files
with
317 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
FROM golang:1.9-alpine | ||
|
||
RUN apk --no-cache add git | ||
|
||
WORKDIR /go/src/github.com/go/helloworld/ | ||
|
||
RUN go get -d -v github.com/go-sql-driver/mysql | ||
|
||
COPY app.go . | ||
|
||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . | ||
|
||
FROM alpine:latest | ||
|
||
RUN apk --no-cache add ca-certificates | ||
|
||
WORKDIR /root/ | ||
|
||
COPY --from=0 /go/src/github.com/go/helloworld/app . | ||
|
||
CMD ["./app"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
FROM golang:1.9-alpine | ||
|
||
RUN apk --no-cache add git | ||
|
||
WORKDIR /go/src/github.com/go/helloworld | ||
|
||
COPY app.go . | ||
|
||
RUN go get -d -v github.com/go-sql-driver/mysql \ | ||
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
FROM alpine:latest | ||
|
||
RUN apk --no-cache add ca-certificates | ||
|
||
WORKDIR /root/ | ||
|
||
COPY app . | ||
|
||
CMD ["./app"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
FROM golang:1.9-alpine | ||
|
||
RUN apk --no-cache add git ca-certificates | ||
|
||
WORKDIR /go/src/github.com/go/helloworld/ | ||
|
||
COPY app.go . | ||
|
||
RUN go get -d -v github.com/go-sql-driver/mysql \ | ||
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . \ | ||
&& cp /go/src/github.com/go/helloworld/app /root | ||
|
||
WORKDIR /root/ | ||
|
||
CMD ["./app"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package main | ||
|
||
import "fmt" | ||
|
||
func main(){ | ||
fmt.Printf("Hello World!"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/bin/sh | ||
|
||
echo Building go/helloworld:build | ||
|
||
docker build -t go/helloworld:build . -f Dockerfile.build | ||
|
||
docker create --name extract go/helloworld:build | ||
docker cp extract:/go/src/github.com/go/helloworld/app ./app | ||
docker rm -f extract | ||
|
||
echo Building go/helloworld:2 | ||
|
||
docker build --no-cache -t go/helloworld:2 . -f Dockerfile.copy | ||
rm ./app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,177 @@ | ||
## 多阶段构建 | ||
|
||
### 之前的做法 | ||
|
||
在 Docker 17.05 版本之前,我们构建 Docker 镜像时,通常会采用两种方式: | ||
|
||
#### 全部放入一个 Dockerfile | ||
|
||
一种方式是将所有的构建过程编包含在一个 `Dockerfile` 中,包括项目及其依赖库的编译、测试、打包等流程,这里可能会带来的一些问题: | ||
|
||
* `Dockerfile` 特别长,可维护性降低 | ||
|
||
* 镜像层次多,镜像体积较大,部署时间变长 | ||
|
||
* 源代码存在泄露的风险 | ||
|
||
例如 | ||
|
||
编写 `app.go` 文件,该程序输出 `Hello World!` | ||
|
||
```go | ||
package main | ||
|
||
import "fmt" | ||
|
||
func main(){ | ||
fmt.Printf("Hello World!"); | ||
} | ||
``` | ||
|
||
编写 `Dockerfile.one` 文件 | ||
|
||
```docker | ||
FROM golang:1.9-alpine | ||
RUN apk --no-cache add git ca-certificates | ||
WORKDIR /go/src/github.com/go/helloworld/ | ||
COPY app.go . | ||
RUN go get -d -v github.com/go-sql-driver/mysql \ | ||
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . \ | ||
&& cp /go/src/github.com/go/helloworld/app /root | ||
WORKDIR /root/ | ||
CMD ["./app"] | ||
``` | ||
|
||
构建镜像 | ||
|
||
```bash | ||
$ docker build -t go/helloworld:1 -f Dockerfile.one . | ||
``` | ||
|
||
#### 分散到多个 Dockerfile | ||
|
||
另一种方式,就是我们事先在一个 `Dockerfile` 将项目及其依赖库编译测试打包好后,再将其拷贝到运行环境中,这种方式需要我们编写两个 `Dockerfile` 和一些编译脚本才能将其两个阶段自动整合起来,这种方式虽然可以很好地规避第一种方式存在的风险,但明显部署过程较复杂。 | ||
|
||
例如 | ||
|
||
编写 `Dockerfile.build` 文件 | ||
|
||
```docker | ||
FROM golang:1.9-alpine | ||
RUN apk --no-cache add git | ||
WORKDIR /go/src/github.com/go/helloworld | ||
COPY app.go . | ||
RUN go get -d -v github.com/go-sql-driver/mysql \ | ||
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . | ||
``` | ||
|
||
编写 `Dockerfile.copy` 文件 | ||
|
||
```docker | ||
FROM alpine:latest | ||
RUN apk --no-cache add ca-certificates | ||
WORKDIR /root/ | ||
COPY app . | ||
CMD ["./app"] | ||
``` | ||
|
||
新建 `build.sh` | ||
|
||
```bash | ||
#!/bin/sh | ||
echo Building go/helloworld:build | ||
|
||
docker build -t go/helloworld:build . -f Dockerfile.build | ||
|
||
docker create --name extract go/helloworld:build | ||
docker cp extract:/go/src/github.com/go/helloworld/app ./app | ||
docker rm -f extract | ||
|
||
echo Building go/helloworld:2 | ||
|
||
docker build --no-cache -t go/helloworld:2 . -f Dockerfile.copy | ||
rm ./app | ||
``` | ||
|
||
现在运行脚本即可构建镜像 | ||
|
||
```bash | ||
$ chmod +x build.sh | ||
|
||
$ ./build.sh | ||
``` | ||
|
||
对比两种方式生成的镜像大小 | ||
|
||
```bash | ||
$ docker images | ||
|
||
REPOSITORY TAG IMAGE ID CREATED SIZE | ||
go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB | ||
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB | ||
``` | ||
|
||
### 使用多阶段构建 | ||
|
||
为解决以上问题,Docker v17.05 开始支持多阶段构建 (`multistage builds`)。使用多阶段构建我们就可以很容易解决前面提到的问题,并且只需要编写一个 `Dockerfile`: | ||
|
||
例如 | ||
|
||
编写 `Dockerfile` 文件 | ||
|
||
```docker | ||
FROM golang:1.9-alpine | ||
RUN apk --no-cache add git | ||
WORKDIR /go/src/github.com/go/helloworld/ | ||
RUN go get -d -v github.com/go-sql-driver/mysql | ||
COPY app.go . | ||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . | ||
FROM alpine:latest | ||
RUN apk --no-cache add ca-certificates | ||
WORKDIR /root/ | ||
COPY --from=0 /go/src/github.com/go/helloworld/app . | ||
CMD ["./app"] | ||
``` | ||
|
||
构建镜像 | ||
|
||
```bash | ||
$ docker build -t go/helloworld:3 . | ||
``` | ||
|
||
对比三个镜像大小 | ||
|
||
```bash | ||
$ docker images | ||
|
||
REPOSITORY TAG IMAGE ID CREATED SIZE | ||
go/helloworld 3 d6911ed9c846 7 seconds ago 6.47MB | ||
go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB | ||
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB | ||
``` | ||
|
||
很明显使用多阶段构建的镜像体积小,同时也完美解决了上边提到的问题。 |
Oops, something went wrong.