Dockerfile 最佳实践

Dockerfile 最佳实践

1. 只添加需要的文件

1.1 使用 .dockerignore


temp?

!README.md

Dockerfile

1.2 用到什么就添加什么


FROM alpine

ADD app /bin/

RUN apk -Uuv add --no-cache ca-certificates tini tzdata && \

  ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \

  mkdir /kuu

WORKDIR /kuu

COPY kuu.json .

ADD docs ./docs

ADD assets ./assets

ENTRYPOINT ["/sbin/tini","--", "app"]

目的

  • 忽略多余的文件和目录,精简镜像体积。
  • 不必要的文件变动,不影响docker构建过程使用缓存。

2. 一个容器运行单一进程

原子性,环境独立。


gogs

gogs-db

3. 打上易读的镜像仓库名和标签

贴标签,方便快速知道它的用途。


gogs

gogs-db

4. 精简基础镜像

精简,体积小。 可靠,推荐试用官方镜像。alpine版本最好

Alpine Linux是一个独立的,非商业的通用Linux发行版,专为那些喜欢安全性,简单性和资源效率的高级用户而设计。(官网介绍)


FROM alpine

4.1 再精简一下

  • 比如使用 --no-install-recommends 参数告诉 apt-get 不要安装推荐的软件包

  • 安装完软件包,清 /var/lib/apt/list/ 缓存 (ubuntu)


RUN apt-get update && apt-get install -y \

    aufs-tools \

    automake \

    build-essential \

    curl \

    dpkg-sig \

    libcap-dev \

    libsqlite3-dev \

    mercurial \

    reprepro \

    ruby1.9.1 \

    ruby1.9.1-dev \

&& rm -rf /var/lib/apt/lists/*

  • alpine 中使用 --no-cache

FROM alpine

    ADD app /bin/

    RUN apk -Uuv add --no-cache ca-certificates tini tzdata

  • 删除中间文件:比如下载的压缩包

  • 删除临时文件:如果命令产生了临时文件,也要及时删除

5. 缓存问题

5.1 层级顺序

经常变化的内容和基本不会变化的内容要分开,把不怎么变化的内容放在上层,可以更好使用缓存


  FROM alpine

  ADD app /bin/

  RUN apk -Uuv add --no-cache ca-certificates tini tzdata

  Run ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

  Run mkdir /kuu

5.2 减少层级

一行RUN 就会生成一个镜像的缓存层, 使用换号符号 “\”。


  FROM alpine

  ADD app /bin/

  RUN apk -Uuv add --no-cache ca-certificates tini tzdata && \

    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \

    mkdir /kuu

5.3 解决5.2产生的可读性问题

尽量按字母排序


RUN apt-get update && apt-get install -y \

  bzr \

  cvs \

  git \

  mercurial \

  subversion

6. 挂载 VOLUME

包括数据库文件、代码库、配置文件……都应该使用 VOLUME 挂载

7. EXPOSE

  • Dockerfile 内不做映射外部端口, 保证镜像灵活性。

EXPOSE 80

  • 应该为应用程序使用通用的传统端口。 例如,包含Nginx服务器的映像将使用EXPOSE 80,而包含MongoDB的映像将使用EXPOSE 27017等。

8. 尽量使用明确版本

当镜像没有指定标签时,将默认使用latest 标签。当版本有大迭代升级,可能会导致镜像不可用。

FROM node:alpine

FROM node:carbon-alpine 或 FROM node:8-alpine

9. 利用好CMD与ENTRYPOINT

  • CMD

    The main purpose of a CMD is to provide defaults for an executing container.

CMD的作用在于执行容器时提供默认的命令操作

  • ENTRYPOINT

    An ENTRYPOINT allows you to configure a container that will run as an executable.

它可以让你的容器功能表现得像一个可执行程序一样

9.1 CMD


CMD echo "Hello world"   

执行docker run -it [image] 

但当后面加上 docker run -it [image] /bin/bash,CMD 会被忽略掉,命令 bash 将被执行:

root@10a32dc7d3d3:/#

9.2 ENTRYPOINT


ENTRYPOINT ["/bin/echo", "Hello"] 

docker run -it [image] 启动, 输出 :Hello 

docker run -it [image] World, 输出:Hello  World

参数化使用,可执行的程序

10. 添加HEALTHCHECK

    运行容器时,可以指定 --restart always 选项。这样的话,容器崩溃时,Docker守护进程(docker daemon)会重启容器。对于需要长时间运行的容器,这个选项非常有用。

但是,如果容器的确在运行,但是不可(陷入死循环,配置错误)用怎么办?使用HEALTHCHECK指令可以让Docker周期性的检查容器的健康状况。我们只需要指定一个命令,如果一切正常的话返回0,否则返回1。

11. 多阶段构建 (可以了解一下)

当编译阶段需要依赖特定系统环境,而运行时依赖少量库或包, 最终上传小镜像即可。(例如: c语言编辑环境)


from debian as build-essential

arg APT_MIRROR

run apt-get update

run apt-get install -y make gcc

workdir /src

from build-essential as foo

copy src1 .

run make

from build-essential as bar

copy src2 .

run make

from alpine

copy --from=foo bin1 .

copy --from=bar bin2 .

cmd ...

参考资料

https://mp.weixin.qq.com/s/wNCfYERWU3GOBHI2juTpmg

https://www.jianshu.com/p/9f15b81759bd

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

https://docs.docker.com/engine/reference/builder/#entrypoint

你可能感兴趣的:(Dockerfile 最佳实践)