zoukankan      html  css  js  c++  java
  • Dockerfile相关

    使用Dockerfile定制镜像

    镜像的定制实际上就是每一层所添加的配置文件。

    Dockerfile是一个文本文件,其中包含多条指令。每条指令构建一层。

    FROM:定制的镜像都是基于FROM的镜像。

    其中如果以scratch为基础镜像,意味着不需要任何镜像基础。

    RUN

    此指令用来执行命令行命令。主要有两种格式:

    • shell格式:RUN 就像直接在命令行中输入的命令一样。
      • 例如:FROM:定制的镜像都是基于FROM的镜像。
    • exec格式:RUN["可执行文件","参数1","参数2"]更像是函数调用的格式
      • 例如: RUN ["./test.php", "dev", "offline"] == RUN ./test.php dev offline

    Dockerfile总每一个指令都会在docker上新建立一层。所以针对多条指令可以用&&符号连接命令,这样执行后,只会创建1层镜像。

    例如

    FROM centos
    RUN yum install wget 
        && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" 
        && tar -xvf redis.tar.gz
    

    同时每一层构建完成后,一定要清理掉无关文件。避免镜像臃肿

    构建镜像

    docker build -t nginx:v3 .
    

    镜像构建上下文

    docker build命令后有一个 .。表示的是当前目录,实际上是表示的上下文路径

    • docker build工作原理
      • Docker在运行时分为Docker引擎和客户端工具,就是服务端守护进程和客户端工具
      • 本机执行的docker功能都是使用远程调用形式在服务端(Docker引擎)完成
    • 构建镜像时,用户需要指定构建镜像上下文的路径,docker build命令会将路径下的所有内容打包,然后上传给Docker引擎。
      • 超出上下文路径的文件是无法COPY

    Dockerfile指令详解

    COPY复制文件

    • 格式:

      • COPY [ -- chown=<user>:<group>] <源路径> ... <目标路径>
      • COPY [--chown=:] ["<源路径1>",... "<目标路径>"]
    • <源路径>可以是通配符 例如 COPY hom* /mydir

    • <目标路径>可以是容器内部的绝对路径,也可以是相对于工作目录的相对路径

    • 使用COPY,源文件的各种元数据都会保留。例如权限,变更时间

    ADD更高级的复制文件

    与COPY基本一致,在COPY的基础上添加了功能

    实际上最适合的场景就是自动解压到目标目录

    比如<源路径>可以是URL,这种情况下Docker引擎会试图下载这个链接的文件放到<目标路径>

    如果权限信息不正确,需要用RUN再次修改权限,所以并不适用,不推荐

    • 如果<源路径>为tar压缩文件,ADD只能会自动解压缩这个压缩文件到<目标路径>

    CMD容器启动命令

    CMD指令就是用于指定默认的容器主进程的启动命令

    在运行时可以指定新的命令来替代镜像设置中的默认命令

    与RUN指令运行时间点区别:

    • CMD 在docker run时运行
    • RUN 是在 docker build

    运行格式:

    • shell格式:CMD <命令>
    • exec 格式: CMD["可执行文件","参数1","参数2"]

    采取 shell 格式,实际的命令会被包装成sh -c 的参数格式进行执行。比如:

    CMD  ["sh","-c","echo $HOME"]
    

    这就是可以使用环境变量的原因,因为这些环境变量会被shell进行解析处理。

    因为docker不是虚拟机,所i容器中的应用都应该以前台执行,而不是像虚拟机,物理机中用system启动后台服务。

    CMD所启动的命令实际都依靠于主进程sh,当sh作为主进程退出了,自然就会令容器退出。

    正确的做法时直接执行相关的可执行文件,并且要求以前台形式运行。

    CMD ["nginx","-g","deamon off"]
    

    ENTRYPOINT入口点

    如果Dockerfile中存在多个ENTRYPOINT指令,仅最后一个生效

    ENTRYPOINT的格式和RUN指令格式一样,分为exec格式和shell格式

    • 制定了ENTRYPOINT后,CMD的含义就发生了变化,不再是直接运行器命令,而是将CMD内容作为参数传为ENTRYPOINT
      • 实际执行时将变成:<ENTRYPOINT> "<CMD>"

    场景一:让镜像变成像命令一样使用

    FROM ubuntu:18.04
    RUN apt-get update 
    && apt-get install -y curl 
    && rm -rf /var/lib/apt/lists/*
    CMD [ "curl", "-s", "http://myip.ipip.net" ]
    

    如果此时用docker build -t myip构建镜像,只需要执行docker run myip

    但是当希望添加参数比如 docker build -t myip -i会提示可执行文件找不到。

    原因:

    • 跟在镜像后的command运行时会替换CMD的默认值。这里的-i会替换原来的CMD,所以自然找不到

    • 如果希望加入-i参数,必须重新完整输入命令docker run myip curl -s http://myip.ipip.net -i

    此时用ENTRYPOINT就可以解决这个问题

    修改最后一句ENTRYPOINT [ "curl", "-s", "http://myip.ipip.net" ],此时可以使用 docker run myip -i

    场景二:运行前的准备工作

    启动容器就是启动主进程,但有时,启动主程序前需要进行准备工作

    此时可以写一个脚本,然后放入ENTRYPOINT中去执行,而这个脚本将会接到的参数(也就是CMD)作为命令,放在脚本最后执行

    eg : redis官方镜像

    FROM alpine:3.4
    ...
    RUN addgroup -S redis && adduser -S -G redis redis
    ...
    ENTRYPOINT ["docker-entrypoint.sh"]
    EXPOSE 6379
    CMD [ "redis-server" ]
    
    

    其中为了redis服务创建redis用户,并在最后指定entrypoint为docker-entrypoint.sh脚本

    #!/bin/sh
    ...
    # allow the container to be started with `--user`
    if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
    find . ! -user redis -exec chown redis '{}' +
    exec gosu redis "$0" "$@"
    fi
    exec "$@"
    
    

    脚本的内容就是根据CDM内容判断,如卡换对应的身份

    ENV设置环境变量

    两种格式:

    • ENV <key> <value>
    • ENV <key1>=<value1> <key2>=<value2>

    这个指令就是设置环境变量,无论是后面的其他指令RUN,还是运行的应用,都可以直接使用这里定义的环境变量

    ENV VERSION=1.0 DEBUG=ON 
    	NAME="HAPPY TREE"
    #后续的命令可以直接使用VERSION
    RUN curl -SLO "https://ppp.ok/v$VERSION"
    

    ARG构建参数

    ARG <参数名>[=<默认值>]

    构建参数和ENV的效果一样,都是设置环境变量。但是,ARG锁构建的环境变量,在将来容器运行时不存在。

    构建命令中可以用--build-arg <参数名>=<值> 来覆盖。

    • ARG指令有生效范围,如果在FROM指令之前指定,那么只能用于FROM指令中

    VOLUME 定义匿名卷

    定义匿名数据券,再启动容器时忘记挂载数据券,会自动挂载到匿名券。

    VOLUME ["<路径1>","<路径2>"] VOLUME "<路径1>"

    作用:

    • 避免重要的数据,因为容器启动而丢失
    • 避免容器不断变大

    为了防止用户忘记将动态文件所保存目录挂载为卷。在Dockerfile中,我们可以实现指定某些目录为匿名卷,这样运行时忘记挂载也可以正常运行

    VLOUME /data
    docker run -d -v mydata:/data xxxx
    #可以通过-v 参数指修改挂载点
    #在这行命名命名参数中,就是用了mydata这个命名权挂载到了/data
    

    EXPOSE暴漏端口

    格式为EXPOSE<端口1> [<端口2>]

    仅仅是声明端口,并不会因为这个声明就开启这个端口的服务。

    -p是映射宿主端口和容器端口,就是将容器对端口服务公开给外界访问

    WORKDIR指定工作目录

    格式为WORKDIR <工作目录路径>

    • 使用WORKDIR指令可以指定工作目录,以后的各层目录都被改成指定目录,如果不存在WORKDIR会帮你创建目录
    • WORKDIR存在相对路径

    USER指定当前用户

    格式:USER <用户名>[:<用户组>]

    • USER则是改变之后层执行RUNCMDENTRYPOINT这类命令身份
    • USER切换的用户必须是事前建立好的否则无法切换

    HEALTHCHECK 健康检查

    ONBUILD

    Dockerfile多阶段构建

    多阶段构建

    之前的做法

    在Docker 17.05 版本之前,在构建Docker镜像时,通常会采取两种方式

    1.全部放入一个Dockerfile

    一种方式是将所有的构建过程编在一个Dockerfile中,包含项目机器依赖库的编译、测试、打包等流程,如此可能带来一些问题:

    • 镜像构建层次多,镜像体积较大,部署时间变长
    • 源代码存在泄露的风险

    例如:

    编写 app.go 文件 // 编写对应dockerfile (其中包含了编译测试打包) // 最后构建镜像

    2.分散到多个Dockerfile

    另一种方式是事先在一个Dockerfile将项目及其依赖库编译测试打包好后,再将其拷贝到运行环境中,这种方式需要编写两个Dockerfile和一些编译脚本才能将两个阶段整合

    使用多阶段构建

    为了解决以上问题,Dockerv17.05开始支持多阶段构建,使用多阶段构建可以解决前面的问题

    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 app .
    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"]
    

    其他制作镜像的方式

    从rootfs压缩包导入

    docker import [option] <file>|<URL> - [<depository><:TAG>]]
    

    压缩包可以是本地文件、远程Web文件,甚至是标准输入中得到的。也所报将会在镜像/目录展开,直接作为镜像第一层提交

    $ docker import 
    http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz 
    openvz/ubuntu:16.04
    

    此命令自动下载了tar.gz文件,并作为跟文件系统展开导入,保存为镜像openvz/ubuntu:16.04

    导入成功后,可以在docker image ls总看到导入的镜像

    Docker镜像导入和导出 docker save和docker load

    保存镜像

    使用docker save命令可以将镜像保存为归档文件docker save alpine -o filename

    若使用gzip压缩:

    docker save alpine | gzip > alpine-latest.tar.gz
    

    加载镜像

    docker load -i alpine-latest.tar.gz
    
  • 相关阅读:
    memcached基础与配置详解
    最小化安装CentOS基础命令
    源码编译redis及解决三个开机告警问题
    HAProxy之一----HAPproxy配置参数详解
    HAProxy之二----HAProxy实现高级负载均衡实战和ACL控制
    6 SQL语言——distinct去重
    5 SQL语言——连接符
    04 Oracle Sql语言API
    03 Oracle——用户密码忘记重置
    02 Oracle——账号管理
  • 原文地址:https://www.cnblogs.com/ginko/p/14385946.html
Copyright © 2011-2022 走看看