lqshow / notes

Cheat Sheet
10 stars 2 forks source link

Best practices for writing Dockerfiles for Node.js #48

Open lqshow opened 5 years ago

lqshow commented 5 years ago

使用 .dockerignore 文件

排除上下文中构建用不到的目录和文件,语法同.gitignore

  1. 构建镜像时能够减少镜像大小
  2. 修改排除的文件,重新构建镜像时可忽略

通常 .dockerignore 文件应该是这样的

kubernetes
node_modules
npm-debug.log
dist
.git
.env

减少层数

Dockerfile中的每条指令都向 docker 镜像添加了一个额外的层。

指令和层的数量应该保持在最小,我们通过合并指令来减少层数。

# 错误写法
RUN yum install -y wget
RUN yum install -y net-tools

# 正确写法
RUN yum install -y wget net-tools

合理的选择 COPY 和 ADD 命令

  1. COPY只支持将本地文件复制到容器中
  2. ADD具有额外的功能(如仅限本地的tar提取和远程URL支持)

如果仅仅用于复制文件,请选择 COPY,简单更有效。 如果需要提取存档,需要使用 ADD。

# 比如将一个local 的包解压,通过 COPY 命令,执行如下,需要三步
# 这里用 COPY,其实是个错误的选择
RUN mkdir -p /usr/java
COPY resource/jdk1.8.0_77.tgz /usr/java/jdk1.8.0_77.tgz
RUN tar -zxvf /usr/java/jdk1.8.0_77.tgz -C /usr/java

# 用 ADD 命令,一步到位
ADD resource/jdk1.8.0_77.tgz /usr/java

使用 multi-stage 构建

生产环境下使用 alpine 进行多级构建,减少最终镜像文件的大小

Dockerfile 用于开发环境

使用卷将主机上的源代码映射到容器, 并使用 Nodemon 实现热更新

完整例子

ARG BUILD_IMAGE=lqshow/node:bigger
FROM ${BUILD_IMAGE} AS builder

# Add credentials on build
RUN mkdir -p /root/.ssh
COPY resource/id_rsa /root/.ssh/id_rsa
RUN chmod 600 /root/.ssh/id_rsa && \
      echo 'StrictHostKeyChecking no' >> /etc/ssh/ssh_config

# Create app directory
WORKDIR /data/project

# Install app dependencies
COPY package.json ./
RUN npm install --only=production && npm cache clean --force

# Remove SSH keys
RUN rm -rf /root/.ssh/ && rm -rf /data/project/resource/id_rsa

# Build a small image
FROM node:8.12.0-alpine
WORKDIR /data/project

# Copy our node_modules into our deployable container context.
COPY --from=builder /data/project/node_modules .

# Bundle app source
COPY ./ ./

# Launch App
CMD ["npm", "start"]
说明
  1. 先单独复制 package.json 并安装依赖,这个顺序非常重要。我们应该将最不频繁改动的放在 Dockerfile 的顶部,主要利用 Docker cache layer 的功能。

    平时开发人员频繁的修改代码,频繁的构建新镜像,这个小技巧能够大大缩短构建时间。

  2. npm install 加上 production,只安装 dependencies 模块,忽略 devDependencies 模块,这样能够减少镜像的大小

  3. 使用 npm cache clean --force 命令,清空npm缓存,能够减少镜像的大小

部署静态文件

ARG BUILD_IMAGE=node:8.12.0-alpine
FROM ${BUILD_IMAGE} as builder

# Create app directory
WORKDIR /data/project

# Install app dependencies
COPY package.json ./
RUN npm install

# Bundle app source
COPY ./ ./
RUN npm run build

# Build a small image
FROM alpine
WORKDIR /project/dist
COPY --from=builder /data/project/dist  ./
说明

在构建类似 React、Vue、Angular 的 App 时,通过多阶段构建,最终只需将静态文件做成一个镜像即可(这样最终生产的镜像会非常小,大概10M 都不到),然后在 kubernetes 中该镜像可以作为 sidecar 在 nginx docker 中来部署。详见:k8s 使用 Sidecar 容器设计模式来部署前端应用

References