Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Best practices for writing Dockerfiles for Node.js #48

Open
lqshow opened this issue Nov 10, 2018 · 0 comments
Open

Best practices for writing Dockerfiles for Node.js #48

lqshow opened this issue Nov 10, 2018 · 0 comments
Labels

Comments

@lqshow
Copy link
Owner

lqshow commented Nov 10, 2018

使用 .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

@lqshow lqshow added the docker label Nov 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant