1-使用#注释

2-Dockerfile 主体内容分为四部分:基础镜像信息、 维护者信息、 镜像操作指令和容器启动时执行指令

 

简单示例:

FROM
# Maitainer: docker_user <docker_user_at_email.com>
LABEL
# Commands to update the image
RUN... 很多条RUN ....
# Commands when creating a new container
CMD

 

指令分配置指令和操作指令

配置指令:

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

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