Dockerfile(二)

2019-10-26  本文已影响0人  lconcise

学习Dockerfile

FROM

位于Dockerfile开头,表示基于什么镜像构建:

FROM scratch # 制作base image
FROM ubuntu:16.04 #使用ubuntu:16.04这个image

出于安全考虑,最好使用官方的image作为base image。

LABLE

Dockerfile的元数据,描述作用。

LABEL version="1.0" author="lconcise" description="dockerfile demo"

Dockerfile最好都要有元数据,这样更易于理解。

RUN

运行命令,每次run都会生成一个图层,所以最好将命令合并:

FROM ubuntu
RUN apt-get update \
    && apt-get install -y vim

\换行

WORKDIR

用于指定工作目录,切换路径:

FROM ubuntu
WORKDIR /test # 没有则自动创建test目录
WORKDIR demo
RUN pwd

输出 /test/demo。
最好不要用RUN cd来切换目录,而使用WORKDIR,这样可以减少不必要的图层,尽量使用绝对目录。

ADD & COPY

ADD 和COPY都可以将构建环境中的文件或目录复制到镜像中

比如

WORKDIR /demo
ADD test test/
WORKDIR /demo
COPY test test/

最终都会将test文件添加到/demo/test/目录下。
区别:

EVN

设置环境变量常量。

ENV MYSQL_VERSION 5.7
RUN apt-get install -y mysql-server="${MYSQL_VERSION}"

通过设定常量,可以提高可维护性。

VOLUME & EXPOSE

存储和网络,这里先略。

CMD

  • 设置容器启动后默认执行的命令和参数。
  • docker run指定了其他命令,CMD命令会被忽略。
  • 定义了多个CMD,只有最后一个有效。

比如有如下Dockerfile:

FROM ubuntu
ENV name lconcise
CMD echo "hello docker"
CMD echo "hello $name"

构建镜像,运行:

  docker run [image]

输出 hello lconcise。
如果运行:

docker run -it [image] /bin/bash

则没有输出。

ENTRYPOINT

  1. 设置容器启动时运行的命令。
  2. 不会被忽略,一定会执行。
  3. 一般写一个shell脚本作为ENTRYPOINT。

比如mongodb官方Dockerfile末尾一段:

COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 27017
CMD ["mongod"]

ENTRYPOINT和CMD结合使用有一个技巧:
比如有如下一个Dockerfile:

FROM ubuntu
ENTRYPOINT ["/bin/ls"]
CMD []

意思是在ubuntu这个镜像上构建,通过ENTRYPOINT运行/bin/ls命令,然后CMD []这行可以介绍额外的参数选项。
通过这个Dockerfile构建镜像后(image id为95c35bb00761),分别运行下面这些命令来创建容器:


image.png

可以看到我们通过相同的镜像构建出了不同的容器。

Shell 和 Exec 格式

在Dockerfile中,命令的写法有Shell格式和Exec格式:

Shell格式的Dockerfile如下:

RUN apt-get install -y vim
CMD echo "hello world"
ENTRYPOINTT echo "hello world"

Exec格式如下所示:

RUN ["apt-get","install","-y","vim"]
CMD ["/bin/echo","hello world"]
ENTRYPOINTT ["/bin/echo","hello world"]

在使用Exec格式的时候需要注意和常量的搭配使用问题,比如在Shell格式下:

FROM ubuntu
ENV name lconcise
ENTRYPOINTER echo "hello $name"

创建镜像,运行容器后输出:hello lconcise。
但是在Exec格式下:

FROM ubuntu
ENV name lconcise
ENTRYPOINTER ["/bin/echo","hello $name"]

创建镜像,运行容器后输出:hello $name。
正确的写法是:

FROM ubuntu
ENV name mrbird
ENTRYPOINTER ["/bin/bash","-c","echo hello $name"]

参考文档:
https://blog.fundebug.com/2017/05/15/write-excellent-dockerfile/
https://docs.docker.com/engine/reference/builder/
https://mrbird.cc/Dockerfile.html

上一篇下一篇

猜你喜欢

热点阅读