使用Dockerfile创建image, 比使用container直接打包更灵活.
本文将介绍一下Dockerfile的用法, 使用Dockerfile建立image, 需要了解4部分的内容.
在docker库也可以找到很多Dockerfile的示例.
https://github.com/docker-library
使用docker inspect则可以查看image或container的内容, 里面有很多信息可以和制作image用到的Dockerfile对应.
1. 上下文目录
首先要创建上下文目录, 用于存放Dockerfile, .dockerignore, 以及要传到image中的文件.
2. 文件
在上下文目录中, 包含几类文件Dockerfile, .dockerignore, 以及要传到image中的文件.
2.1 Dockerfile即用来制作image的一些指令集合.
2.2 .dockerignore即用来忽略上下文目录中包含的一些image用不到的文件, 在.dockerignore中的文件或目录, 在制作image时, 不会传送到docker server.
2.3 要传输到docker server的文件和目录都放在上下文目录中, (例如使用ADD, COPY时, 源文件必须在上下文目录中)
3. Dockerfile 的语法
# Comment
INSTRUCTION arguments
注意第一条指令必须是FROM. 即基础镜像是哪个.
4. Dockerfile 指令集介绍
在Dockerfile文件中, 指令不区分大小写, 但是为了易读, 建议统一使用大写指令.
4.1 FROM
FROM <image>
Or
FROM <image>:<tag>
解释, 指定一个基础镜像, 用以制作本镜像. 如果image有多个tag, 但是未指定tag的话, 默认使用latest. (即最新的镜像)
例如,
FROM centos:centos6
4.2 MAINTAINER
MAINTAINER <name>
解释, 可用于告知该image的制作作者是谁.
例如,
MAINTAINER digoal@126.com
4.3 RUN
RUN has 2 forms:
RUN <command> (the command is run in a shell - /bin/sh -c - shell form)
RUN ["executable", "param1", "param2"] (exec form)
解释, 在building过程中执行的命令, 可以写多条, 有两个格式, 分别表示在shell环境中执行, 或者直接执行.
例如,
RUN yum install -y postgresql
RUN ["/bin/bash", "-c", "yum install -y postgresql"]
注意, 当环境中没有shell环境时, 使用第一种格式会有问题, 必须使用第二种格式, 或者没有/bin/sh但是有其他shell环境的话, 也必须使用第二种格式.
环境变量只有在shell 中被替换, 所以必须使用shell格式或在exec格式中使用shell, 例如 :
RUN [ "sh", "-c", "echo", "$HOME" ]
RUN echo $HOME
4.4 CMD
The CMD instruction has three forms:
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)
解释, CMD在Dockerfile中只需要使用一次, 如果写了多条, 那么只有最后一条生效. CMD不是在building时被调用的, 而是在docker run时自动调用的command, 并且会被docker run后面写的command覆盖. 可参考 :
http://blog.163.com/digoal@126/blog/static/163877040201410411715832/
CMD还可以和ENTRYPOINT结合使用, 当做ENTRYPOINT的传入参数.
例如,
FROM ubuntu
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]
4.5 EXPOSE
EXPOSE <port> [<port>...]
解释, 用于container inter connection, 参考http://blog.163.com/digoal@126/blog/static/163877040201492710339762/
指该image启动后的监听端口, 和-p或-P的功能不一样, EXPOSE仅仅用于container之间内部连接, 即自动创建端口对应的环境变量. 如果要将端口映射到宿主机还是需要使用-p或-P的.
4.6 ENV
ENV <key> <value>
解释, 用于设置环境变量, 我们可以使用docker inspect查看当前image设置的环境变量, 同时可以在运行时覆盖已经设置的环境变量, docker run --env <key>=<value>
4.7 ADD
ADD <src>... <dest>
解释, 用于将上下文目录中的文件或目录拷贝到image中, 同时还可以直接从URL下载文件并拷贝到image中, 注意, 如果文件是压缩文件的话(identity, gzip, bzip2 or xz), 会自动解压. 如果你不希望自动解压, 那么请使用COPY , 而不要使用ADD.
支持通配符.
例如,
ADD hom* /mydir/ # adds all files starting with "hom"
ADD hom?.txt /mydir/ # ? is replaced with any single character
4.8 COPY
COPY <src>... <dest>
解释, 与ADD略有不同(不解压, 不支持URL), 参考 :
http://blog.163.com/digoal@126/blog/static/163877040201410341236664/
例如,
4.9 ENTRYPOINT
ENTRYPOINT has two forms:
ENTRYPOINT ["executable", "param1", "param2"] (exec form, the preferred form)
ENTRYPOINT command param1 param2 (shell form)
解释, 在Dockerfile中只需要写一条ENTRYPOINT指令, 多条的话最后一条生效, 和CMD一样, 在run image的时候被调用, 在build image时不会调用. 但是与CMD略有不同, 不会被docker run的COMMAND部分覆盖, 参考 :
http://blog.163.com/digoal@126/blog/static/163877040201410411715832/
例如,
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
4.10 VOLUME
VOLUME ["/data"]
解释, 创建卷, 一般可用于存储数据库数据文件, 配置文件等container特定的文件.
例如,
VOLUME ["/data"]
4.11 USER
USER daemon
解释, 设置后续的RUN指令执行的用户.
例如,
RUN useradd postgres
USER postgres
RUN pg_ctl start
4.12 WORKDIR
WORKDIR /path/to/workdir
解释, 改变当前的工作目录, 因为RUN并不会改变工作目录, 所以要改变工作目录时, 可以使用 WORKDIR或者使用一行指令.
例如,
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
或者
RUN cd /a/b/c && pwd
返回/a/b/c
但是
RUN cd /a/b/c
RUN pwd
无法得到/a/b/c
4.13 ONBUILD
ONBUILD [INSTRUCTION]
解释, ONBUILD中的指令不会被触发, 而是在其他image使用该image时, 自动在FROM后面加上这些 ONBUILD后的指令, 如果这些指令执行失败的话, 以该image创建其他image的操作也会失败.
ONBUILD不会被继承, 即其他image使用该image创建的话, 不会继承该image的ONBUILD指令.
例如,
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
使用该image创建其他image时, 会自动在FROM后加上
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src
[参考]
1. https://docs.docker.com/reference/builder/
2. https://docs.docker.com/articles/dockerfile_best-practices/
3. https://github.com/docker-library