Dockerfile编写(备份)
1-使用#注释
2-Dockerfile 主体内容分为四部分:基础镜像信息、 维护者信息、 镜像操作指令和容器启动时执行指令
简单示例:
FROM xxx:latest #基于xxx:latest镜像,必须位于非注释的首行
# Maitainer: docker_user <docker_user_at_email.com>
LABEL maintainer docker_user<docker_user@email.com>
# Commands to update the image
RUN echo "deb http://archive.ubuntu.com/ubuntu/ xeniel main universe" >> /etc/apt/sources.list
... 很多条RUN ....
# Commands when creating a new container
CMD /usr/sbin/nginx
指令分配置指令和操作指令
配置指令:
FROM <image> [AS <name>] 或 FROM <image>:<tag> [AS <name>] 或 FROM <image>@<digest> [AS <name>] //任何 Dockerfile 中第一条指令必须为 FROM 指令 。如果在同 一 个 Dockerfile 中创建多个镜像时, 可以使用多个 FROM 指令(每个镜像 一 次)。
ENV <key> <value> 或 ENV <key>=<value> //环境变量,被后面的RUN使用,也能在从镜像启动的容器中生效。
环境变量覆盖: docker run --env <key>=<value> build_image
环境变量计算的“延迟特性”:
ENV k1=v1
ENV k1=v2 k2=k1 //最终结果是,k1=v2 k2=v1
ARG <name>[=<default value>] //镜像创建变量。只作用于镜像创建时(区别于ENV)。无须声明直接可以使用的有HTTP_PROXY、HTTPS_PROXY、FTP_PROXY、NO_PROXY
变量重新赋值: 通过docker build --build-arg[=] 来为ARG声明的变量赋值
LABEL <key>=<value> <key>=<value> <key>=<value> ... //LABEL指令可以为生成的镜像添加元数据标签信息。这些信息可以用来辅助过滤出特定镜像。
EXPOSE <port> [<port/<protoocol>... ] //声明镜像内服务监听的端口。注意是声明,是一种文档化意义,而非操作意义。
ENTRYPOINT ["executable", "paraml ", "param2"] 或 ENTRYPOINT command param 1 param2 //镜像默认入口命令,启动容器时作为根命令执行。前者使用exec执行,后者使用shell执行。每个Dockerfile中只能有一个ENTRYPOINT,指定多个时最后一个生效
覆盖: 使用 --entrypoint 选项来覆盖
VOLUME ["/data"] // 创建 一 个数据卷挂载点。运行容器时可以从本地主机或其他容器挂载数据卷, 一般用来存放数据库和需要保持的数据等。
USER daemon //指定运行容器时的用户名或UID, 后续的RUN等指令也会使用指定的用户身份。要临时获取管理员权限可以使用 gosu 命令
WORKDIR /path/to/workdir //为后续的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目录。可以使用多个 WORKDIR 指令,后续命令如 果参数是相对路径, 则 会基于之前命令指定的路径。
例如: WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd // 最终路径为/a/b/c
ONBUILD [INSTRUCTION ] //类似go包init()函数。从该镜像派生的镜像,先会执行ONBUILD定义的指令。由于 ONBUILD 指令是隐式执行的,推荐在使用它的镜像标签中进行标注, 例如 ruby:2.l-onbuild。ONBUILD 指令在创建专门用于自动编译、检查等操作的基础镜像时,十分有用 。
例如 ONBUILD RUN /usr/local/bin/python build --dir /app/src
STOPSIGNAL signal //定义基于此镜像创建的容器的退出信号
HEALTHCHECK [OPTIONS] CMD command //根据command的返回值是否为0来判断容器是否健康。如果禁止基础镜像的健康检查,使用:HEALTHCHECK NONE
SHELL [” executable ”,” parameters ”] //指定其他命令使用的shell类型, 默认值为 [ "/ bin/sh " ," -c " ]
操作指令:
RUN <command >或 RUN [ "executable " , ” param1 ” , ” param2 ” ] //运行命令。前者是shell; 后者是exec,不会启用shell环境。每条 RUN 指令将在当前镜像基础上执行指定命令,并提交为新的镜像层。
CMD [“executable ",” param1 ” , " param2 " ] //启动容器时默认执行的命令, exec形式
CMD command param1 param2 //默认shell形式。提供给需要交互的应用;
CMD[ ”param1 ”,” param2 " ] :提供给 ENTRYPOINT 的默认参数
注意: 每个 Dockerfile 只能有一条 CMD 命令 。 如果指定了多条命令,只有最后一条会被执行 。
如果用户启动容器时候手动指定了运行的命令(作为 ru口命令的参数),则会覆盖掉CMD 指定的命令 。
ADD <src> <dest> //添加内容到镜像的某个目录。src可以是url、文件、目录、tar,注意src支持通配符(例如 *.c)。 dest可以是绝对路径或相对WORKDIR的路径。
COPY <src> <dest> //复制内容到镜像,目标路径不存在时,会自动创建。当使用本地目录为源目录时,推荐使用 COPY,而不是ADD。
创建镜像:
docker build [OPTIONS] PATH | URL | - //该命令将读取指定路径下(包括子目录)的 Dockerrfile ,并将该路径下所有数据作为上下文( Context )发送给 Docker 服务端 。 Docker 服务端在校验 Dockerfile 格式通过后,逐条执行其中定义的指令,碰到 ADD 、 COPY 和 RUN 指令会生成一层新的镜像 。(个人理解:所以为了避免上下文过大,可以使用-f选项来指定Dockerfile路径)。 可以使用-t指定标签,-t可以多次使用。创建选项自行执行docker build --help查看。 可以通过 .dockerignore 文件(每一行添加一条匹配模式)来让 Docker忽略匹配路径或文件,在创建镜像时候不将无关数据发送到 服务端 。语法支持通配符
基础镜像: 基础镜像 比较特殊,其 Dockerfile 中往往不存在 FROM 指令,或者基于 scratch 镜像(FROM scratch ),这意味着其在整个镜像树中处于根的位置 。
定义一个基础镜像的例子:
FROM scratch
ADD binary / #提前编译好的二进制文件"binary"ADD到/
CMD [”/binary" ] #启动镜像的时候,执行这个二进制文件。
多步骤创建:
例如下面使用golang 1.9作为编译镜像编译main.go , 使用精简镜像alpine作为运行环境的镜像。
FROM golang : l.9 as builder # define stage name as builder
RUN mkdir -p /go/src/test
WORKDIR /go/src/test
COPY main.go .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/test/app . # copy file from the builder stage
from=builder /go/src/test/app . # copy file from the builder stage
CMD ["./app"]
建议:
提供注释和维护者信息: Dockerfile 也是一种代码,需要考虑方便后续的扩展和他人的使用;
正确使用版本号:使用明确的版本号信息,如 1.0 ' 2.0 ,而非依赖于默认的 latest。通过版本号可以避免环境不一致导致的问题;
减少镜像层数:如果希望所生成镜像的层数尽量少, 则要尽量合并RUN 、ADD和COPY指令 。通常情况下,多个RUN指令可以合并为一条RUN指令 ;
恰当使用多步骤创建:通过多步骤创建 ,可以将编译和运行等过程分开,保证最终生成的镜像只包括运行应用所需要的最小化环境 。
使用 .dockerignore文件: 使用它可以标记在执行docker build 时忽略的路径和文件,避免发送不必要的数据内容,从而加快整个镜像创建过程 。
及时删除临时文件和缓存文件:特别是在执行 apt -get 指 令后,/var/cache/apt 下面会缓存了一些安装包 ;
提高生成速度: 如合理使用cache , 减少内容目录下的文件,或使用.dockerignore文件指定等 ;
调整合理的指令顺序: 在开启cache的情况下,内容不变的指令尽量放在前面,这样可以尽量复用;
减少外部源的干扰:如果确实要从外部引人数据,需要指定持久的地址, 并带版本信息等,让他人可以复用而不出错 。
我自己测试Dockerfile的例子:
Dockerfile内容(给debian9.7增加密码登录的ssh-server,新增的用户为stone,密码为1234):
FROM debian:9.7 MAINTAINER zhdcok6 (zh[At]mintvotex.io) RUN sed -ri 's/(deb|security).debian.org/mirrors.tuna.tsinghua.edu.cn/' /etc/apt/sources.list ; \ apt -y update && apt -y install openssh-server && apt clean; \ mkdir /run/sshd ; useradd -l stone; printf "1234\n1234\n" |passwd stone; \ printf "toor\ntoor\n" |passwd root ENTRYPOINT /usr/sbin/sshd -D EXPOSE 22
cd到放Dockerfile目录下,宿主机执行build命令创建镜像:
docker build -t sshd:debian9.7 .
#执行shell命令 docker images //会看到了刚刚创建的镜像:sshd debian9.7 4178f22c95dd 2 minutes ago 207MB docker run -d -p 127.0.0.1:10022:22 sshd:debian9.7 ssh -p 10022 stone@localhost //输入密码1234即可登录, su - 输入密码toor即可切换到root
================================== 我自己写的加密socks5代理客户端 ===========================
# #PubKey: AAAAB3NzaC1yc2EAAAADAQABAAABAQDCg6vXqpvayt5s46pJd7hYyMGGrxGvbZmOWdrQ2fDg5jOVkEAPMrIRyWQLFDACikvEz63yZdPKBZDMfuix9WVVR6XFFREVz2rn70zV3cL5XPT2ZGLUNNutsKHGV+vgyxiQ3/9pyQyUPzWR0GDlJno5xoo+p50R859l1oMM0sxNp8JtwdcXgrpux6pTVwhgf9ft0sBfg7dxDD5A8OAeOtlXF7SpZ+W8IBbFdI2WQFhtZ8Kq9AZJpLTomEyarJ3tXPm/KxZqGmGZOJyh59gnmTtoCZRTp1mhZZgnOyZesPF1a62f8/9kc9FMxdSuxqzp4WX0F463aoFt1sziDiNbckTR # # 构建: docker build -t socks5_alpine . # 运行容器: docker run -e SUSER=zh -e SHOST=zhou.ddns.net -e SPORT=22 -p0.0.0.0:10080:1080 -d --rm --name sck5 socks5_alpine #这里的SPORT/SUSER/SHOST分别指远端主机ssh端口/用户/主机名; # 将上面的pubkey按照格式添加到服务器的authorized_keys文件中,重启sshd服务 # 设置浏览器的socks代理服务器为 localhost:10080, 浏览器测试ok # FROM alpine:3.9 MAINTAINER zhdcok6 (zh[At]xxxxx.io) ENV sdir="/root/.ssh" RUN sed -i 's|http://dl-cdn.alpinelinux.org|https://mirrors.aliyun.com|g' /etc/apk/repositories; apk update && \ { apk add --no-cache openssh-client && { rm -rf /var/cache/apk/* ; mkdir -m700 -p $sdir; \ printf "-----BEGIN RSA PRIVATE KEY-----\n\ MIIEpAIBAAKCAQEAwoOr16qb2srebOOqSXe4WMjBhq8Rr22Zjlna0Nnw4OYzlZBA\n\ DzKyEclkCxQwAopLxM+t8mXTygWQzH7osfVlVUelxRURFc9q5+9M1d3C+Vz09mRi\n\ 1DTbrbChxlfr4MsYkN//ackMlD81kdBg5SZ6OcaKPqedEfOfZdaDDNLMTafCbcHX\n\ F4K6bseqU1cIYH/X7dLAX4O3cQw+QPDgHjrZVxe0qWflvCAWxXSNlkBYbWfCqvQG\n\ SaS06JhMmqyd7Vz5vysWahphmTicoefYJ5k7aAmUU6dZoWWYJzsmXrDxdWutn/P/\n\ ZHPRTMXUrsas6eFl9BeOt2qBbdbM4g4jW3JE0QIDAQABAoIBAQCrAfnE/IBTJYHQ\n\ 94LRXkia/bxufWGt+kxDAypF7SVBhAEb35sCAY7d5lFnEBN5WD5uxCroba9579Sy\n\ hGxtcBHrnLbXgsLnitgxGohRicqNUrUmHXFpoSL1G9HOP6PnmIZ7cALr7M57Uur0\n\ y98z9tUEEFGf7dpAWw/rB2Fll7n4FhgCjhzqpvGroCOLRTy9gZpyfy7GeAvwaMPO\n\ SqT809mx3Owp+rPB/6/YJnb8vqDOoPhRURwJdrVglN61Ns53/EJQC2PDUK3mK0f+\n\ lJ7B5+Ez9SeGBC6mfMFotvrcBS8jzkPun6NLoRWE4PGRecTKlOtB1JJsRQR6/EJH\n\ ilp0venlAoGBAPPw69AnAOA8wqOEXFxAmNaqIw7N9oX10GX5Hy0Sswxy/1RWCkAk\n\ 01+YyXLxWGruwYdx+izlms7gvDocN+iBrMqSh68z9K+JX6JSiHeS2PqIS6ek9RcX\n\ wfHT7nylt0VdzabHDEwNwLUSHA7XFgHHeqDXOIfhOcmu1px8Da+DkCPPAoGBAMwh\n\ QO5li19d7E8Gf0KFeIo7f88LvQ2LFW/8k748NczNrCQ0v6+MpcLUXTqKXUlDFe+2\n\ 9YiINz3O1dwFUgpSKwbVdNpzLjv7XAb6YIx7N8lavDCIYUtPU2X26oZi5fUUY8hq\n\ 1TMfOtoNpK72hiIZA68zSsD4GAmKKylv27d56xVfAoGBAOX4wtdBbfn4TiaJqeju\n\ nSgCzXovgbFYxFbePR3o+xNJdpyzYIaIMR12lLPgA1MMMzbVpNyeuQs/ozPFVo/D\n\ cHqpGXF6sbqq75W/6ReRQS0vQOOTB9v1ccnh2nt4XwbuH+qSzG0Gqh4KLJlw/DZB\n\ MMJhI9I16pzQT1LHQL+ucDzRAoGAHlf7HPT/SMffbsfadvr8NiAuGYr3KWI5Z5I2\n\ LBsrLCyOoDsvG1te8J081ozm3RMZ2a5qxUbqX0e1xqUL0vjv6G4mlqp0fvoYbfke\n\ DQPsAQR54QUE4XsDPK79ochlwo6rXoly88x6pRtOFawTuFHbmFmZjSHUAOcHD3vP\n\ P3DiHyUCgYAUAoTv1YNPMJmdUl2VovLdugXwQHaq+t6rW8sbTJxwm3uqMRVGKVQo\n\ fciKDx6P8htyAS7aTenaWettvFKopaCIg0kAr/fBTEheBPkHWxE/bgqZWY913+Mt\n\ kub6t5quAGXReyrYtZcbscKVdJlCI90VrNfq0k8aZwPDGtR1rFrLCA==\n\ -----END RSA PRIVATE KEY-----\n" > $sdir/id_rsa; chmod 600 $sdir/id_rsa; };} ENTRYPOINT ssh -oStrictHostKeyChecking=no -Nf -D 0.0.0.0:1080 -p$SPORT $SUSER@$SHOST; while :;do sleep 3600;done EXPOSE 1080