zoukankan      html  css  js  c++  java
  • Dockerfile多阶段构建

    多阶段构建
    之前的做法:
        在Docker17.05版本之前,构建Docker镜像,通常采用两种方式:
        1.全部放入一个Dockerfile
        一种方式是将所有的构建过程全都包含在一个Dockerfile中,包括项目及其依赖库的编译、测试、打包流程,这里会带来的一些问题:
            镜像层次多,镜像体积较大,部署时间变长
            源代码存在泄漏的风险
            例如,编写app.go文件,输出Hello World!
    		
    package main
    import "fmt"
    func main(){
        fmt.Printf("Hello World!");
    }
    
            编写Dockerfile.one文件
    		
    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"]
    
    
            构建上面的镜像
            docker build -t go/helloworld:1 -f Dockerfile.one .
    
            构建完之后查下 docker image ls
            输出:
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    go/helloworld       1                   abdac4fc2d71        18 seconds ago      260MB
    
           启动 docker run abdac4fc2d71 ,输出 Hello World! ,说明没问题。
    	   
    	2.第二种方式就是分散到多个Dockerfile 
            事先在一个Dockerfile将项目及其依赖库编译测试打包好后,再将其拷贝到运行环境中,这种方式需要编写两个Dockerfile和一些编译脚本才能将其两个阶段自动整合起来,这种方式虽然可以很好的规避第一种方式存在的风险,但明显部署过程复杂。
            例子:		
    		
    
    app.go文件
    --------------------------
    package main
    import "fmt"
    func main(){
        fmt.Printf("Hello World!");
    }
    		
    		
    Dockerfile.build 文件
    --------------------------
    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 文件
    --------------------------
    FROM alpine:latest
    RUN apk --no-cache add ca-certificates
    WORKDIR /root/
    COPY app .
    CMD ["./app"]
    
    
    build.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
    54
    /
    
    
    然后执行build.sh 这个脚本
    加个执行权限 chmod +x build.sh
    ./build.sh
    
    PS:如果是windows环境下创建的build.sh这个文件的话,直接放到linux上会有问题,报错会是说XXX文件路径不存在,我的这个就是,最简答的处理方法就是 用vim打开build.sh这个文件,然后执行:set fileformat=unix  然后再 wq 保存退出就行了。
    
    看下镜像 docker image ls
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    go/helloworld       2                   411821efb026        4 minutes ago       7.97MB
    go/helloworld       build               e43c3b88e2c2        4 minutes ago       258MB
    go/helloworld       1                   abdac4fc2d71        2 hours ago         260MB
    ubuntu              18.04               775349758637        4 weeks ago         64.2MB
    alpine              latest              965ea09ff2eb        5 weeks ago         5.55MB
    hello-world         latest              fce289e99eb9        11 months ago       1.84kB
    golang              1.9-alpine          b0260be938c6        15 months ago       240MB
    
    最上面的那个就是了,可以跑下试试:docker run 411821efb026 可以输出Hello World!
    
    
    
    
    
    上面就是两种之前的创建镜像的方式,接下来的笔记是关于 多阶段构建的 Docker v17.05之后开始支持多阶段构建(multistage builds)
        
    	
    Dockerfile 文件
    FROM golang:1.9-alpine as builder
    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 a
    pp .
    FROM alpine:latest as prod
    RUN apk --no-cache add ca-certificates
    WORKDIR /root/
    COPY --from=0 /go/src/github.com/go/helloworld/app .
    CMD ["./app"]
    
    开始构建 docker build -t go/helloworld:3 .
    跑下试试:docker run 0186e09ebd69 可以跑出来Hello World!
    
    对比下体积看看 docker image ls
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    go/helloworld       3                   0186e09ebd69        36 seconds ago      7.97MB
    go/helloworld       2                   411821efb026        55 minutes ago      7.97MB
    go/helloworld       build               e43c3b88e2c2        55 minutes ago      258MB
    go/helloworld       1                   abdac4fc2d71        3 hours ago         260MB
    
    TAG为3的这个镜像非常小。
    
    
    只构建某一阶段的镜像
    使用  as  来为某一阶段命名,例如 FROM golang:1.9-alpine as builder
    如当只想构建  builder  阶段的镜像时,增加  --target=builder  参数即可
    docker build --target builder -t username/imagename:tag .
    
    构建时从其他镜像复制文件 使用  COPY --from=0
    例子:
    COPY --from=0 /go/src/github.com/go/helloworld/app .
    COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
    
    
    
    
    
  • 相关阅读:
    转载:揪出MySQL磁盘消耗迅猛的真凶
    转载:MySQL看这一篇就够了
    转载:MySQL:亲测备份策略实例(线上真实备份案例)
    Consul集群搭建 2Server+ 3Client
    consul配置参数大全、详解、总结
    基于consul高可用
    MySQL MGR+ Consul之数据库高可用方案
    MySQL Group Replication-MGR集群
    MySQL binlog_format中sbr 和rbr(Statement-Based and Row-Based Replication)的优缺点
    MySQL binlog2sql-闪回数据
  • 原文地址:https://www.cnblogs.com/csnd/p/12061840.html
Copyright © 2011-2022 走看看